今天写程序时需要写一个命令行解析程序,于是网上搜索getopt()的实现代码,但搜到的信息基本上是如何使用getopt(),而系统又是Windows的;于是想到了以前项目中使用到的Google开源命令行解析库gflags。
google开源的gflags是一套命令行参数解析工具,他可以替代getopt(),使用起来更加方便灵活,包括支持C++内建的类型如string,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
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