简介
gflags是什么?gflags是google开源的命令行标记处理库;
那么什么是命令行标记呢?顾名思义就是当运行一个可执行文件时,由用户为其指定的标记,形如:
fgrep -l -f ./test ccc jjj
注意上述命令,-l与-f ./test是命令行标记,而ccc与jjj是命令行参数,因为这两者不是以破折号开头的。
一般的一个可执行文件,允许用户为其传入命令行标记以及参数,如上述例子,-l是一个不带参数的标记,-f是一个带了参数“./test”的标记,而gflags可以解析这些标记以及参数并将其存储在某些数据结构中。
gflags不像getopt()那样,gflags的flags可以分散到各个源文件而不是只在一个地方,也就是说只要是和定义了指定flags的源文件链接的其他文件都可以使用这个flags,这是灵活而又强大的,但这也是危险的,如果两个文件定义的flags一样,那么当它们链接在一起的时候将会出错。
下载与安装(ubuntu环境)
gflags官方github链接,克隆代码:
git clone https://github.com/gflags/gflags.git gflags_stable
安装二进制发布包:
sudo apt-get install libgflags-dev
安装cmake:
sudo apt-get install cmake-curses-gui
cd到代码根目录,即gflags_stable目录,执行如下命令:
mkdir build && cd build
ccmake ..
# 在cmake界面一路按‘c’直到可以按‘g’
make
sudo make install
安装成功后会提示如下信息:
[ 50%] Built target gflags_static
[100%] Built target gflags_nothreads_static
Install the project...
-- Install configuration: "Release"
-- Installing: /usr/local/lib/libgflags.a
-- Installing: /usr/local/lib/libgflags_nothreads.a
-- Installing: /usr/local/include/gflags/gflags.h
-- Installing: /usr/local/include/gflags/gflags_declare.h
-- Installing: /usr/local/include/gflags/gflags_completions.h
-- Installing: /usr/local/include/gflags/gflags_gflags.h
-- Installing: /usr/local/lib/cmake/gflags/gflags-config.cmake
-- Installing: /usr/local/lib/cmake/gflags/gflags-config-version.cmake
-- Installing: /usr/local/lib/cmake/gflags/gflags-targets.cmake
-- Installing: /usr/local/lib/cmake/gflags/gflags-targets-release.cmake
-- Installing: /usr/local/lib/cmake/gflags/gflags-nonamespace-targets.cmake
-- Installing: /usr/local/lib/cmake/gflags/gflags-nonamespace-targets-release.cmake
-- Installing: /usr/local/bin/gflags_completions.sh
-- Installing: /usr/local/lib/pkgconfig/gflags.pc
-- Installing: /home/caojingsong/.cmake/packages/gflags/e5f7ce61772240490d3164df06f58ce9
编译代码时需要连同gflags的静态库一同编译
g++ demo.cpp /usr/local/lib/libgflags.a -lpthread
使用
在程序中定义flag
#include <gflags/gflags.h> // 头文件必须得加啊啊啊啊啊
DEFINE_bool(is_handsome, true, "Is the author a handsome guy");
DEFINE_string(hobby, "eat, drink, sleep",
"comma-separated list of hobby to offer in the 'hobby' menu");
如上,DEFINE有三个宏,其意义分别为:flag的名称,flag的默认值,help字符串。如何查看help信息呢,在执行可执行文件时加上–help选项即可,但是如果要显示help信息,代码里需要调用接口gflags::ParseCommandLineFlags(&argc, &argv, true)才行。
gflags支持的变量类型如下:
- DEFINE_bool: 布尔类型
- DEFINE_int32: 32-bit 整型
- DEFINE_int64: 64-bit 整型
- DEFINE_uint64: 无符号 64-bit 整型
- DEFINE_double: double
- DEFINE_string: C++ string
在程序中使用flag
对于DEFINE过的flag我们可以像使用普通变量那样读写它,只需加一个“FLAGS_”前缀即可,如下:
if (FLAGS_is_handsome)
FLAGS_is_handsome = false;
std::cout << FLAGS_hobby << std::endl;
在其他文件中使用flag
形如上述例子,我们在一个源文件中使用flag方式是先“DEFINE_”然后“FLAGS_”使用即可,但如果想在其他文件访问这个flag呢?举个例子,我们上述flag定义在hello.cpp,而我们要在bye.cpp中使用它,那么我们只需在bye.cpp中做如下声明:
DECLARE_bool(is_handsome);
DECLARE_string(hobby);
上述DECLARE作用等同于extern.
注册flag验证器
当我们DEFINE一个flag时,可以为其注册一个Validator,如下:
static bool ValidatePort(const char* flagname, int32 value) {
if (value > 0 && value < 32768) // value is ok
return true;
printf("Invalid value for --%s: %d\n", flagname, (int)value);
return false;
}
DEFINE_int32(port, 0, "What port to listen on");
DEFINE_validator(port, &ValidatePort);
上述DEFINE_validator宏将会调用RegisterFlagValidator()函数,成功返回true,失败返回false,失败的原因可能为:1、第一个参数不是flag;2、该flag被不同的validator注册。返回值作为全局静态布尔变量是可以被访问的,格式为:
<flag>_validator_registered
设置flag
我们可以通过给可执行文件传输命令行参数来修改flag的默认值,只需要在main函数开头,调用如下函数:
gflags::ParseCommandLineFlags(&argc, &argv, true);
上述参数的最后一个参数是"remove_flag",如果为true该函数将会从argv中移除flag并修改argc为相应的值,如此下来,argv只保留命令行参数,而不再有命令行标记
如果remove_flag为false,那么该函数将会重新排列argv。
具体命令行传参格式如下:
a.out --nois_handsome -hobby="play football"
当运行ParseCommandLineFlags时,将会设置FLAGS_is_handsome为false,
FLAGS_hobby 为"play football",注意上述布尔类型变量通过在名字前加no将其设置为false。
对于hobby标记还有如下指定方式:
a.out --hobby="play football"
a.out -hobby="play football"
a.out --hobby "play football"
a.out -hobby "play football"
对于布尔变量有下述几种设置方式:
a.out --is_handsome
a.out --nois_handsome
a.out --is_handsome=true
a.out --is_handsome=false
不过为了使自己的程序易于理解可读,
建议非布尔flag使用这种形式:–variable=value
布尔flag使用这种形式:–variable/–novariable
API
gflags提供了一些有用的API如:gflags::SetUsageMessage() 和gflags::SetVersionString更多信息请参考gflags.h头文件
最后一点
出于一些安全原因或者想要减小可执行文件大小,我们可以去掉自己定义的flag的help信息,如下:
#define STRIP_FLAG_HELP 1 // this must go before the #include!
#include <gflags/gflags.h>
参考文献
以上内容均参考自该文章:https://gflags.github.io/gflags/