Google命令行解析gflags
一、简介
gflags是Google的一个命令行参数处理的开源库,使用C++开发,具备Python接口,可以替代getopt。gflags支持从环境变量、配置文件读取参数。gflags使用起来比getopt方便,但是不支持参数缩写(例如getopt支持--list缩写成-l,gflags不支持)。
gflags不支持列表,用户可通过借助string参数实现:可看作以逗号分隔的参数列表:
DEFINE_string(languages, “english, french, german, chinese", “comma-separated list of languages to offer in the ‘lang’ menu”);
二、源码获取
可以访问官网下载安装最新版本gflags:
https://code.google.com/p/gflags/
也可以上github获取(对于国内访问更加方便):
https://github.com/gflags/gflags
安装使用过程如下(摘自INSTALL.md):
- 获取并解压源码;
- 创建build目录并进入该目录;
- 运行cmake配置构建树;
- 使用编译工具编译源码;
- 验证编译后的库;
- 安装并使用。
如源码目录下INSTALL.md所述:
Compiling the source code with CMake
=========================
The build system of gflags is since version 2.1 based on [CMake](http://cmake.org).
The common steps to build, test, and install software are therefore:
1. Extract source files.
2. Create build directory and change to it.
3. Run CMake to configure the build tree.
4. Build the software using selected build tool.
5. Test the built software.
6. Install the built files.
On Unix-like systems with GNU Make as build tool, these build steps can be
summarized by the following sequence of commands executed in a shell,
where ```$package``` and ```$version``` are shell variables which represent
the name of this package and the obtained version of the software.
$ tar xzf gflags-$version-source.tar.gz
$ cd gflags-$version
$ mkdir build && cd build
$ ccmake ..
- Press 'c' to configure the build system and 'e' to ignore warnings.
- Set CMAKE_INSTALL_PREFIX and other CMake variables and options.
- Continue pressing 'c' until the option 'g' is available.
- Then press 'g' to generate the configuration files for GNU Make.
$ make
$ make test (optional)
$ make install (optional)
编译的时候,可以使用ccmake来可视化的修改编译选项和工具,也可以通过cmake –D的方式指定编译选项。常见可用的编译选项如下:
CMake Option | Description |
---|---|
CMAKE_INSTALL_PREFIX | Installation directory, e.g., "/usr/local" on Unix and "C:\Program Files\gflags" on Windows. |
BUILD_SHARED_LIBS | Request build of dynamic link libraries. |
BUILD_STATIC_LIBS | Request build of static link libraries. Implied if BUILD_SHARED_LIBS is OFF. |
BUILD_PACKAGING | Enable binary package generation using CPack. |
BUILD_TESTING | Build tests for execution by CTest. |
BUILD_NC_TESTS | Request inclusion of negative compilation tests (requires Python). |
BUILD_CONFIG_TESTS | Request inclusion of package configuration tests (requires Python). |
BUILD_gflags_LIBS | Request build of multi-threaded gflags libraries (if threading library found). |
BUILD_gflags_nothreads_LIBS | Request build of single-threaded gflags libraries. |
GFLAGS_NAMESPACE | Name of the C++ namespace to be used by the gflags library. Note that the public source header files are installed in a subdirectory named after this namespace. To maintain backwards compatibility with th |
e Google Commandline Flags, set this variable to "google". The default is "gflags".
GFLAGS_INTTYPES_FORMAT | String identifying format of built-in integer types.
GFLAGS_INCLUDE_DIR | Name of headers installation directory relative to CMAKE_INSTALL_PREFIX.
LIBRARY_INSTALL_DIR | Name of library installation directory relative to CMAKE_INSTALL_PREFIX.
INSTALL_HEADERS | Request installation of public header files.
三、使用方法
3.1 包含头文件
在使用的源代码中,包含如下头文件:
#include <gflags/gflags.h>
3.2 参数定义
将需要使用的命令行参数使用gflags的如下宏定义的形式全局定义在文档中,注意是全局域:
DEFINE_type(变量名, 默认值, help-string)
gflags支持如下类型(如上type部分):
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
比如分别定义了一个bool和一个string类型的参数:
DEFINE_bool(big_menu, true, “Include ‘advanced’ options in the menu listing”);
DEFINE_string(languages, “english, french, german, chinese", “comma-separated list of languages to offer in the ‘lang’ menu”);
gflags不支持列表,用户可通过借助string参数实现,比如上面的languages参数,可以看作是以逗号分割的参数列表。
3.3 参数声明
当我们需要在其他文件中使用命令行定义的flags变量时,可以使用gflags的如下宏定义声明一下(就和C++中全局变量使用extern声明一样):
DELCARE_type(变量名)
type部分与前面gflags支持的类型对应。推荐在对应的*.h文件中进行DECLARE_type声明,需要使用的文件直接include即可。
3.4 参数解析
参数解析,也叫参数初始化。在main函数头几行加入如下语句(越早了解用户需求越好么):
google::ParseCommandLineFlags(&argc, &argv, true);
argc和argv就是main主函数传入的参数,想必大家都很了解。第三个参数表示是否释放argv以节约内存:
- 如果为true,则该函数处理完成后,argv中只保留argv[0]程序名,argc会被设置为1;
- 如果为false,则argv和argc都会被保留,但解析函数会调整argv中的顺序;
第三个参数的真正含义是remove_flag:如果为true,则gflags会移除parse过的参数,否则gflags就会保留这些参数,但可能会对参数顺序进行调整。
3.5 参数访问
当参数被定义后,在程序中就可以通过FLAGS_name的形式访问对应的flags参数了。FLAGS_是固定的前缀,name为宏定义中使用的名字。比如前面定义的两个参数:
printf(“big_menu=%d\n”, FLAGS_big_menu);
if(FLAGS_languages.find(“english”) != string::npos)
HandleEnglish();
3.6 参数检查
gflags库支持定制自己的输入参数范围检查函数,使用方法如下:
static bool ValidatePort(const char *flagname, int32 value)
{
if(value > 0 && value < 32768)
return true;
printf(“Invalid value for --%s:%d\n”, flagname, (int) value);
return false;
}
DEFINE_int32(port, 0, “What port to listen on”);
static const bool port_dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort);
建议在参数定义之后,立即注册检查函数。RegisterFlagValidator()在检查函数注册成功时返回true;如果参数已经注册了检查函数,或者检查函数类型不匹配,返回false。
3.7 参数传递——命令行
最后,将源码编译成可执行文件之后(编译的时候指定-lgflags),可以使用如下形式来使用命令行参数对flags变量赋值:
executable --参数1=值1 --参数2=值2 . . .
其中的‘=’也可以使用空格‘ ’代替。如果flags变量类型为bool,那么除了使用--xxx=true/false的形式外,还可以使用--xxx和--noxxx后面不加等号的方式指定true和false。比如:
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"
app_containing_foo --big_menu
app_containing_foo --nobig_menu
app_containing_foo --big_menu=true
app_containing_foo --big_menu=false
app_containing_foo --big_menu true
app_containing_foo --big_menu false
==使用--nodefok参数==,可直指定当命令行中出现没有定义的参数时,并不退出(error-exit)。
3.8 参数传递——配置文件
如果参数比较多,那么在执行程序的时候,会显得非常的冗余。可以==使用--flagfile==来指定从文件中读取参数值。比如--flagfile=my.conf表明要从my.conf文件读取参数的值。
在配置文件中指定参数值与在命令行方式类似,另外在flagfile里可进一步通过--flagfile来包含其他的文件。
3.9 参数传递——环境变量
如果我们想让程序直接从环境变量中读取参数值,可以==使用--formenv==来指定。比如:--fromenv=foo,bar表明要从环境变量读取foo,bar两个参数的值。
通过export FLAGS_foo=xxx; export FLAGS_bar=yyy程序就可读到foo,bar的值分别为xxx,yyy。
==参数--tryfromenv==与--fromenv类似,当参数的没有在环境变量定义时,不退出(fatal-exit)。
四、高阶用法
4.1 添加自己的help信息
可以使用google::SetUsageMessage来设定帮助信息。然后在程序中可以使用google::ProgramUsage访问帮助信息,也可在程序外(命令行)通过--help来获取。
【注意】:google::SetUsageMessage必须在google::ParseCommandLineFlags之前执行。
添加自己的version信息
可以使用google::SetVersionString来设定版本信息。然后在程序中可以使用google::VersionString来访问,在程序外(命令行)可以通过--version参数来获取。
【注意】:google:: SetVersionString必须在google::ParseCommandLineFlags之前执行。