如何使用 Boost 的命令行和分层配置文件的选项 Program_Options
How to use options for both command line and hierarchical config file with Boost Program_Options
假设我有一个采用以下命令行选项的程序:
$ 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.
前缀。
所以我的问题是,如果您使用分层配置文件选项,您如何将它们与命令行选项相关联? IE。如何使 --foo
和 prog1.foo
在 Storage 对象中表示相同的配置值?
我已经学到了足够的知识来回答我自己的问题。希望有一天这会对某人有所帮助,因为 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" 来访问值 - 只需使用引用的存储变量。
假设我有一个采用以下命令行选项的程序:
$ 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.
前缀。
所以我的问题是,如果您使用分层配置文件选项,您如何将它们与命令行选项相关联? IE。如何使 --foo
和 prog1.foo
在 Storage 对象中表示相同的配置值?
我已经学到了足够的知识来回答我自己的问题。希望有一天这会对某人有所帮助,因为 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" 来访问值 - 只需使用引用的存储变量。