今天写程序时需要写一个命令行解析程序,于是网上搜索getopt()的实现代码,但搜到的信息基本上是如何使用getopt(),而系统又是Windows的;于是想到了以前项目中使用到的Google开源命令行解析库gflags。
google开源的gflags是一套命令行参数解析工具,他可以替代getopt(),使用起来更加方便灵活,包括支持C++内建的类型如string,gflags还支持从环境变量、配置文件读取参数(可用gflags代替配置文件)。本文简单介绍gflags的安装与使用。
gflags的安装
gflags源代码可以按照
https://code.google.com/p/gflags/
给的download链接地址去下载,我的机器是Windows系统,于是下载最新的
gflags-2.1.1.zip,当然tar.gz也可以的。下载完后解压,这时候源代码并不能直接放在应用程序中引用,因为看网上好多例子都include <gflags/gflags.h>,而压缩完的源代码中并没有gflags.h,但是注意到src目录中有个gflags.h.in文件,想必是需要做什么操作将
gflags.h.in文件转换为
gflags.h;继续浏览根目录gflags-2.1.1,可以看到有个INSTALL.txt文件,可惜里面都是一些Linux安装操作,再看有个CMakeLists.txt文件,这个文件是CMake工具生成工程必备的文件,于是用CMake生成VS工程配置:
点击Configure,出现报错信息:
The CXX compiler identification is MSVC 16.0.30319.1
Check for working CXX compiler using: Visual Studio 10
Check for working CXX compiler using: Visual Studio 10 -- broken
CMake Error at C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeTestCXXCompiler.cmake:54 (message):
The C++ compiler "C:/Program Files (x86)/Microsoft Visual Studio
10.0/VC/bin/cl.exe" is not able to compile a simple test program.
It fails with the following output:
Change Dir: D:/software/gflags-2.1.1/cmake-bin/CMakeFiles/CMakeTmp
Run Build Command:C:\PROGRA~2\MICROS~2.0\Common7\IDE\devenv.com
CMAKE_TRY_COMPILE.sln /build Debug /project cmTryCompileExec1038135002
Microsoft(R) Visual Studio 10.0.30319.1 版。
版权所有(C) Microsoft Corp。保留所有权利。
1>------ 已启动生成: 项目: cmTryCompileExec1038135002, 配置: Debug Win32
------
1>生成启动时间为 2014/5/5 19:27:03。
1>PrepareForBuild:
1>
正在创建目录“D:\software\gflags-2.1.1\cmake-bin\CMakeFiles\CMakeTmp\Debug\”。
1>InitializeBuildStatus:
1>
正在创建“cmTryCompileExec1038135002.dir\Debug\cmTryCompileExec1038135002.unsuccessfulbuild”,因为已指定“AlwaysCreate”。
1>ClCompile:
1> 用于 80x86 的 Microsoft (R) 32 位 C/C++ 优化编译器 16.00.30319.01 版
1> 版权所有(C) Microsoft Corporation。保留所有权利。
1>
1> cl /c /Zi /W3 /WX- /Od /Ob0 /Oy- /D WIN32 /D _WINDOWS /D _DEBUG /D
"CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise
/Zc:wchar_t /Zc:forScope /GR /Fo"cmTryCompileExec1038135002.dir\Debug\\"
/Fd"cmTryCompileExec1038135002.dir\Debug\vc100.pdb" /Gd /TP /analyze-
/errorReport:prompt testCXXCompiler.cxx
1>
1> testCXXCompiler.cxx
1>LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
1>
1>生成失败。
1>
1>已用时间 00:00:00.98
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
CMakeLists.txt:16 (project)
Configuring incomplete, errors occurred!
See also "D:/software/gflags-2.1.1/cmake-bin/CMakeFiles/CMakeOutput.log".
See also "D:/software/gflags-2.1.1/cmake-bin/CMakeFiles/CMakeError.log".
按照提示,打开文件D:/software/gflags-2.1.1/cmake-bin/CMakeFiles/CMakeError.log,
看到报错信息为:
LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
这个解决方案在
http://blog.chinaunix.net/uid-20385936-id-3506149.html
写的很清楚;替换
cvtres.exe
之后再次点积Configure后,就没有什么问题了,之后就Generateg一个flags的VS工程。
生成ALL_BUILD项目,然后生成INSTALL项目,这里安装时可能会出以下错误:
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: 命令“setlocal
3>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: "C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=Debug -P cmake_install.cmake
3>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: if %errorlevel% neq 0 goto :cmEnd
3>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: :cmEnd
3>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
3>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: :cmErrorLevel
3>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: exit /b %1
3>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: :cmDone
3>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: if %errorlevel% neq 0 goto :VCEnd
3>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: :VCEnd”已退出,代码为 1。
这个一般是权限问题,退出VS,重新以管理员省份打开该工程,再次生成INSTALL项目就没有问题了;在C:\Program Files (x86)目录中可以看到已经有gflags目录,之后就可以引用该目录下的库进行编程了。在这里为方便大家不用做以上操作,直接获得gflags库的使用,这里提供我已经
编译好的库和头文件
,地址为:
http://download.csdn.net/detail/lming_08/7352863
gflags的使用
使用flags需要包含头文件 #include <gflags/gflags.h>
gflags主要支持的参数类型包括bool,int32, int64, uint64, double, string等,定义参数通过DEFINE_type宏实现,如下所示,分别定义了一个bool和一个string类型的参数,该宏的三个参数含义分别为命令行参数名,参数默认值,以及参数的帮助信息。
DEFINE_bool(big_menu, true, "Include 'advanced' options in the menu listing");
DEFINE_string(languages, "english,french,german",
"comma-separated list of languages to offer in the 'lang' menu");
gflag不支持列表,用户通过灵活借助string参数实现,比如上述的languages参数,可以类型为string,但可看作是以逗号分割的参数列表。
定义以上参数后,就需要在main()函数中执行gflags::ParseCommandLineFlags(&argc, &argv, true);
然后就可以在应用程序中使用FLAGS_big_menu、FLAGS_languages表示获取到的命令行参数值。
注意:直接#include <gflags/gflags.h>并链接上gflags.lib或gflags_nothreads.lib,应用程序可能并不能链接成功,可能会生成如下报错信息:
gflags.lib(gflags.obj) : error LNK2019: 无法解析的外部符号 __imp__PathMatchSpecA@8,该符号在函数 "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall gflags::`anonymous namespace'::CommandLineFlagParser::ProcessOptionsFromStringLocked(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,enum gflags::FlagSettingMode)" (?ProcessOptionsFromStringLocked@CommandLineFlagParser@?A0x8a801983@gflags@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABV45@W4FlagSettingMode@3@@Z) 中被引用
查阅资料发现是没有链接上
shlwapi.lib,而
shlwapi.lib是已经被废弃的库;链接上
shlwapi.lib库后再次编译链接就OK了。
考虑到
shlwapi.lib和gflags库都是静态库,因此可以在生成gflags库时链接上
shlwapi.lib,这样在应用程序中就不用额外地再链接上
shlwapi.lib了。
另外需要注意的是,在VS【属性】-【调试】中设置的原始命令行参数argv[]中表示字符串内容不仅仅是设置的相应字符串,他会在字符串前加上工程路径名,而gflags中就没有了工程路径名,设置的多少就是多少。
参考资料:
http://blog.chinaunix.net/uid-20385936-id-3506149.html
http://blog.chinaunix.net/uid-20196318-id-3440642.html
http://www.cnblogs.com/dkblog/archive/2012/02/15/2352315.html