Как использовать параметры для командной строки и иерархического файла конфигурации с Boost Program_Options - PullRequest
0 голосов
/ 06 ноября 2019

Представьте, что у меня есть программа, которая использует следующую опцию командной строки:

$ prog1 --foo 1

У меня также есть файл конфигурации в этом иерархическом формате с fooпараметр в области действия prog1:

[prog1]
foo = 42

Насколько я понимаю, Boost :: program_options определяет, что параметр командной строки определяется следующим образом:

description.add_options()
    ("foo", "Set foo value");

Однако я хочу получить значениев файле конфигурации, чтобы быть значением по умолчанию (как результат вызова store() дважды, сначала с описанием командной строки, затем описанием файла конфигурации), который может быть переопределен параметром командной строки, но я считаю, чтоПараметр файла конфигурации должен быть объявлен как:

description.add_options()
    ("prog1.foo", "Set foo value");

Обратите внимание на использование prog1.foo здесь, особенно префикс prog1..

Поэтому мой вопрос, если вы используете иерархическую конфигурацию-file параметры, как вы связываете их с параметрами командной строки? Т.е. как сделать так, чтобы --foo и prog1.foo представляли одно и то же значение конфигурации в объекте Storage?

1 Ответ

0 голосов
/ 08 ноября 2019

Я выучил достаточно, чтобы ответить на свой вопрос. Надеемся, что однажды это кому-нибудь поможет, потому что документация Boost :: Program_Options не покрывает это.

Если вы создаете параметр иерархической конфигурации, подобный этому (это задокументировано ):

    config_only_opts.add_options()
        ("section.option", po::bool_switch(), "Some option");

И передать его как parse_command_line(), так и parse_config_file().

Тогда файл конфигурации будет выглядеть следующим образом:

[section]
option=1

И параметр командной строки будетвыглядеть следующим образом (это не задокументировано):

--section.option

Таким образом, иерархические параметры преобразуются в пунктирные параметры командной строки. Поэтому я ожидал бы, что:

[one.two]
three=4

будет эквивалентен следующей опции конфигурации:

--one.two.three=4

Значения по умолчанию, которые применяются к параметрам командной строки или файла конфигурации, применяются вв зависимости от порядка вызова store().

Если вы хотите связать произвольный параметр командной строки, например --foo, с иерархическим (или плоским) файлом конфигурациизначение, например bar.baz, тогда вы можете зарегистрировать первое с помощью parse_command_line(), а второе - с parse_config_file(), но для каждого из них укажите одинаковую переменную хранения:

    bool foo;

    po::options_description cmdline_opts;
    cmdline_only_opts.add_options()
        ("foo", po::value<bool>(&foo), "Foo")
        ;

    po::options_description config_file_opts;
    config_only_opts.add_options()
        ("bar.baz", po::value<bool>(&foo))
        ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, cmdline_opts), vm);
    po::store(po::parse_config_file("config.file", config_file_opts, true /* allow unregistered */), vm);
    po::notify(vm);

Теперь выможно использовать --foo или

[bar]
baz=X

для установки переменной foo. Единственное предостережение, о котором следует быть осторожным, это то, что вы больше не можете использовать vm[XXX].as<T>(), где «XXX» - это «foo» или «bar.baz» для доступа к значению - просто используйте вместо этого указанную переменную хранилища.

...