#头文件
#include <co/flag.h>
API 在 flag 命名空间。
#概述
flag 提供命令行参数与配置文件解析功能,coost 中所有组件配置项都通过 flag 定义。
- 定义 flag 即定义全局变量,变量名是
FLG_<name>; - 支持命令行参数与配置文件两种方式;
- 命令行中支持
-help打印帮助信息、-mkconf生成配置文件、-version显示程序版本;
#定义 flag
#DEF 宏
DEF_bool(name, value, help, ...);
DEF_int32(name, value, help, ...);
DEF_int64(name, value, help, ...);
DEF_uint32(name, value, help, ...);
DEF_uint64(name, value, help, ...);
DEF_double(name, value, help, ...);
DEF_string(name, value, help, ...);
定义后通过全局变量访问,如 FLG_name。
类型对应关系:
| 宏 | 类型 | 内部标识 |
|---|---|---|
DEF_bool |
bool |
'b' |
DEF_int32 |
int32 |
'i' |
DEF_int64 |
int64 |
'I' |
DEF_uint32 |
uint32 |
'u' |
DEF_uint64 |
uint64 |
'U' |
DEF_double |
double |
'd' |
DEF_string |
co::string& |
's' |
示例:
// 定义全局 bool 类型变量,变量名是 FLG_debug
DEF_bool(debug, false, "debug mode");
#DEC 宏
DEC_bool(name);
DEC_int32(name);
DEC_int64(name);
DEC_uint32(name);
DEC_uint64(name);
DEC_double(name);
DEC_string(name);
用于跨文件声明,类型必须与 DEF_xxx 一致。
#别名
flag 支持别名,命令行或配置文件中可以用别名。
DEF_xxx 最后一个变参可以指定最多一个别名:
// d 是别名
DEF_bool(debug, false, "debug mode", d);
别名会显示在帮助信息中,例如 -debug,d。
#解析参数
co::vector<co::string> parse(int argc, char** argv, bool command_line_only=false);
- 解析命令行参数与配置文件,更新 flag 的值。
- 返回值包含所有非 flag 参数;
command_line_only == true时只解析命令行参数;- 通常在
main开头调用; - 遇到错误时,打印信息,退出程序。
#命令行参数
支持两种形式:
-name=value
-name value
- 可以是 1 个或多个,-debug、--debug 等价。
#bool 类型
-debug # 等价于 -debug=true
-debug=true
-debug=false
#整数单位
整数类型支持单位 k, m, g, t, p,不分大小写,1k = 1024。
-co_stack_size=2m # 2 * 1024 * 1024
#单字母 flag 简写语法
单字母 flag 支持如下两种简写(仅用于命令行):
- 多个单字母 bool flag 可以合并:如 x、y、z 都是 bool flag,
-xyz可以将三者都设为 true。 - 单字母整型 flag 可以连写值:如
-n8相当于-n=8。
#配置文件
默认命令行中第一个非 flag 参数(名字必须以 .conf 结尾),作为配置文件:
./xx xx.conf
配置文件格式:
# 注释
debug = true
threads = 8
port = 8080
name = "my app"
n = 8k # 8192
#表示注释;- 支持空行;
- 行首或行尾可以有空格;
- key 前面不加
--; =前后可以有空格;- 字符串首尾有空格时需要加引号,单引号和双引号都支持;
- 字符串支持常见转义字符,具体见
co::string::unescape; - bool 支持
true/false、1/0,其余值都当作false; - 整数支持
k, m, g, t, p单位,不区分大小写; - 配置文件中出现未定义 flag 时,会在终端打印一行 warning 信息,不会退出程序;
- flag 名大小写敏感。
#命令行与配置文件优先级
- 命令行参数与配置文件同时存在时,命令行参数会覆盖配置文件中的值;
- 命令行传入的
.conf会覆盖set_config_path设置的默认路径。
#内部 flag
flag 组件内部定义了三个 bool 类型 flag:
DEF_bool(help, false, s_help);
DEF_bool(version, false, s_version);
DEF_bool(mkconf, false, s_mkconf);
#-help
打印帮助信息。
./xx -help
帮助信息格式示例:
usage: ./xx [xx.conf] [-flag [value]] [-flag=value]...
flags: -name[,alias] type comments (default value)
-help b 显示帮助信息 (false)
-version,v b 显示版本信息 (false)
-mkconf b 生成配置文件 (false)
-boo b bool flag (false)
...
若用户包含了 co/log.h, co/co.h, co/rpc.h,coost 内部定义的 flag 也会显示在帮助信息中。
#-version
显示程序版本,需要在 flag::parse 前调用 flag::set_program_version 设置版本号。未设置时版本信息为空。
./xx -version
#-mkconf
生成配置文件:
./xx -mkconf
- 在当前执行命令的目录生成配置文件;
- 文件名规则:可执行文件名去掉
.exe,再加上.conf; - 包含所有用户 flag,以及用到的 coost 组件中的 flag;
- 若不想 flag 出现在配置文件中,可以用
flag::hide()隐藏 flag。
#运行时 API
// 添加别名,@new_name 必须有静态生命周期
// 如果 @new_name 为空,则移除已有别名
void flag::alias(const char* name, const char* new_name);
// 设置默认配置路径
void flag::set_config_path(const char* path);
// 设置程序版本
void flag::set_program_version(const char* ver);
// 隐藏 flag,使其不出现在帮助信息与 -mkconf 生成的配置文件中
void flag::hide(const char* name);
// 与 hide 相反
void flag::unhide(const char* name);
// 设置 flag 的值,出错时返回 false, 终端打印错误信息
bool flag::set_value(const char* flag_name, const char* value);
// 注册回调,在 flag::parse 解析完命令行参数后执行
void flag::run_after_parse(void(*cb)());
// 注册回调,在 flag::parse 解析命令行参数前执行
void flag::run_before_parse(void(*cb)());
上述 API 均非线程安全,需要在 flag::parse 前调用。
alias添加最多一个别名。set_config_path设置默认配置路径后,命令行中可以不传配置文件,parse会从默认路径解析配置文件。set_value中value是字符串形式,内部按 flag 类型解析,出错不会退出程序;
示例:
flag::alias("version", "v");
flag::set_value("debug", "true");
#线程安全
flag 本质是全局变量或对象,若有多个线程访问或修改 FLG_xxx。用户需要自己保证并发安全。
#示例
#include <co/log.h> // 已包含 co/flag.h
DEF_bool(debug, false, "enable debug mode");
DEF_int32(threads, 4, "number of threads");
DEF_uint32(port, 8080, "server port");
DEF_string(name, "coost", "app name", n); // n 为别名
int main(int argc, char** argv) {
// 设置程序版本号
flag::set_program_version("1.0.0");
// 日志组件内置 flag,日志也输出到终端
flag::set_value("also_log2console", "true");
// 可选:设置默认配置文件路径
// flag::set_config_path("my.conf");
auto non_flags = flag::parse(argc, argv);
log::info("debug=", FLG_debug);
log::info("threads=", FLG_threads);
log::info("port=", FLG_port);
log::info("name=", FLG_name);
for (auto& s : non_flags) {
log::info("non-flag: ", s);
}
return 0;
}
运行:
./app
./app -debug -threads=8 -port 8080 -name=myapp
./app -help
./app -version
./app -mkconf
./app app.conf