LINUX.ORG.RU

Кросс-платформенный разбор аргументов командной строки

 ,


2

4

Понадобилось разбирать аргументы командной строки на С++. Самое главное требование: чтобы можно было с минимумом усилий и зависимостей собирать на Linux, Windows и MacOS. Погуглил и понял, что в случае с С++ не все так просто, как в более современных ЯП, а именно есть такие варианты:

  1. Стародедовский копролит из POSIX, т.е. getopt. Минус: в стандартной поставке MS VC++ его, как я понял, нет, ибо unistd.h. Кто-то предлагает специально для оффтопика передирать часть unistd.h и соотв. функционала, но это звучит как исключительно красноглазый пердолинг;

  2. boost.program_options Минус: только ради этого добавлять зависимость от части boost…

  3. QCommandLineParser Минус: см. п.2), только в этом случае надо тащить часть Qt, что кажется еще большим оверкиллом;

  4. Какие-то костыли из рецептов «одной бабки» с SO. Минус: нет желания лепить самодельный велосипед на ровном месте, и еще надо понять, что код вообще рабочий, а не только лайкнут автором вопроса, который этот код запустил один раз и выбросил;

  5. Какие-то васянские библиотеки. Минус: см. п.4). Хоть качество (может быть) и выше, чем портянки с SO, все равно надо тянуть доп. зависимость, и тогда уж лучше взять boost как более качественную библиотеку.

Ничего не забыл? На сколько я понял, в С++20 этого тоже нет. Как-то грустно в 21-м веке, когда уже вот-вот скоро выйдет 6й по счету стандарт языка, не иметь такой фичи в стандартной библиотеке.

★★★★★

Грустно да. Что лично ты сделал что бы стало веселее? Конкурсы на лучшее предложение в стандарт на каждой затхлой конфе проводят уже кажется.

pon4ik ★★★★★
()

Нет его. Добро пожаловать в экосистему плюсов.

RazrFalcon ★★★★★
()

Какие-то васянские библиотеки. Минус: см. п.4). Хоть качество (может быть) и выше, чем портянки с SO, все равно надо тянуть доп. зависимость, и тогда уж лучше взять boost как более качественную библиотеку.

Я сишник, человек простой: тупо написал один раз свою васянскую библиотеку которая парсит argv, и потом всюду ее юзаю, дорабатывая в случае необходимости

SZT ★★★★★
()
Последнее исправление: SZT (всего исправлений: 1)

Некоторое время назад использовал https://github.com/catchorg/Clara

Но она приказала долго жить и вроде как теперь ее инкарнацией является https://github.com/bfgroup/Lyra

Еще если есть время полистайте новости на https://www.reddit.com/r/cpp Там иногда появляются анонсы новых библиотек подобного рода. Типа вот такого: https://www.reddit.com/r/cpp/comments/bg33h0/cpp_cli_a_robust_c11_command_line_parser/

eao197 ★★★★★
()

Boost в принципе можно давно считать приложением к стандартной библиотеке плюсцов, так что я бы взял его.

hateyoufeel ★★★★★
()
Ответ на: комментарий от RazrFalcon

Лучше пусть модули и ПМ осилят.

Хахахаха! Ты это серьёзно?

hateyoufeel ★★★★★
()

но это звучит как исключительно красноглазый пердолинг

Красноглазый? С MS VC++?
Берёшь MSYS2 и радуешься с костылём типа argv = CommandLineToArgv(GetCommandLine(), &argc), что в MinGW-w64 есть и getopt и getopt_long.

Darth_Revan ★★★★★
()

каждый настоящий мужчина сначала сам пишет такую либу, и только потом берется за собственную ОС %)

https://github.com/metawishmaster/libarg :)

// только я ее забывал обновлять, так что там только то, что получилост с первого раза, пардон муа...

metawishmaster ★★★★★
()

boost.program_options Минус: только ради этого добавлять зависимость от части boost…

Ты так говоришь, как будто это что-то плохое

не иметь такой фичи в стандартной библиотеке.

А какому стилю опций должна следовать библиотека: -o, –long-opt, -opt, /OPT, что там ещё? При стандартизации такой фичи обязательно вспомнят про z/OS или ещё какую экзотику.

Begemoth ★★★★★
()

покажите мне какой то другой язык в котором такое изобилие возможных библиотек + еще можно написать свою

anonymous
()

Стародедовский копролит из POSIX, т.е. getopt. Минус: в стандартной поставке MS VC++ его, как я понял, нет, ибо unistd.h.

Там одна короткая функция, реализация в гугле.

Как-то грустно в 21-м веке, когда уже вот-вот скоро выйдет 6й по счету стандарт языка, не иметь такой фичи в стандартной библиотеке.

POSIX давно есть, все вопросы к микрософту.

Serral
()

Если у тебя не ЯП на аргументах коммандной строки, то хватит и такого:

std::vector<std::string_view> positionals;
for (int i = 1; i < argc; ++i) {
  const std::string_view param = argv[i];
  if (param == "-h" || param == "--help") {
    printHelp();
    exit(0);
  } else if (param == "-a" || param == "--valueless") {
    setYourFrigginParam();
  } else if (param == "-b" || param == "--valued") {
    if (i == argc - 1)
      throw std::runtime_error("requires value");
    setYourFrigginValue(argv[++i]);
  } else if (param == "--") {
    for (int j = i + 1; j < argc; ++j)
      positionals.emplace_back(argv[j]);
    break;
  } else {
    positionals.emplace_back(param);
  }
}

А если тебе действительно надо ОС специализирующаяся на вытягивании параметров, то извольте тащить Boost/Qt/etc.

KennyMinigun ★★★★★
()
Последнее исправление: KennyMinigun (всего исправлений: 3)

Стародедовский копролит из POSIX, т.е. getopt. Минус: в стандартной поставке MS VC++ его

Но он есть в MinGW (включая getopt_long()), а MS VC++ проприетарщина и поэтому не нужно

Harald ★★★★★
()

В MS VC++ есть много того, чего нет в других компиляторах. Если STL не хватает для твоих задач, то опирайся на Posix

SR_team ★★★★★
()

Lyra, docopt

anonymous
()
Ответ на: комментарий от Harald

#pragma once, declspec, указание соглашения о вызовах не как в gcc/clang, накед-функции, годный inline-asm для x86, возможность создавать специализации шаблонных функций в классах, возможность кастовать функции к void* (хотя gcc тоже вроде позволяет)

SR_team ★★★★★
()
Ответ на: комментарий от RazrFalcon

А как же -v=value?

  1. KISS. Всегда можно найти случай, когда работать будет «не так». Вопрос: действительно ли стоит усилий поддержка такого случая. Мы ведь знаем, что для данного случая стоит всего лишь добавить проверку в стиле param.find('=') != npos чтоб поддерживать. Но, если можно обойтись --valued value, то зачем?

--valued --valueless будет криво разобрано?

--valued требует значения, и значение может тоже начинаться с --. Делать эвристику? См. п. 1.

KennyMinigun ★★★★★
()
Ответ на: комментарий от SR_team

#pragma once

Есть в gcc.

соглашения о вызовах

В MinGW

годный inline-asm для x86

GCC + ‘-masm=intel’

возможность кастовать функции к void*

Практически любой си-компилятор, кроме какой-нибудь экзотики для AVR.

LamerOk ★★★★★
()

Пробовал tclap. По сравнению с Boost больше понравилось API и авто-обработка --version/--help/-h.

xaizek ★★★★★
()

Минус: в стандартной поставке MS VC++ его, как я понял, нет, ибо unistd.h.

На этот случай предусмотрена условная компиляция. И это не велосипед!

anonymous
()

Ничего не забыл? На сколько я понял, в С++20 этого тоже нет. Как-то грустно

Чо как маленький-то? На флексе/бизоне уже запили :)

slackwarrior ★★★★★
()
Ответ на: комментарий от KennyMinigun

Ты вообще не понял.

Эквивалентные варианты на примере мускульдампа: "-x FOO", "-xFOO" для аргументов, значения у которых обязательны. Простым говноцикликом уже не обойтись.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Я за то, что есть надо сделать разбор агрументов, то незачем морочить себе мозги всеми вариантами. Берешь самый простой и чтоб работало. Бонусные пункты, если твой подход совместим с более-менее общепринятыми «нормами». Иначе – тащи либу.

Другими словами, зачем мне -xFOO если я то же самое могу сделать -x FOO?

KennyMinigun ★★★★★
()
Последнее исправление: KennyMinigun (всего исправлений: 1)

Всем спасибо за ответы. Буду думать на досуге.

seiken ★★★★★
() автор топика
Ответ на: комментарий от KennyMinigun

зачем мне -xFOO

Это и есть общепринятые «нормы»:

ping -c3 8.8.8.8

deep-purple ★★★★★
()
Ответ на: комментарий от RazrFalcon

ПМ осилят.

ПМ в С++:

  1. https://brew.sh/ (он же кроссплатформенный сейчас, можешь и под линуксом его запустить для зависимостей)

  2. https://mesonbuild.com/ , это не только сборочная система, но и пм, он использует по умолчания github, устанавливать пакеты типа такого:

meson wrap install nlohmann_json
  1. https://conan.io/

  2. https://spack.io/

  3. https://hunter.readthedocs.io/en/latest/

  4. https://buckaroo.pm/

  5. https://github.com/Microsoft/vcpkg/

  6. https://cget.readthedocs.io/en/latest/

8 пакетных менеджеров недостаточно? Это лишь кроссплатформенные, а ещё есть в каждом дистрибутиве и msys2 для Windows…

fsb4000 ★★★★★
()

радоваться надо что такого нет, ибо хоть где-то остаётся где можно попрограммировать именно создавая код, а не соединяя уже готовые решения между собой.

bonta ★★★★★
()

Я что-то не понял проблемы.

Заходишь на гитхаб, выбираешь проекты c++, ищешь “args”, “arguments” и т.д., на что хватит фантазии, сортируешь по звездочкам. В 99% процентов это будет header-only библиотека, кроссплатформенная, отлаженная сотнями людей, с удобным апи. Пробежался по коду глазами (не думаю, что там будет больше 1k строк) и юзай на свое удовольствие.

Смысл велосипедить свое? Задача скучная, работы другой много. Если только пет проджект для себя, но, имхо, есть куда более интересные вещи, чем в миллионный раз парсить аргуметы.

anonymous
()
Ответ на: комментарий от anonymous

Я лично юзаю https://github.com/CLIUtils/CLI11 . Особых проблем нет. Работает нормально и под онтопиком и под офтопиком, функционала хватает с головой.

anonymous
()
Ответ на: комментарий от LamerOk

В MinGW

А в GCC? ТСа ведь парит компиляция разными компиляторами, нативными для своих платформ, судя по хотелки MSVC++

GCC + ‘-masm=intel’

Вообще не то. Это просто переключение синтаксиса.

SR_team ★★★★★
()
Ответ на: комментарий от Harald

ненужные костыли

Без #pragma once жить можно, но штука удобнее, чем макросы

указание соглашения о вызовах не как в gcc/clang

Если по какой-то причине в коде это надо указать, то для MSVC++ оно будет указываться иначе, так что это все же проблема.

SR_team ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.