gflags使用
参考资料:
gitHub
官方使用文档
Gflags简明教程 http://dreamrunner.org/blog/2014/03/09/gflags-jian-ming-shi-yong/
GFlags使用文档 http://www.yeolar.com/note/2014/12/14/gflags/
简介
GFlags是Google开源的一套命令行参数处理的开源库,包括C++的版本和python 版本。
和 getopt() 之类的库不同,flag的定义可以散布在各个源码中,而不用放在一起。一个源码文件可以定义一些它自己的flag,链接了该文件的应用都能使用这些flag。这样就能非常方便地复用代码。如果不同的文件定义了相同的flag,链接时会报错。
在程序中定义Flags
定义一个flag是简单的:只需要使用你想用的类型的相应的宏就可以。
example:
// foo.cc #include <gflags/glags.h> DEFINE_bool(big_menu, true, "Include 'advanced' options in the menu listing"); DEFINE_string(languages, "english,french,german", "comma-separated list of languages to offer in the 'lang' menu");
支持的类型:
- DEFINE_bool: boolean
- DEFINE_int32: 32-bit integer
- DEFINE_int64: 64-bit integer
- DEFINE_uint64: unsigned 64-bit integer
- DEFINE_double: double
- DEFINE_string: C++ string
DEFINE宏包含三个参数:flag名、默认值、描述方法的帮助。帮助会在执行 --help flag时显示。
可以在任何源文件中定义flag,但是每个只能定义一次。如果需要在多处使用,那么在一个文件中 DEFINE ,在其他文件中 DECLARE 。比较好的方法是在 .cc 文件中 DEFINE ,在 .h 文件中 DECLARE ,这样包含头文件即可使用flag了。
使用flag
定义的flag可以像正常的变量一样使用,只需在前面加上 FLAGS_
前缀。如前面例子中的定义了 FLAGS_big_menu
和 FLAGS_languages
两个变量。可以像一般变量一样读写:
if (FLAGS_consider_made_up_languages) FLAGS_languages += ",klingon"; // implied by --consider_made_up_languages if (FLAGS_languages.find("finnish") != string::npos) HandleFinnish();
初始化所有参数
定义好参数后,最后要告诉执行程序去处理命令行传入的参数,使得定义的FLAG参数得到正确赋值。
通常是在main()
函数中调用
google::ParseCommandLineFlags(&argc, &argv, true);
argc
和argv
就是 main
的入口参数,因为这个函数会改变他们的值,所以都是以指针传入。第三个参数被称为
remove_flags
。如果它是true,ParseCommandLineFlags
会从argv
中移除标识和它们的参数,相应减少argc
的值。然后argv
只保留命令行参数。相反,
remove_flags
是false,ParseCommandLineFlags
会保留argc
不变,但将会重新调整它们的顺序,使得标识再前面。Note:
./foo --big_menu=false arg1
中再big_menu
是标识,false
是它的参数,arg1
是命令行参数。设置命令行flag
一般使用flag的原因是为了能在命令行指定一个非默认值。以 foo.cc 为例,可能的用法是:
app_containing_foo --nobig_menu -languages="chinese,japanese,korean" ...
执行 ParseCommandLineFlags 会设置 FLAGS_big_menu = false , FLAGS_languages = "chinese,japanese,korean" 。
注意这种在名字前面加“no”的设置布尔flag为false的语法。
设置“languages”flag的方法有:
app_containing_foo --languages="chinese,japanese,korean" app_containing_foo -languages="chinese,japanese,korean" app_containing_foo --languages "chinese,japanese,korean" app_containing_foo -languages "chinese,japanese,korean"
布尔flag稍有不同:
app_containing_foo --big_menu app_containing_foo --nobig_menu app_containing_foo --big_menu=true app_containing_foo --big_menu=false 还包括以上这些的单短线的变种
建议只使用一种形式:非布尔flag, --variable=value ;布尔flag, --variable/--novariable 。保持一致性有一定的好处。
在命令行使用未定义的flag会在执行时失败。如果需要允许未定义的flag,可以使用 --undefok 来去掉报错。
和 getopt() 一样, -- 可以用于结束flag。
重复指定flag使用最后的一个。
不支持单字母的形式的flag,也不支持单短线后的flag合并,像 ls -la 那样。
特殊flag
GFlags中默认定义了一些flag。有三类,第一类是“报告”flag,用于打印一些信息然后退出。
--help | 显示所有文件的所有flag,按文件、名称排序,显示flag名、默认值和帮助 |
--helpfull | 和 --help 相同,显示全部flag |
--helpshort | 只显示执行文件中包含的flag,通常是 main() 所在文件 |
--helpxml | 类似 --help,但输出为xml |
--helpon=FILE | 只显示定义在 FILE.* 中得flag |
--helpmatch=S | 只显示定义在 *S*.* 中的flag |
--helppackage | 显示和 main() 在相同目录的文件中的flag |
--version | 打印执行文件的版本信息 |
第二类是可以影响其他flag的。
--undefok=flagname,flagname,... --undefok 后面列出的flag名,可以在无定义的情况下忽略而不报错
第三类是“递归”flag,可以用来设置其他flag: --fromenv, --tryfromenv, --flagfile 。
--fromenv
--fromenv=foo,bar 表示从环境变量中读取 foo 和 bar flag。需要在环境中预先设置对应的值:
export FLAGS_foo=xxx; export FLAGS_bar=yyy # sh
setenv FLAGS_foo xxx; setenv FLAGS_bar yyy # tcsh
等价于在命令行指定 --foo=xxx --bar=yyy 。
如果在应用中没有定义 foo ,或者环境变量中没有定义 FLAGS_foo ,使用 --fromenv=foo 会导致失败。
--tryfromenv
--tryfromenv 和 --fromenv 类似,区别是在环境变量中没有定义 FLAGS_foo 时, --tryfromenv=foo 不会导致失败,这时会使用定义时指定的默认值。但是应用中没有定义 foo 仍会导致失败。
--flagfile
--flagfile=f 表示从文件 f 中读取flag。
对于简单形式,文件 f 中每行一个flag。在flagfile文件中flag需要使用等号。如:
# /tmp/myflags --nobig_menus --languages=english,french
以下两种方式是等价的:
./myapp --foo --nobig_menus --languages=english,french --bar ./myapp --foo --flagfile=/tmp/myflags --bar
注意在flagfile中很多类型的错误会被忽略掉,比如不能识别的flag,没有指定值的flag。
一般形式的flagfile要复杂一些。写成一组文件名,每行一个,后面加上一组flag,每行一个的形式,可以有多组。文件名可以使用通配符( * 和 ? ),只有当前可执行模块名和其中一个文件名匹配时才会处理文件名后的flag。flagfile可以直接以一组flag开始,这时这些flag对应到当前可执行模块。
以 # 开头的行作为注释被忽略,前导空白和空行也都会被忽略。
flagfile中还可以使用 --flagfile flag来包含另一个flagfile。
flag会按顺序执行。从命令行开始,遇到flagfile时,执行文件,执行完再继续命令行中后面的flag。