Gflags

概述

gflags是Google开发的一个开源库,用于C++应用程序中命令行参数的声明、定义和解析。gflags库提供了一种简单的方式来添加、解析和文档化命令行标志(flags),使得程序可以根据不同的运行时配置进行调整。
它具有如下几个特点:

  • 易于使用:gflags 提供了一套简单直观的API 来定义和解析命令行标志,使得开发者可以轻松地为应用程序添加新的参数。
  • 自动帮助和文档:gflags 可以自动生成每个标志的帮助信息和文档,这有助于用户理解如何使用程序及其参数。
  • 类型安全:gflags 支持多种数据类型的标志,包括布尔值、整数、字符串等,并且提供了类型检查和转换。
  • 多平台支持:gflags 可以在多种操作系统上使用,包括Windows、Linux 和macOS。
  • 可扩展性:gflags 允许开发者自定义标志的注册和解析逻辑,提供了强大的扩展性。

官方文档: https://gflags.github.io/gflags/
代码仓库:https://github.com/gflags/gflags.git

使用

头文件

包含头文件。使用gflags库来定义/解析命令行参数必须包含如下头文件

1
#include <gflags/gflags.h>

CMake编译

1
2
3
4
cmake_minimum_required(VERSION 3.20)
project(test)
add_executable(main.exe main.cpp)
target_link_libraries(main.exe gflags)

语法

定义参数

利用gflag 提供的宏定义来定义参数。该宏的3 个参数分别为命令行参数名,参数默认值,参数的帮助信息。

1
2
3
DEFINE_bool(reuse_addr, true, "是否开始网络地址重用选项"); 
DEFINE_int32(log_level, 1, "日志等级:1-DEBUG, 2-WARN, 3-ERROR");
DEFINE_string(log_file, "stdout", "日志输出位置设置,默认为标准输出");

程序中通过FLAGS_name像正常变量一样访问标志参数。比如在上面的例子中,我们可以通过FLAGS_big_menuFLAGS_languages变量来访问命令行参数。

如果想再另外一个文件访问当前文件的参数,以参数FLAGS_big_menu为例,我们可以使用用

1
DECLARE_bool(big_menu)

来声明引入这个参数。其实这个宏就相当于做了extern FLAGS_big_menu,定义外部链接属性。

初始化所有参数

当我们定义好参数后,需要告诉可执行程序去处理解析命令行传入的参数,使得FLAGS_*变量能得到正确赋值。我们需要在main函数中,调用下面的函数来解决命令行传入的所有参数。

1
google::ParseCommandLineFlags(&argc, &argv, true);

参数:

  • argcargv就是`main 的入口参数
  • 第三个参数被称为remove_flags
    • 如果它为true, 表示ParseCommandLineFlags会从argv中移除标识和它们的参数,相应减少argc的值。
    • 如果它为falseParseCommandLineFlags会保留argc不变,但将会重新调整它们的顺序,使得标识再前面。

运行参数设置

gflags为我们提供了多种命令行设置参数的方式。

string和int设置参数:

1
2
3
4
exec --log_file="./main.log" 
exec -log_file="./main.log"
exec --log_file "./main.log"
exec -log_file "./main.log"

bool设置参数

1
2
3
4
exec --reuse_addr 
exec --noreuse_addr
exec --reuse_addr=true
exec --reuse_addr=false

配置文件的使用

配置文件的使用,其实就是为了让程序的运行参数配置更加标准化,不需要每次运行的时候都手动收入每个参数的数值,而是通过配置文件,一次编写,永久使用。

需要注意的是,配置文件中选项名称必须与代码中定义的选项名称一致。

1
2
3
-reuse_addr=true 
-log_level=3
-log_file=./log/main.log

特殊参数标识

gflags也默认为我们提供了几个特殊的标识。

1
2
3
4
5
6
--help # 显示文件中所有标识的帮助信息 
--helpfull # 和-help 一样, 帮助信息更全面一些
--helpshort # 只显示当前执行文件里的标志
--helpxml # 以 xml 方式打印,方便处理
--version # 打印版本信息,由 google::SetVersionString()设定
--flagfile -flagfile=f #从文件 f 中读取命令行参数
1
2
3
4
5
6
user@DESKTOP-KFNQORU:~$ ./main.exe --help
main.exe: Warning: SetUsageMessage() never called
Flags from /home/user/BuildTools/Gflags/main.cpp:
-debug_enable (是否启用调试模式) type: bool default: true
-ip (这是服务器的监听ip地址) type: string default: "172.0.0.1"
-port (这是服务器的监听端口) type: int32 default: 8080
1

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <gflags/gflags.h>
#include <iostream>

DEFINE_string(ip, "172.0.0.1", "这是服务器的监听ip地址");
DEFINE_int32(port, 8080, "这是服务器的监听端口");
DEFINE_bool(debug_enable, true, "是否启用调试模式");

int main(int argc, char* argv[])
{
google::ParseCommandLineFlags(&argc, &argv, true);
std::cout << FLAGS_ip << std::endl;
std::cout << FLAGS_port << std::endl;
std::cout << FLAGS_debug_enable << std::endl;
return 0;
}

输出:

1
2
3
4
5
6
7
8
user@DESKTOP-KFNQORU:~$ ./main.exe --ip="192.169.1.1" --port=9090 --debug_enable=false
192.169.1.1
9090
0
user@DESKTOP-KFNQORU:~$ ./main.exe
172.0.0.1
8080
1

配置文件:

1
2
3
-ip = "192.168.1.1"
-port = 10001
-debug_enable = true