#Header
#include <co/flag.h>
The API is in the flag namespace.
#Overview
flag provides command-line argument and configuration file parsing functionality. All component configuration items in coost are defined through flags.
- Defining a flag defines a global variable; the variable name is
FLG_<name>; - Supports both command-line arguments and configuration files;
- The command line supports
-helpto print help information,-mkconfto generate a configuration file, and-versionto display the program version;
#Defining Flags
#DEF Macros
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, ...);
After definition, access it through a global variable, such as FLG_name.
Type correspondence:
| Macro | Type | Internal Identifier |
|---|---|---|
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' |
Example:
// Define a global bool variable; the variable name is FLG_debug
DEF_bool(debug, false, "debug mode");
#DEC Macros
DEC_bool(name);
DEC_int32(name);
DEC_int64(name);
DEC_uint32(name);
DEC_uint64(name);
DEC_double(name);
DEC_string(name);
Used for cross-file declarations; the type must match DEF_xxx.
#Aliases
Flags support aliases; aliases can be used on the command line or in configuration files.
The last variadic parameter of DEF_xxx can specify at most one alias:
// d is an alias
DEF_bool(debug, false, "debug mode", d);
Aliases are displayed in the help information, for example -debug,d.
#Parsing Arguments
co::vector<co::string> parse(int argc, char** argv, bool command_line_only=false);
- Parses command-line arguments and the configuration file, and updates flag values.
- The return value contains all non-flag arguments;
- When
command_line_only == true, only command-line arguments are parsed; - Usually called at the beginning of
main; - On error, prints information and exits the program.
#Command-Line Arguments
Two forms are supported:
-name=value
-name value
- can be one or more; -debug and --debug are equivalent.
#bool Type
-debug # Equivalent to -debug=true
-debug=true
-debug=false
#Integer Units
Integer types support the units k, m, g, t, p, case-insensitive, 1k = 1024.
-co_stack_size=2m # 2 * 1024 * 1024
#Single-Letter Flag Shorthand Syntax
Single-letter flags support the following two shorthands (command line only):
- Multiple single-letter bool flags can be combined: for example, if x, y, and z are all bool flags,
-xyzcan set all three to true. - A single-letter integer flag can be written together with its value: for example,
-n8is equivalent to-n=8.
#Configuration File
By default, the first non-flag argument on the command line (whose name must end with .conf) is used as the configuration file:
./xx xx.conf
Configuration file format:
# Comment
debug = true
threads = 8
port = 8080
name = "my app"
n = 8k # 8192
#indicates a comment;- Blank lines are supported;
- Leading or trailing spaces on a line are allowed;
- The key is not prefixed with
--; - Spaces are allowed before and after
=; - If a string has leading or trailing spaces, it needs to be quoted; both single and double quotes are supported;
- Strings support common escape characters; see
co::string::unescapefor details; - bool supports
true/falseand1/0; all other values are treated asfalse; - Integers support the units
k, m, g, t, p, case-insensitive; - If an undefined flag appears in the configuration file, a warning line is printed to the terminal, but the program does not exit;
- Flag names are case-sensitive.
#Command-Line vs. Configuration File Priority
- When both command-line arguments and a configuration file are present, command-line arguments override values in the configuration file;
- A
.confpassed on the command line overrides the default path set byset_config_path.
#Internal Flags
The flag component internally defines three bool flags:
DEF_bool(help, false, s_help);
DEF_bool(version, false, s_version);
DEF_bool(mkconf, false, s_mkconf);
#-help
Prints help information.
./xx -help
Example help information format:
usage: ./xx [xx.conf] [-flag [value]] [-flag=value]...
flags: -name[,alias] type comments (default value)
-help b show help information (false)
-version,v b show version information (false)
-mkconf b generate configuration file (false)
-boo b bool flag (false)
...
If the user includes co/log.h, co/co.h, co/rpc.h, flags defined internally by coost will also appear in the help information.
#-version
Displays the program version. You need to call flag::set_program_version before flag::parse to set the version number. If not set, the version information is empty.
./xx -version
#-mkconf
Generates a configuration file:
./xx -mkconf
- Generates the configuration file in the directory where the command is executed;
- File name rule: the executable file name with
.exeremoved, plus.conf; - Contains all user flags as well as flags from the coost components used;
- If you do not want a flag to appear in the configuration file, you can use
flag::hide()to hide the flag.
#Runtime API
// Add an alias; @new_name must have static lifetime
// If @new_name is empty, remove the existing alias
void flag::alias(const char* name, const char* new_name);
// Set the default configuration path
void flag::set_config_path(const char* path);
// Set the program version
void flag::set_program_version(const char* ver);
// Hide a flag so that it does not appear in help information or the configuration file generated by -mkconf
void flag::hide(const char* name);
// Opposite of hide
void flag::unhide(const char* name);
// Set the value of a flag; returns false on error and prints an error message to the terminal
bool flag::set_value(const char* flag_name, const char* value);
// Register a callback to be executed after flag::parse finishes parsing command-line arguments
void flag::run_after_parse(void(*cb)());
// Register a callback to be executed before flag::parse parses command-line arguments
void flag::run_before_parse(void(*cb)());
The above APIs are not thread-safe and need to be called before flag::parse.
aliasadds at most one alias.- After
set_config_pathsets the default configuration path, you do not need to pass a configuration file on the command line;parsewill parse the configuration file from the default path. - In
set_value,valueis in string form and is parsed internally according to the flag type; an error will not cause the program to exit;
Example:
flag::alias("version", "v");
flag::set_value("debug", "true");
#Thread Safety
A flag is essentially a global variable or object. If multiple threads access or modify FLG_xxx, the user needs to ensure concurrency safety themselves.
#Example
#include <co/log.h> // Already includes 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 is an alias
int main(int argc, char** argv) {
// Set the program version number
flag::set_program_version("1.0.0");
// Built-in flag of the logging component; also output logs to the terminal
flag::set_value("also_log2console", "true");
// Optional: set the default configuration file path
// 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;
}
Run:
./app
./app -debug -threads=8 -port 8080 -name=myapp
./app -help
./app -version
./app -mkconf
./app app.conf