简介
- 在百度Apollo中gflag被广泛的应用在各种全局变量中,例如节点名,变量名,各种状态标志中。
- gflags 是google开源的一套
命令行参数解析
工具,比 getopt 功能更加强大,使用起来更加方便。 - 什么是
命令行参数解析工具
呢? 这里拿python做例子,例如:python test.py cmd1 cmd2
其中cmd1
和cmd2
就是命令行参数,gflags就是用来解析cmd1 cmd2 到程序中的。 - ps: 在cpp中命令行参数就是字符串
1. 安装 gflags
下载地址:git clone https://github.com/gflags/gflags.git
build和安装教程在INSTALL文件中有, 该教程支持pkg-config, CMake, 以及 Bazel.
1.1 cmake
如果gflags不是安装在默认路径下,则环境变量gflags_DIR
需要是 <prefix>/lib/cmake/gflags
该文件夹下需要是有 gflags-config.cmake
的文件。
如果gflags安装在默认路径下CMake 可以通过 find_package(gflags REQUIRED)
或者添加单线程静态库:
find_package(gflags COMPONENTS nothreads_static)
自动找到 gflags 。
添加dependency和execute
add_executable(foo main.cc)
target_link_libraries(foo gflags)
1.2 Bazel
在WORKSPACE
中添加以下语句
git_repository(
name = "com_github_gflags_gflags",
commit = "<INSERT COMMIT SHA HERE>",
remote = "https://github.com/gflags/gflags.git",
)
bind(
name = "gflags",
actual = "@com_github_gflags_gflags//:gflags",
)
bind(
name = "gflags_nothreads",
actual = "@com_github_gflags_gflags//:gflags_nothreads",
)
ps
gflags_nothreads
强制单线程
gflags
多线程
然后添加到BUILD
中:
cc_binary(
name = "foo",
srcs = ["main.cc"],
deps = ["//external:gflags"],
)
2. 使用 gflags
2.1. 首先需要#include "gflags.h"
#include <gflags/gflags.h>
2.2. 宏定义
将需要的命令行参数使用gflags的宏
来定义,例如:DEFINE_xxxxx(变量名,默认值,help-string) 定义在文件当中,注意:是全局的, 例如Apollo中的FLAGS_control_node_name
就是一个全局的一个string。gflags支持以下类型:
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
2.3. main函数添加
在main函数中开始的地方加入,以下这句话:
google::ParseCommandLineFlags(&argc, &argv, true);
//如果设为true,则该函数处理完成后,argv中只保留argv[0],argc会被设置为1。
//如果为false,则argv和argc会被保留,但是注意函数会调整argv中的顺序。
2.4 调用
在后续代码中使用FLAGS_变量名访问对应的命令行参数方法如下:
printf("%s", FLAGS_mystr);
2.5 测试
在编译成可执行文件之后,使用:./exe --参数1=值1 --参数2=值2 ...
来为这些命令行参数赋值。
./mycmd --var1="test" --var2=3.141592654 --var3=32767 --mybool1=true --mybool2 --nomybool3
3. gflags进阶使用
3.1. 在其他文件
中使用定义的flags变量
- 有些时候需要在main之外的文件使用定义的flags变量,这时候可以使用宏定义DECLARE_xxx(变量名)声明一下(就和c++中全局变量的使用是一样的,extern一下一样)
DECLARE_bool: boolean
DECLARE_int32: 32-bit integer
DECLARE_int64: 64-bit integer
DECLARE_uint64: unsigned 64-bit integer
DECLARE_double: double
DECLARE_string: C++ string
在对应的.h文件中进行DECLARE_xxx声明,需要使用的文件直接include就行了。
检验输入参数是否合法:gflags库支持定制自己的输入参数检查的函数,如下:
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");
static const bool port_dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort);
3.2 判断flags变量是否被用户使用
在gflags.h中,还定义了一些平常用不到的函数和结构体。这里举一个例子,判断参数port有没有被用户设定过
google::CommandLineFlagInfo info;
if(GetCommandLineFlagInfo("port" ,&info) && info.is_default) {
FLAGS_port = 27015;
}
3.3 定制你自己的help信息与version信息
- version信息:使用
google::SetVersionString
设定,使用google::VersionString
访问 - help信息:使用
google::SetUsageMessage
设定,使用google::ProgramUsage
访问 - 注意:
google::SetUsageMessage
和google::SetVersionString
这两个函数的调用必须
在google::ParseCommandLineFlags
之前执行