1、下载、安装:

Google 的 gflags 是一套命令行参数处理的开源库。比 getopt 更方便、功能更强大。包括 C++的版本和 python 的版本。

github地址:​​https://github.com/gflags/gflags​

1)安装cmake工具:

在安装gflags前需要先安装cmake:

官网:​​https://cmake.org/download/​

github:​​https://github.com/Kitware/CMake/releases​

1.1)下载:

本文下载、安装3.8.1版本,地址:

wget ​64.tar.gz">​https://github.com/Kitware/CMake/releases/download/v3.8.1/cmake-3.8.1-Linux-x86_64.tar.gz​

或者:

1.2)编译、安装:

install_specified_deps "cmake-3.8.1"
if [ ! -d cmake-3.8.1 ]; then
tar -zxf cmake-3.8.1.tar.gz
cd cmake-3.8.1
./bootstrap
check_install_status
make -j8
check_install_status
make install
check_install_status
ldconfig
cd ../
fi

 

2)git下载、编译gflags:

git clone https://github.com/gflags/gflags.git
cd gflags
mkdir build && cd build #通过cmake生成的Makefile等文件放到build目录
cmake ..
make j8
make install

3)下载gflags源码tar.gz包、编译安装:(方法二)

地址:

#install gflags
install_specified_deps "gflags-2.2.0"
if [ ! -d gflags-2.2.0 ]; then
tar -zxf gflags-2.2.0.tar.gz
cd gflags-2.2.0/
cmake -DBUILD_SHARED_LIBS=1 -DBUILD_STATIC_LIBS=1 ./
check_install_status
make -j8
check_install_status
make install
check_install_status
ldconfig
cd ../
fi

注:这时 gflags 库会默认安装在 /usr/local/lib/ 下,头文件放在 /usr/local/include/gflags/ 中。

注:在编译gflags的时候如果不加参数(即:直接使用cmake),默认会采用静态编译。这个时候代码引入gflags库后,编译出来的业务代码会很大。

2、基本功能:

2.1)先看一个示例:

1)cpp代码:

#include <iostream>
#include <gflags/gflags.h>

using namespace std;

DEFINE_string(host,"127.0.0.1","ip address");
DEFINE_int32(port,3306,"server port");

int main(int argc,char* argv[]){
gflags::ParseCommandLineFlags(&argc,&argv,true);
cout<<"server ip:"<<FLAGS_host<<",port:"<<FLAGS_port<<endl;
return 0;
}

 

2)编译:

g++ -o run test_gflag1.cpp -lgflags -lpthread

注:不加-lpthread会报如下错:

//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::(anonymous namespace)::FlagRegistry::GlobalRegistry()':
gflags.cc:(.text+0xef6): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0xf16): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0xfb7): undefined reference to `pthread_rwlock_init'
gflags.cc:(.text+0xfd0): undefined reference to `pthread_rwlock_init'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::(anonymous namespace)::RegisterCommandLineFlag(char const*, char const*, char const*, google::(anonymous namespace)::FlagValue*, google::(anonymous namespace)::FlagValue*)':
gflags.cc:(.text+0x1265): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x1285): undefined reference to `pthread_rwlock_unlock'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::(anonymous namespace)::AddFlagValidator(void const*, bool (*)())':
gflags.cc:(.text+0x1524): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x153c): undefined reference to `pthread_rwlock_wrlock'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::GetCommandLineOption(char const*, std::string*)':
gflags.cc:(.text+0x2554): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x256e): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x25de): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x266d): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x2854): undefined reference to `pthread_rwlock_init'
gflags.cc:(.text+0x286f): undefined reference to `pthread_rwlock_init'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::GetCommandLineFlagInfo(char const*, google::CommandLineFlagInfo*)':
gflags.cc:(.text+0x29ac): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x29c6): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x2a3e): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x2a54): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x2b18): undefined reference to `pthread_rwlock_init'
gflags.cc:(.text+0x2b37): undefined reference to `pthread_rwlock_init'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::GetCommandLineFlagInfoOrDie(char const*)':
gflags.cc:(.text+0x2c4c): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x2c96): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x2d0e): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x2d24): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x2dc8): undefined reference to `pthread_rwlock_init'
gflags.cc:(.text+0x2de7): undefined reference to `pthread_rwlock_init'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::FlagSaver::FlagSaver()':
gflags.cc:(.text+0x3317): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x332e): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x3397): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x33ae): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x3486): undefined reference to `pthread_rwlock_init'
gflags.cc:(.text+0x349c): undefined reference to `pthread_rwlock_init'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::FlagSaver::~FlagSaver()':
gflags.cc:(.text+0x38b7): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x38cd): undefined reference to `pthread_rwlock_wrlock'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::ShutDownCommandLineFlags()':
gflags.cc:(.text+0x4591): undefined reference to `pthread_rwlock_destroy'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::SetCommandLineOptionWithMode(char const*, char const*, google::FlagSettingMode)':
gflags.cc:(.text+0x660c): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x6624): undefined reference to `pthread_rwlock_unlock'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::ReadFlagsFromString(std::string const&, char const*, bool)':
gflags.cc:(.text+0x7827): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x783e): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x7855): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x786a): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x7880): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x7895): undefined reference to `pthread_rwlock_wrlock'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::SetCommandLineOption(char const*, char const*)':
gflags.cc:(.text+0x7b64): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x7b7c): undefined reference to `pthread_rwlock_unlock'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::ParseCommandLineFlagsInternal(int*, char***, bool, bool)':
gflags.cc:(.text+0x867a): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x868f): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x86aa): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x86c0): undefined reference to `pthread_rwlock_wrlock'
gflags.cc:(.text+0x86d6): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x86ec): undefined reference to `pthread_rwlock_wrlock'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `google::GetAllFlags(std::vector<google::CommandLineFlagInfo, std::allocator<google::CommandLineFlagInfo> >*)':
gflags.cc:(.text+0x9cd8): undefined reference to `pthread_rwlock_unlock'
gflags.cc:(.text+0x9cf3): undefined reference to `pthread_rwlock_wrlock'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `gflags_mutex_namespace::Mutex::~Mutex()':
gflags.cc:(.text._ZN22gflags_mutex_namespace5MutexD2Ev[_ZN22gflags_mutex_namespace5MutexD5Ev]+0x15): undefined reference to `pthread_rwlock_destroy'
//usr/local/lib/libgflags.a(gflags.cc.o): In function `gflags_mutex_namespace::Mutex::Unlock()':
gflags.cc:(.text._ZN22gflags_mutex_namespace5Mutex6UnlockEv[_ZN22gflags_mutex_namespace5Mutex6UnlockEv]+0x15): undefined reference to `pthread_rwlock_unlock'
collect2: error: ld returned 1 exit status

 

3)运行:

C++ gflas示例_命令行参数

2.2)说明:

1)定义命令行标记:

通过DEFINE_type宏实现,该支持三种参数:变量名、默认值、说明。例如:

DEFINE_string(host,"localhost","sever ip address");

gflags 一共支持 5 种类型的命令行参数定义:

  • DEFINE_bool: 布尔类型
  • DEFINE_int32: 32 位整数
  • DEFINE_int64: 64 位整数
  • DEFINE_uint64: 无符号 64 位整数
  • DEFINE_double: 浮点类型 double
  • DEFINE_string: C++ string 类型

2)访问命令行标记:

所有我们定义的 gflags 变量都可以通过 FLAGS_ 前缀加参数名访问,gflags 变量也可以被自由修改。

3)命令行中指定标记:

  • 可以使用--或者-;
  • 可以有等号(=),也可以直接用空格;

3、进阶:

正常来说我们的代码不可能只有1个cpp,还会有很多模块。而每个模块可能都会使用命令行参数值。如何在其他模块怎么引用和使用呢?so easy,与DEFINE相对应的有DECLARE。

  • 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

它的作用就相当于用 extern 声明变量。为了方便的管理变量,我们推荐在 .cpp 文件中 DEFINE 变量,然后只在对应 .h 中或者单元测试中 DECLARE 变量。看一个例子:

C++ gflas示例_命令行参数_02

编译:g++ demo.cpp logic.cpp -lgflags -lpthread

4、参数检查

一般情况下,我们获取到所有命令行参数的值后,都会做一次检查。gflags里面建议使用 RegisterFlagValidator 这个方法来做参数检查。参数不通过的时候,程序是启动失败的。例如:

#include <iostream>
#include <gflags/gflags.h>

using namespace std;

DEFINE_string(host,"127.0.0.1","ip address");
DEFINE_int32(port,3306,"server port");
static bool ValidatePort(const char* flagname, gflags::int32 value) {
if (value >= 36800 && value <= 36888) {
cout<<"param "<<flagname<<"="<<value<<" is valid!"<<endl;
return true;
}

cout<<"param "<<flagname<<"="<<value<<" is invalid!"<<endl;
return false;
}

static const bool port_dummy = gflags::RegisterFlagValidator(&FLAGS_port, &ValidatePort);

int main(int argc,char* argv[]){
gflags::ParseCommandLineFlags(&argc,&argv,true);
cout<<"server ip:"<<FLAGS_host<<",port:"<<FLAGS_port<<endl;
return 0;
}

 

 

 

编译:g++ test_gflag2.cpp -lgflags -lpthread

运行:

C++ gflas示例_2d_03

 

5、使用flagfile:

如果我们定义了很多参数,那么每次启动时都在命令行指定对应的参数显然是不合理的。gflags允许把 flag 参数和对应的值写在文件中,然后运行时使用 -flagfile 来指定对应的 flag 文件就好。例如:

1)编辑一个flags文件:vim ./test_gflag2.flags

里面的内如:

--port=36810

2)运行程序:

# ./a.out --flagfile=./test_gflag2.flags

param port=36810 is valid!

server ip:127.0.0.1,port:36810