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):

  1. 获取并解压源码;
  2. 创建build目录并进入该目录;
  3. 运行cmake配置构建树;
  4. 使用编译工具编译源码;
  5. 验证编译后的库;
  6. 安装并使用。

如源码目录下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之前执行。

想了解更多有关嵌入式Linux驱动、应用、常用开源库、框架、模式、重构等相关相关的主题内容,请长安下面图片,关注我的公众号(只有技术干货分享,不拉稀摆带!)。

image

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容