从编译到运行,轻松学会gflags库
导读:秋招时,会经常问你有没有使用过一些开源的工具库,这期来介绍下
gflags
。
gflags
是Google开源的一个库,可以很方便地定义一些全局变量,并且可以从命令行设置他们的值,广泛应用于各个项目中以及自己平时的开发中。本期参考gflags的官方文档,简单直接介绍下怎么使用这个库。
构建依赖环境
在具体介绍怎么使用gflags
库之前,先说下怎么基于CMakeLists.txt
来构建依赖环境,方便大家跟着这期博文一起上手体验。
首先需要将gflags
从github下载下来:
$ git clone git@github.com:gflags/gflags.git
此时,我的目录结构如下:
$ tree -L 2 . └── demo ├── CMakeLists.txt ├── build # 目前是空的,用于后面编译输出 ├── gflags # 上面clone下来的代码 └── main.cc # 目前是空的
其中,demo/CmakeLists.txt
的构建代码如下:
cmake_minimum_required(VERSION 2.8.12) project(gflags_demo) add_subdirectory(gflags) # 添加子目录 add_executable(main main.cc) # 生成目标文件 main target_link_libraries(main gflags::gflags) # 链接到 gflags库
经过上述步骤,我们就可以在main.cc
文件中,写gflags
的demo了啦啦啦。
- 更好阅读体验,点击:必先利其器 (4) | 从编译到运行,轻松学会gflags库
- 更多硬核知识,点击并关注: look_code_art,精彩等你发现
tutorials
gflags
定义的是全局变量,目前支持以下7种基本类型:
DEFINE_bool
:bool
类型DEFINE_int32
:int32_t
整数类型DEFINE_int64
:int64_t
整数类型DEFINE_uint32
:uint32_t
整数类型DEFINE_uint64
:uint64_t
整数类型DEFINE_double
:double
浮点数类型DEFINE_string
: STL的std::string
类型
上述的DEFINE_XXX
函数,本质上是宏,接口类型一致:DEFINE_XXX(name, val, txt)
:
name
:变量名val
:变量的默认值txt
:这个变量的提示信息,在使用--help
时会显示出来
下面通过一个简单的demo来介绍gflags
的使用。
在下面的demo中,使用DEFINE_XXX
函数定义了三个类型都全局变量:
#include <gflags/gflags.h> #include <iostream> DEFINE_bool(big_menu, true, "Include 'advance' option in the menu listing"); DEFINE_string(languages, "english, french, chinese", "comma-separated list of languages to offer in the 'lang' menu"); DEFINE_uint32(age, 10, "age");
那怎么在程序中使用他们呢?
在程序中使用DEFINE_XXX
函数定义的变量时,需要在每个变量前加上FLAGS_
前缀。
比如,下面输出三个变量的默认值:
int main(int argc, char** argv) { std::cout<<std::boolalpha; // 为了让bool类型输出true/false,而不是 1/0 std::cout<<"big_menu: "<<FLAGS_big_menu<<'\n' <<"languages: "<<FLAGS_languages<<'\n' <<"age: "<<FLAGS_age<<std::endl; return 0; }
编译运行:
$ cd build && cmake .. && make # 进入 demo/build 目录,再编译 $./main big_menu: true languages: english, french, chinese age: 10
从结果可以看出,输出的就是DEFINE_XXX
函数中设置的默认值。
那这些变量的值,怎么通过命令行设置?
只需要在main
函数后,添加::gflags::ParseCommandLineFlags
函数,就能解析命令行,即解析argc
、argv
参数。
int main(int argc, char** argv) { ::gflags::ParseCommandLineFlags(&argc, &argv, true); std::cout<<std::boolalpha; std::cout<<"big_menu: "<<FLAGS_big_menu<<'\n' <<"languages: "<<FLAGS_languages<<'\n' <<"age: "<<FLAGS_age<<std::endl; return 0; }
此时,重新编译运行:
$ make $ ./main -age 100 -languages "123456" big_menu: true languages: 123456 age: 100
对于命令行输入格式,gflags
提供了四种格式,以age
变量为例:
./main -age 100
./main -ag=100
./main --age 100
./main --age=100
如果这个main.cc
程序不是你写的,但是你知道他使用了gflags
库,想看看它定义了哪些变量,则可以使用--helpshort
选项,就会显示这些变量的相关信息:
$ ./main --helpshort main: Warning: SetUsageMessage() never called Flags from /Users/self_study/Cpp/OpenSource/demo/main.cc: -age (age) type: uint32 default: 10 -big_menu (Include 'advance' option in the menu listing) type: bool default: true -languages (comma-separated list of languages to offer in the 'lang' menu) type: string default: "english, french, chinese"
如果某个项目中使用了 gflags
定义了很多全局变量,分布在不同的文件中,你可以使用--helpfull
选项来查看这些变量:
% ./main --helpfull main: Warning: SetUsageMessage() never called Flags from /Users/self_study/Cpp/OpenSource/demo/gflags/src/gflags.cc: -flagfile (load flags from file) type: string default: "" -fromenv (set flags from the environment [use 'export FLAGS_flag1=value']) type: string default: "" -tryfromenv (set flags from the environment if present) type: string default: "" -undefok (comma-separated list of flag names that it is okay to specify on the command line even if the program does not define a flag with that name. IMPORTANT: flags in this list that have arguments MUST use the flag=value format) type: string default: "" Flags from /Users/self_study/Cpp/OpenSource/demo/gflags/src/gflags_completions.cc: -tab_completion_columns (Number of columns to use in output for tab completion) type: int32 default: 80 -tab_completion_word (If non-empty, HandleCommandLineCompletions() will hijack the process and attempt to do bash-style command line flag completion on this value.) type: string default: "" Flags from /Users/self_study/Cpp/OpenSource/demo/gflags/src/gflags_reporting.cc: -help (show help on all flags [tip: all flags can have two dashes]) type: bool default: false -helpfull (show help on all flags -- same as -help) type: bool default: false currently: true -helpmatch (show help on modules whose name contains the specified substr) type: string default: "" -helpon (show help on the modules named by this flag value) type: string default: "" -helppackage (show help on all modules in the main package) type: bool default: false -helpshort (show help on only the main module for this program) type: bool default: false -helpxml (produce an xml version of help) type: bool default: false -version (show version and build info and exit) type: bool default: false Flags from /Users/self_study/Cpp/OpenSource/demo/main.cc: -age (age) type: uint32 default: 10 -big_menu (Include 'advance' option in the menu listing) type: bool default: true -languages (comma-separated list of languages to offer in the 'lang' menu) type: string default: "english, french, chinese"
好嘞,gflags
库的使用就介绍到这。更多细节,自行阅读官方文档和源码。
reference
推荐阅读
- 踩坑记 (1) | std::sort函数隐藏着BUG,你知道吗
- 网络编程 (1) | 走近reactor设计模式,剖析高性能服务器框架核心
- 必先利其器(3) | 分享我所有的C++学习资源
- 必先利其器(2) | 手把手教你学会gdb,适应Linux调试环境