Compare commits

...

463 commits
v0.2 ... master

Author SHA1 Message Date
Andreas Schuh
52e94563eb
test: Trigger workflow upon push on master (#370)
Some checks failed
Build and Run Tests / Test on ubuntu-latest (push) Failing after 1s
2025-03-31 23:49:02 +01:00
Andreas Schuh
c1f63a168d
doc: Replace CI badges with GitHub Action status (#369) 2025-03-31 23:39:15 +01:00
Rui Chen
70c01a642f
build: support cmake 4.0 (#367)
Signed-off-by: Rui Chen <rui@chenrui.dev>
2025-03-31 23:35:49 +01:00
Andreas Schuh
b364def945
test: Add GitHub Action to run CTest (#368)
* test: Remove Travis CI and Appveyor config files

* test: Add GitHub Action to run CTest on Ubuntu
2025-03-31 23:33:08 +01:00
JaiXJM-BB
58cf1ef6d0
cmake: Support BlackBerry QNX (#364) 2024-12-13 23:00:05 +00:00
Izzie Corley
3c4399ba46
Fix spelling in ChangeLog.txt (#362) 2024-10-11 13:35:38 +01:00
Lan Zongwei
03a4842c9c cmake: export gflags_nothreads_static into one export set by subproject default 2024-06-09 22:38:04 +01:00
Vertexwahn
82793e3f38 Fix spelling 2024-06-09 22:08:02 +01:00
Alexander Borsuk
c196ce6baa Fixed macro redifinition warning for Unity builds
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-06-09 22:07:48 +01:00
Vertexwahn
3df39f3a03 Add MODULE.bazel file to support Bzlmod 2024-06-09 22:04:34 +01:00
Biswapriyo Nath
a738fdf933 cmake: Do not add suffix with static library names in mingw
In mingw environment, this fixes static linking using pkgconfig file.
2022-07-27 22:06:09 +01:00
Joseph Shanak
b7fd838331 Update docs. Add id to --flagfile so it can be jumped to 2022-07-27 22:05:07 +01:00
Biswapriyo Nath
986e8eed00 cmake: Install pkgconfig file in mingw 2022-01-08 23:24:44 +00:00
Michael Chinen
9ca7e9ee7a
Android linking fix (#321) 2022-01-08 23:02:39 +00:00
HongboLiu
4ace06d024 make bazel use same namespace with cmake 2022-01-08 22:40:36 +00:00
Changqing Li
827c769e5f switch shebang to python3
python2 is EOL, swith shebang to python3

Signed-off-by: Changqing Li <changqing.li@windriver.com>
2020-10-30 10:16:12 +00:00
Zachary
5d5a6c5501 Include string.h for strchr and strcmp.
This fixes a continuous build
(https://travis-ci.org/github/google/perf_data_converter/jobs/714589290)
running on Ubuntu 16.04 using gcc-4.8.
2020-10-11 01:37:59 +01:00
panzhongxian
a386bd0f20 Update index.html dependency with Bazel section. 2020-09-23 11:26:36 +01:00
panzhongxian
cb68d9eeb8 Update index.html dependency with Bazel section. 2020-09-23 09:05:28 +01:00
Andreas Schuh
ae2fae5645 Merge branch 'remove-doc-submodule' 2020-09-18 17:55:31 +01:00
Andreas Schuh
1c86423887 Add doc/README.md with command to update gh-pages 2020-09-18 17:50:41 +01:00
Andreas Schuh
8843f88b69 Add 'doc/' from commit '8411df715cf522606e3b1aca386ddfc0b63d34b4'
git-subtree-dir: doc
git-subtree-mainline: 4405871443
git-subtree-split: 8411df715c
2020-09-18 17:44:46 +01:00
Andreas Schuh
4405871443 Remove doc/ submodule self-reference 2020-09-18 17:44:26 +01:00
Andrew Gasparovic
f7388c6655 Simplify found_question_marks tests 2020-06-16 22:11:03 +01:00
Andrew Gasparovic
84968c6bb2 Remove fallthrough switch case
GCC gives an implicit-fallthrough warning (included in -Wextra). C++17 has the [[fallthrough]] attribute, and GCC7+ has __attribute__ ((fallthrough)), but I didn't want to require either so I refactored the switch into if statements.
2020-06-16 22:11:03 +01:00
Tom Lundell
1137acc9e0 Remove msys dependency for Windows.
Bazel genrules require a msys shell to execute
shell commands. Replace the genrules with a
simple C++ regex replacement binary.

Fixes #303.
2020-06-13 03:44:00 +01:00
Andrew Gasparovic
ef8e134d48 Remove unreachable code
INFO: From Compiling external/com_github_gflags_gflags/src/gflags_completions.cc:
external/com_github_gflags_gflags/src/gflags_completions.cc:459:16: warning: code will never be executed [-Wunreachable-code]
      DVLOG(3) << "Result: most-common match";
               ^~
1 warning generated.
2020-06-13 00:41:51 +01:00
Ilya Lavrenov
addd749114 Set POCICY 0063 to new 2020-03-18 12:31:18 +00:00
Trevor Hickey
2e227c3daa remove attribute where it does not apply
```
gflags.h(226): warning: attribute "visibility" does not apply here
```

The visibility attribute applies to symbols like functions and variables. A definition of an enumeration type that doesn't contain a variable name doesn't create any symbols.
2020-01-16 00:49:58 +00:00
Jacky Wu
d9b184bd00 Avoid no-match message in case STRIP_FLAG_HELP been set
If the workaround in issue #43 is used along with the define of
STRIP_FLAG_HELP to 1, there would be a wrong "No modules matched"
message been print at end of the usage message.

That's because we continue the loop if we see strip flag help value and
never set the `found_match` flag to true even if we found a match.

By moving the set statement above the continue, we can avoid this wrong
message.
2019-11-13 14:07:30 +00:00
Rosen Penev
6c8f50b567 [clang-tidy] Remove redundant initialization of strings
Found with readability-redundant-string-init

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2019-11-01 09:26:51 +00:00
Rosen Penev
6d224d34b6 [clang-tidy] Replace deprecated C headers
Deprecated with C++14.

Found with modernize-deprecated-headers

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2019-11-01 09:26:51 +00:00
Mizux
0b7f8db2c6 Fix check of targets in package config when GFLAGS_USE_TARGET_NAMESPACE 2019-09-29 15:31:36 +01:00
Andreas Schuh
f40e43a628 Change order of sections in INSTALL file, mention Homebrew 2019-09-29 14:59:09 +01:00
grdowns
57c5913fb8 Add vcpkg installation instructions 2019-09-29 14:50:43 +01:00
Rosen Penev
2cac878761 package.pc.in: bin and libdir to exec_prefix
More consistent with other pkgconfig files.

No functional difference.
2019-09-17 19:13:49 +01:00
Andreas Schuh
28f50e0fed
fix: Install pkgconfig file only when INSTALL_HEADERS option is ON 2019-01-25 17:58:59 +00:00
Andreas Schuh
1005485222 fixup: Keep CMake coding style with whitespace after command name 2018-12-05 11:11:48 +00:00
Andreas Schuh
be65295633 fix: GFLAGS_* variables take precedence in gflags_define 2018-12-05 11:11:48 +00:00
Andreas Schuh
524b83d026
Merge pull request #276 from Rastaban/master
Add missing @ to cmake-config.in
2018-12-01 00:20:51 +00:00
Phil Christensen
34819405ab
Merge pull request #1 from Rastaban/Rastaban-patch-1
Add missing @ to cmake file
2018-11-30 15:50:14 -08:00
Phil Christensen
00fcadd9b8
Add missing @ to cmake file 2018-11-30 15:48:42 -08:00
Andreas Schuh
498cfa8b13
doc: Minor English language fix in release notes 2018-11-11 21:43:32 +00:00
Andreas Schuh
e171aa2d15
Release v2.2.2 2018-11-11 21:21:00 +00:00
Andreas Schuh
3d2a101c9e doc: Update README for release v2.2.2 2018-11-11 21:17:01 +00:00
Andreas Schuh
af502c8176 doc: Update ChangeLog for release v2.2.2 2018-11-11 21:09:58 +00:00
Andreas Schuh
0f439e8407 cmake: Increment project version to 2.2.2 2018-11-11 21:09:38 +00:00
Andreas Schuh
83fecd3ed0 doc: Updated CMake and Bazel examples 2018-11-11 20:45:00 +00:00
Andreas Schuh
8411df715c Update CMake and Bazel examples 2018-11-11 20:44:23 +00:00
Andreas Schuh
4c0bbc0604 fix: Use 'default' visibility for GCC 2018-11-11 20:35:02 +00:00
Andreas Schuh
0c7012d647 fix: Build with MinGW version after Nov 2016 2018-11-09 16:38:57 +00:00
Andreas Schuh
b051bace27 fix: Build with _UNICODE support on Windows 2018-11-09 16:16:24 +00:00
Andreas Schuh
7e70988188 fix: PVS Studio warnings 2018-10-15 02:15:17 -07:00
Andreas Schuh
754d3329a6 fix: No extern template declaration for MSVC <12.0 2018-10-15 00:50:48 -07:00
Andreas Schuh
82456f220f fix: Declare FlagRegisterer c’tor explicit template instanations as extern in header 2018-10-15 00:50:48 -07:00
Andreas Schuh
3e2e349307 fix: Declare FALGS_no##name variables as static 2018-10-14 00:16:13 -07:00
Andreas Schuh
c0b1add45f fix: Import with GFLAGS_USE_TARGET_NAMESPACE=ON 2018-09-28 16:28:33 +01:00
Andreas Schuh
f1ea012a41 fix: Import with or without gflags:: namespace 2018-09-28 16:28:33 +01:00
Andreas Schuh
b0c4cd29e4 fix: Define both 'gflags' and 'gflags::gflags' alias targets 2018-09-28 16:28:33 +01:00
Andreas Schuh
04c8ce76e2 fix: Indentation, use spaces instead of real tabs 2018-09-28 16:00:51 +01:00
Andreas Schuh
d4a050d173
Merge pull request #247 from Mizux/master 2018-09-28 14:52:29 +01:00
wuchenghui
48677f930d fix missing-field-initializers warnings on gcc 2018-09-28 14:50:39 +01:00
drillsar
6e536553ef Fix V728 excessive check 2018-09-28 14:49:19 +01:00
kokerf
cad38c919c Set postfixes for generated libraries based on buildtype 2018-09-28 13:23:32 +01:00
Matt Hargett
2c49763b73 Fix build on some clang variants
Some platforms' yval.h defines restrict as a macro when using clang, which causes this file to not compile.
2018-09-28 13:21:24 +01:00
Andreas Schuh
660603a3df doc: Update documentation on how to use Bazel 2018-07-05 23:24:35 +01:00
Andreas Schuh
679df49798 Merge branch 'gh-pages' of github.com:gflags/gflags into gh-pages 2018-07-05 23:23:36 +01:00
Andreas Schuh
48cdc79332 doc: Use of Bazel bind discouraged 2018-07-05 23:23:21 +01:00
Sam Liu
518267d34f Remove installation guide's recommendation to use Bazel's bind(). 2018-07-05 23:17:28 +01:00
Corentin Le Molgat
f7228d77b5 Use CMake namespace gflags:: for export and alias target
Now use gflags::gflags instead of gflags

note: seems already in use in gRPC
cf https://github.com/grpc/grpc/blob/master/cmake/gflags.cmake#L30
2018-01-31 13:46:59 +01:00
Corentin Le Molgat
8b39845d6f Remove uneeded enable_test()
cf https://gitlab.kitware.com/cmake/cmake/blob/master/Modules/CTest.cmake#L88
2018-01-31 13:40:42 +01:00
Corentin Le Molgat
9ab4d115cb Add VERSION to project 2018-01-29 14:00:35 +01:00
Rob Earhart
e292e0452f Use += for appends 2018-01-07 10:40:06 +00:00
Rob Earhart
6d1c363dde Add Bazel-on-Windows support 2018-01-07 10:40:06 +00:00
Silver Chan
77592648e3 repair wrong namespace problem
repair wrong namespace problem
2017-11-03 12:21:22 +00:00
Sumit Gupta
23348465a0 Removed unused functions. 2017-10-08 10:52:46 +01:00
Yi Wang
60784b53e3 Remove using ::fLS::clstring; 2017-09-01 11:12:50 +02:00
Andreas Schuh
57ceb0ecc8 enh: Move CMake defines to separate header, unused by Bazel
This change avoids having to configure a private .h.in file during the Bazel build such that these files are not available to dependent projects in the GENDIR of the external gflags project.
2017-09-01 11:10:03 +02:00
Siddhartha Bagaria
7d36353579 Fix typo in BUILD 2017-08-29 14:51:00 +02:00
Andreas Schuh
aa2d0f7b4e fix: Remove obsolete and unused CleanFileName code 2017-07-13 16:28:54 +01:00
Jason Juang
4663c80d3a cmake: Add convenience uninstall target (#221)
Note: Leaves behind empty directories, no real uninstaller. Just for convenience of some.
2017-07-11 22:22:41 +01:00
Andreas Schuh
46f73f88b1 Release v2.2.1 2017-07-11 18:30:34 +01:00
Andreas Schuh
66d4386d0e enh: AppVeyor builds with different toolchains (copied from gtest project) 2017-07-11 17:47:32 +01:00
Andreas Schuh
6348ea9d7e fix: Check HAVE_STDINT_H or HAVE_INTTYPES_H for older MSVC versions 2017-07-11 17:47:32 +01:00
Andreas Schuh
3d5bc48dc8 git: Ignore symbolic links created by Bazel build tool 2017-07-11 15:32:24 +01:00
Andreas Schuh
74603f5ed3 fix: Static code analyzer error regarding strncmp with empty kRootDir string 2017-07-11 14:47:40 +01:00
Ben Vanik
4a694e8736 Use inttypes.h on VC++ 2013 and up
Warnings will spit out on newer compilers due to PRI* being redefined.
Tested with VC++ 2015 and 2017. [Blog post](https://blogs.msdn.microsoft.com/vcblog/2013/07/19/c99-library-support-in-visual-studio-2013/) describing the defines being added in 2013.
2017-05-16 11:37:59 +01:00
randomguy3
21c7bcd895 Fix CMake macro special variable usage (#216)
The argument-related variables in a macro body are not real variables,
but special substitutions. They cannot be directly referred to by name,
only expanded.
2017-05-16 11:35:11 +01:00
Mmanu Chaturvedi
95ffb27c9c Fix static initialization order fiasco caused by global registry lock (#215) 2017-05-12 22:11:28 +01:00
Arkady Shapkin
80ebb424a5 Install dll's to correct path (#213) 2017-05-11 13:02:21 +01:00
Arkady Shapkin
652651b421 Fix statically linked gflags library with MSVC
Fix #211
2017-05-06 01:47:54 +01:00
Dan Minor
9314597d4b Mark single argument constructors in mutex.h as explicit. 2017-03-29 13:01:34 +01:00
Razvan Musaloiu-E
48f409438b Removed the unused link to #varz 2017-01-06 11:53:05 +00:00
Geoffrey Lalonde
30dbc81fb5 Changed include directory in bazel build 2017-01-06 11:46:43 +00:00
Andreas Schuh
8935ef4526 enh: Link to online documentation in README 2016-11-29 10:33:53 +00:00
Andreas Schuh
20858a49e0 fix: Enable language C for older CMake versions when needed (#196)
* fix: Enable language C for older CMake versions when needed
* fix: Don’t care about buggy Android toolchain
2016-11-26 21:55:33 +00:00
Andreas Schuh
ac6834e979 fix: Remove unused program_name variable 2016-11-26 21:25:02 +00:00
Andreas Schuh
22ed2ce6c8 fix: Include utils by file instead of CMAKE_MODULE_PATH search 2016-11-26 16:01:46 +00:00
Andreas Schuh
f8a0efe03a Release v2.2.0 2016-11-25 18:54:37 +00:00
Andreas Schuh
2f336a2a87 doc: //external:gflags_nothreads Bazel target 2016-11-25 18:54:37 +00:00
Andreas Schuh
971dd2a4fa doc: Bazel gflags_nothreads target 2016-11-25 18:48:27 +00:00
Andreas Schuh
c6b937797c git: Ignore builds/ subdirectory 2016-11-25 18:10:51 +00:00
Andreas Schuh
84ab952375 doc: Update use of gflags with Bazel documentation 2016-11-25 18:10:19 +00:00
Andreas Schuh
78c66b3726 doc: Add section on how to use gflags with Bazel 2016-11-25 18:09:44 +00:00
Andreas Schuh
b872d6b5d4 enh: Bazel BUILD, add WORKSPACE file (#192) 2016-11-25 17:37:38 +00:00
Andreas Schuh
37c4c58371 add: Bazel WORKSPACE file 2016-11-25 17:18:01 +00:00
Andreas Schuh
37e2867335 enh: Refactored Bazel BUILD rules 2016-11-25 17:18:01 +00:00
Andreas Schuh
8f2c22a03f Revert "enh: Rename private sources, include public headers with rel path" 2016-11-25 13:53:24 +00:00
Andreas Schuh
ea6144e243 enh: Rename private sources, include public headers with rel path 2016-11-25 12:38:54 +00:00
Andreas Schuh
86d67a3f49 fix: Add -lpthread to link Bazel BUILD options (#189)
* fix: Add -pthread link option to Bazel BUILD file
* fix: Use -lpthread instead of -pthread
2016-11-25 09:10:09 +00:00
Andreas Schuh
c94a60e2f6 enh: Configure and install pkg-config .pc file 2016-11-25 08:58:30 +00:00
Andreas Schuh
3e7ef74a07 enh: Set GFLAGS_IS_A_DLL in INTERFACE_COMPILE_DEFINITIONS 2016-11-25 08:30:21 +00:00
Andreas Schuh
18469830ae fix: Ensure installation path uses forward slashes 2016-11-24 23:30:55 +00:00
Andreas Schuh
3886da50e1 enh: Add option to add installation to CMake’s package registry 2016-11-24 23:30:55 +00:00
Andreas Schuh
6c0ee003e8 fix: Copy missing IMPORTED_IMPLIB_<CONFIG> gflags target property 2016-11-24 23:23:23 +00:00
Andreas Schuh
3064f63a6e enh: Avoid use of install(EXPORTS) FILE option 2016-11-24 22:42:59 +00:00
Todd Lipcon
14c0e93755 Convert dashes to underscores for unknown flags (#177) 2016-11-22 00:11:14 +00:00
David Lam
cce68f0c9c Fix error messages to not truncate to 255 characters (#175) 2016-10-05 08:25:50 +01:00
Andreas Schuh
f4eace1331 fix: Validate modified flags only once (#173) 2016-09-17 17:17:24 +01:00
田欧
408061b469 fix make error for lacking namespace (#170) 2016-08-31 06:39:41 +01:00
Aaryaman Sagar
7d31c02de8 Fix unsigned comparison error in gflags_reporting.cc (#168) 2016-08-24 18:03:08 +01:00
Dreamer
a69b2544d6 Fix Windows linker errors and warnings. (#166) 2016-08-03 08:25:38 +01:00
Dreamer
15394d356c Add shared library build to the AppVeyor CI config. (#167) 2016-08-03 08:24:55 +01:00
Dreamer
e58e5303d6 Remove filter for excluded tests from AppVeyor config. (#165) 2016-08-02 12:28:57 +01:00
Andreas Schuh
435f949dbb test: Travis CI build static+shared in Release+Debug (#164) 2016-08-02 12:24:34 +01:00
Andreas Schuh
22e4a534c1 fix: Run strip_flags_binary test only for release configurations (#163) 2016-08-02 12:15:44 +01:00
Dreamer
c713d2e789 test: Run AppVeyor build via cmake --build and run tests. (#162) 2016-08-02 12:00:16 +01:00
Andreas Schuh
b16653edf0 fix: Typo in gflags_strip_flags_test.cmake script 2016-08-02 09:51:47 +01:00
Andreas Schuh
ec4b5daadf doc: Add AppVeyor status badge to README
[ci skip]
2016-08-01 20:04:43 +01:00
Dreamer
f0be9c88ca Add initial AppVeyor config. (#161) 2016-08-01 19:57:54 +01:00
Andreas Schuh
78cab6c649 doc: Add Travis CI status badge to README 2016-08-01 17:05:26 +01:00
Dreamer
4667f41317 Enable Travis CI for Linux and OSX builds (#160) 2016-08-01 17:01:18 +01:00
Andreas Schuh
a5a1b28767 Merge pull request #158 from dreamer-dead/use-type-name-enum
Use enum to specify flag value type.
2016-08-01 15:10:29 +01:00
dreamer.dead
7ba9921866 Fix wrong type comparison and outdated OfType() usage. 2016-08-01 16:45:49 +03:00
dreamer.dead
30519426c3 Fix indentation and remove outdated assert. 2016-08-01 15:47:46 +03:00
dreamer.dead
3c0ad4fc9e Extract common code from FlagRegisterer to reduce size. 2016-08-01 14:52:26 +03:00
dreamer.dead
a1e461d61d Change template FlagValue::OfType() to Type() getter. 2016-08-01 14:51:11 +03:00
dreamer.dead
46ea10f071 Do not pass flag type as a char literal when registering a new flag.
It is possible to create a type-safe version of FlagRegisterer
ctor (as well as some internal gflags classes), that will deduce
type of the new flag automatically.

This results in removing quite a few calls to strcmp() when new
flag is created.

No existing behavior change.
2016-07-29 21:02:29 +03:00
Andreas Schuh
fe57e5af4d Merge pull request #156 from dreamer-dead/fix-flag-value-typename
Fix incorrect flag value typename for uint32.
2016-07-20 10:24:14 +01:00
dreamer.dead
fa2663839c Fix unittests expectations related to uint32. 2016-07-20 12:18:08 +03:00
dreamer.dead
5ef4c3c076 Fix uint32 type name. 2016-07-20 12:16:34 +03:00
Andreas Schuh
2e4159fbe5 Merge pull request #155 from dreamer-dead/add-missing-reference
Add missing reference symbol to a function parameter.
2016-07-18 17:09:53 +01:00
dreamer.dead
3e946c9ebc Add missing reference symbol to a function parameter. 2016-07-18 18:44:20 +03:00
Andreas Schuh
546819b1d9 Merge pull request #152 from Liuchang0812/master
fix: Consider Windows-style LRLF in flag parsing
2016-06-28 12:15:02 +01:00
liuchang0812
0c17f1ee02 fix bug about LRLF 2016-06-28 17:57:02 +08:00
Andreas Schuh
ac1a925c2b fix #151: Ubuntu package name in INSTALL instructions 2016-06-01 12:00:42 +01:00
Andreas Schuh
d701ceac73 Merge pull request #150 from LuminateWireless/fix-bazel-build
Fix bazel build
2016-05-10 22:45:26 +01:00
Ming Zhao
7ae23fd1e7 Add gendir to the include path so that building with bazel doesn't
complain config.h can't be found.
2016-05-10 14:42:11 -07:00
Andreas Schuh
8de80b9a2d Merge pull request #149 from hevy-CC4477/master
Add GFLAGS_IS_A_DLL compile option for unit test which includes private config.h.
2016-04-26 15:46:56 +01:00
FARBOS Arnaud
eff38cbc18 fix test compilation 2016-04-26 15:05:53 +02:00
Andreas Schuh
9353bca5e9 Merge pull request #147 from bazineta/master
Support uint32 as flag type
2016-04-06 11:55:47 +01:00
Allan L. Bazinet
81d8a9234b Correct FV_MAX_INDEX 2016-04-05 10:56:57 -07:00
Allan L. Bazinet
eaf05340dc Support uint32 as flag type
From #99, “Given that there is an unsigned flag type for 64-bit
integers, it is probably reasonable to request/expect the same for
32-bit integers.”
2016-04-05 10:50:21 -07:00
Andreas Schuh
74bcd20c0e Merge PR #137 with change of SOVERSION to <major>.<minor> 2016-03-04 10:12:01 +00:00
Andreas Schuh
45341954bc fix: Change SOVERSION to <major>.<minor> for 2.x release versions 2016-03-04 10:11:39 +00:00
Andreas Schuh
5e3070670f Merge pull request #143 from schuhschuh/fix-bazel-bulid-osx
fix #133: Use awk instead of sed which would require different options on OS X
2016-03-02 17:53:32 +00:00
Andreas Schuh
687b2c56d2 fix #133: Use awk instead of sed which would require different options on OS X 2016-03-02 17:52:19 +00:00
Andreas Schuh
58441994df Merge pull request #142 from schuhschuh/master
mod: Update doc with new find_package COMPONENTS or subproject use
2016-03-01 22:01:54 +00:00
Andreas Schuh
1c8285fd63 mod: Update doc with new find_package COMPONENTS or subproject use 2016-03-01 22:01:29 +00:00
Andreas Schuh
ea1cc83b50 doc: Use of find_package COMPONENTS or inclusion as subproject 2016-03-01 22:00:58 +00:00
Andreas Schuh
12d810d8e6 Merge pull request #141 from schuhschuh/master
Fix build of unit test on Ubuntu/Windows by changing include order
2016-03-01 21:35:48 +00:00
Andreas Schuh
389ef3f737 Merge branch 'master' of github.com:gflags/gflags 2016-03-01 21:34:32 +00:00
Andreas Schuh
752c63249b fix: Include order of config.h and gflags.h in unit test 2016-03-01 21:34:24 +00:00
Andreas Schuh
f9e69b3531 Merge pull request #140 from schuhschuh/enh-#117-gflags-subproject-support
These changes improve the CMakeLists.txt of the gflags project to make CMake variables configurable via command-line option -D or super-project settings. Moreover, gflags related variables are only added to the CMake cache when the gflags project is configured as a standalone project. When it is a subproject (cf. #117), the super-project is responsible for setting the configuration variables.

This change set also changes the names of the (exported) target names to gflags[_nothreads]_(static|shared) and the CMake (package) configuration variable names to start with an uppercase prefix "GFLAGS_".
2016-03-01 21:33:41 +00:00
Andreas Schuh
7a21c16f00 cmake: Rename targets to gflags[_nothreads]_(static|shared), support
find_package COMPONENTS
2016-03-01 21:04:10 +00:00
Andreas Schuh
a4382e5f37 cmake: Require CMake 2.8.12 in NC tests 2016-03-01 21:03:05 +00:00
Andreas Schuh
2de6bf3904 cmake: Change CMake package configuration variable name prefix to GFLAGS_ 2016-03-01 20:12:34 +00:00
Andreas Schuh
91e16eeff1 cmake: Add CMake variable to cache only when gflags is not a subproject
This change allows the user to include the gflags project as subtree/
submodule in their own project. In this case, no CMake variables used
to configure the build and installation of the gflags library should be
added to the CMake cache.
2016-03-01 20:12:34 +00:00
Andreas Schuh
b686469597 git: Add CMakeLists.txt.user Qt Creator configuration to ignore list 2016-03-01 20:10:22 +00:00
Andreas Schuh
e50698c200 Merge pull request #139 from schuhschuh/master
Fix compilation of unittest on Ubuntu
2016-03-01 19:59:53 +00:00
Andreas Schuh
18cb422451 fix: Require CMake version 2.8.12 in test project 2016-03-01 19:56:54 +00:00
Andreas Schuh
799e910c74 fix: Include private config.h in gflags_unittest.cc 2016-03-01 19:56:02 +00:00
Andreas Schuh
abe4b10c33 fix: Package URLs 2016-03-01 16:01:45 +00:00
Andreas Schuh
221f327749 Revert "#136 Move test binaries to Testing/bin"
This reverts commit 02f3189788.
2016-02-29 19:30:58 +00:00
Andreas Schuh
2a3454c104 fix: DLL import/export defines for unit tests, remove obsolete config_for_unittests.h 2016-02-29 19:18:21 +00:00
Andreas Schuh
545e9df567 fix: Add missing include guards to gflags/config.h 2016-02-29 19:17:00 +00:00
Andreas Schuh
6bd636c964 cmake: Clean up static library filename suffix code from PR #126 2016-02-29 17:58:46 +00:00
Andreas Schuh
dd48d704c5 Merge pull request #126 from hevy-CC4477/master
Use ```_static``` suffix in filename of static library on Windows to distinguish it from the import library.
2016-02-29 17:54:40 +00:00
Andreas Schuh
9ef0d5220e enh: Add usage of DEFINE_validator to test project 2016-02-29 17:12:15 +00:00
Andreas Schuh
02f3189788 #136 Move test binaries to Testing/bin 2016-02-29 17:03:08 +00:00
Andreas Schuh
92865cee87 #51 #138 Use std::string instead const char * for global "constants" 2016-02-29 16:15:11 +00:00
Andreas Schuh
8ac4bc41aa fix: Pass std::string directly, no need for c_str() call 2016-02-29 16:12:33 +00:00
Evan Klitzke
b90a325ef3 properly export the .so minor version 2016-02-27 12:36:14 -08:00
Andreas Schuh
3ae911f3e7 mod: Update doc 2016-02-19 13:43:45 +00:00
Andreas Schuh
16651b7870 #115 Use HTTPS as default Git clone protocol 2016-02-19 13:43:27 +00:00
Andreas Schuh
762f9cbb65 #51 Call ShutDownCommandLineFlags for (manual) valgrind test 2016-02-19 13:20:40 +00:00
Andreas Schuh
7a69001868 #51 Use static StringFlagDestructor to destruct string objects allocated by placement new 2016-02-19 12:59:05 +00:00
Andreas Schuh
3f968fc16b Merge pull request #133 from earhart/master
Add Bazel build support
2016-02-19 09:50:17 +00:00
Rob Earhart
40b85b18de Add bazel support 2016-02-18 18:28:31 -08:00
Andreas Schuh
f9fa30506c Merge pull request #131 from sbc100/no_threads
Define NO_THREADS when building without threads
2016-02-12 17:44:56 +00:00
Sam Clegg
b572a72daa Define NO_THREADS in when building without threads
Previously NOTHREADS was being defined but the code
in mutex.h checks for NO_THREADS.
2016-01-29 16:09:43 -08:00
Andreas Schuh
03bebcb065 Merge pull request #129 from Nazg-Gul/master
Resolve some compiler warnings
2016-01-12 13:30:13 +00:00
Sergey Sharybin
366e9d335c Fix some compilation warnings with MSVC 2015
MSVC 2015 already defines vsnprintf() and va_copy().
2015-12-31 17:16:26 +05:00
Sergey Sharybin
4f100cb6a0 Resolve several missing declarations warnings 2015-12-31 17:09:59 +05:00
Arnaud Farbos
d78b00d2de handle generation of dynamic and static library on windows. 2015-11-05 12:03:37 -08:00
Andreas Schuh
9db828953a #125 Fix unused typedef/variable warning for static assertion 2015-10-28 00:19:33 +00:00
Andreas Schuh
4e61c45ef9 #124 Remove using namespace from mutex.h 2015-10-27 23:00:58 +00:00
Andreas Schuh
f0523f14a9 Merge pull request #116 from KjellSchubert/vs2015
Fix build with MS VS 2015 RC
2015-05-20 00:37:42 +01:00
Kjell Schubert
4a56d614cf support for msvs 2015 2015-05-19 16:01:38 -07:00
Andreas Schuh
58345b18d9 #113 Require CMake >= 2.8.12
Earlier version, such as CMake 2.8.11.2 in particular, have incomplete or faulty support of target_include_directories generator expressions. Moreover, this allows us to assume that the command target_include_directories is available.
2015-04-03 16:12:38 +01:00
Andreas Schuh
d4e971c10b #112 Use HTTPS protocol for "doc" submodule to not require SSH authentication 2015-03-31 15:53:18 +01:00
Andreas Schuh
16a168763e #106 Add test of gflags-config.cmake package configuration 2015-03-25 13:54:49 +00:00
Andreas Schuh
f4f524df1f #110 Set gflags_LIBRARIES to value of gflags_TARGET instead of "gflags" 2015-03-25 03:17:36 +00:00
Andreas Schuh
73178f0051 #110 Update CMake example on how to link against gflags library 2015-03-25 03:13:56 +00:00
Andreas Schuh
e1d15b3340 doc: Use "gflags" as link dependency instead of ${gflags_LIBRARIES} 2015-03-25 03:13:22 +00:00
Andreas Schuh
ed1d91f912 #110 Add "gflags" import target and gflags_TARGET
The gflags_TARGET variable contains the name of the originally exported import target. The "gflags" import target contains a copy of the relevant properties of this import target created by CMake. The gflags_LIBRARIES variable can be used to be consistent with other packages, but is otherwise no longer needed. In most cases, "target_link_libraries(foo gflags)" should be used.
2015-03-25 03:07:04 +00:00
Andreas Schuh
71c656e0e9 #108 Use PROJECT_BINARY_DIR in place of gflags_BINARY_DIR 2015-03-25 00:14:46 +00:00
Andreas Schuh
73b67041d8 #107 Correct description of GFLAGS_INCLUDE_DIR 2015-03-25 00:02:22 +00:00
Andreas Schuh
2e5b884fce #107 Document remaining CMake cache entries 2015-03-25 00:00:50 +00:00
Andreas Schuh
7eb3d365e3 #105 Modify negative compilation tests to link against gflags_LIBRARIES 2015-03-24 23:45:21 +00:00
Andreas Schuh
ccff5658e0 #108 Fix temporary directory configuration of negative compilation tests 2015-03-24 23:44:34 +00:00
Andreas Schuh
33fc9997bd #104 Fix compilation of tests 2015-03-24 23:43:53 +00:00
Andreas Schuh
c3fd5432c3 mod: Update gh-pages with correct GitHub organization URLs and CMake example 2015-03-24 23:31:34 +00:00
Andreas Schuh
745082dbd3 fix: Example CMake command 2015-03-24 23:09:53 +00:00
Andreas Schuh
73bb1e87c9 fix: GitHub URLs to point to gflags organization 2015-03-24 23:07:20 +00:00
Andreas Schuh
5f29c4b940 mod: Update gh-pages with documentation of config options 2015-03-24 19:13:46 +00:00
Andreas Schuh
d7a69edf66 doc: Update CMake example and demonstrate use of config options 2015-03-24 19:13:18 +00:00
Andreas Schuh
9e937e80fb #105 Add gflags_SHARED and gflags_NOTHREADED gflags-config.cmake options 2015-03-24 18:55:17 +00:00
Andreas Schuh
a9b983a827 #104 Fix library include directories settings 2015-03-24 18:54:30 +00:00
Andreas Schuh
f9e1ffaa39 doc: Correct year in README 2015-03-24 17:48:29 +00:00
Andreas Schuh
a4bae965eb doc: Spelling correction 2015-03-24 17:07:00 +00:00
Andreas Schuh
14e1138441 mod: Change URL of gh-pages submodule to use GitHub gflags community repo 2015-03-24 17:04:08 +00:00
Andreas Schuh
2861b1c269 doc: Add ChangeLog entries for release 2.1.2 2015-03-24 16:36:13 +00:00
Andreas Schuh
06ccc16dec doc: Update README 2015-03-24 16:35:19 +00:00
Andreas Schuh
a819f0f019 fixup: Package configuration 2015-03-24 16:29:31 +00:00
Andreas Schuh
64ac2e30b6 fix: Extension of README file for PackageMaker 2015-03-24 16:21:44 +00:00
Andreas Schuh
51f1db7431 #101 Enable C language again as long as FindThreads requires it
This avoids having patched CMake modules in the source tree of the gflags library. Usually a C compiler is installed along a C++ compiler (or it is used for C as well). The only slight downside is the extra configuration time needed by CMake to check the C compiler.
2015-03-24 15:36:26 +00:00
Andreas Schuh
35fcdb3b2f mod: Update gh-pages 2015-03-24 15:05:08 +00:00
Andreas Schuh
3398e7b0c9 doc: Remove no longer needed include_directories command from CMake example 2015-03-24 15:04:35 +00:00
Andreas Schuh
13cf9e1b39 doc: Readding doc submodule 2015-03-24 14:59:51 +00:00
Andreas Schuh
afbf3f22ff fix: Remove accidentally added gh-pages files 2015-03-24 14:48:59 +00:00
Andreas Schuh
7fc7826cc1 Merge branch 'master' of github.com:schuhschuh/gflags 2015-03-24 14:45:05 +00:00
Andreas Schuh
4b771465b1 cmake: Set version of master branch to next release version 2015-03-24 14:44:57 +00:00
Andreas Schuh
76c53b710e #104 Set INTERFACE_INCLUDE_DIRECTORIES of (imported) targets 2015-03-24 14:44:12 +00:00
Andreas Schuh
2b8deaa5e0 fix: File paths and package URLs 2015-03-24 14:41:52 +00:00
Andreas Schuh
7b5b080a06 #103 Silence CMake warning regarding CMP0042 (MACOS_RPATH) 2015-03-24 14:41:10 +00:00
Andreas Schuh
64cf9f3249 Merge branch 'update-cmake-example' 2015-03-24 14:40:11 +00:00
Andreas Schuh
67dc01d3e0 Merge branch 'master' of github.com:schuhschuh/gflags into update-cmake-example 2015-03-24 14:39:48 +00:00
Andreas Schuh
04c73f86c3 doc: Remove no longer needed include_directories command from example 2015-03-24 14:39:43 +00:00
Andreas Schuh
02e8c78f9d doc: Spelling correction 2015-03-24 13:21:35 +00:00
Andreas Schuh
957aa3aa62 doc: Add download and issue report instructions to project page 2015-03-24 13:13:50 +00:00
Andreas Schuh
0133710d47 add: Common build directory names to ignore list 2015-03-24 12:59:56 +00:00
Andreas Schuh
d8d218ac6f doc: Add gh-pages branch as submodule in doc directory 2015-03-24 12:58:23 +00:00
Andreas Schuh
957f0d291c add: .nojekyll file 2015-03-24 12:55:52 +00:00
Andreas Schuh
63b9776eee fix: Rename documentation HTML file to index.html 2015-03-24 12:55:31 +00:00
Andreas Schuh
3a49eafd20 add: Files from doc/ directory of master branch 2015-03-24 12:51:30 +00:00
Andreas Schuh
6e390924d3 Merge branch 'feature/#83-alternative-namespace' 2015-03-24 12:42:53 +00:00
Andreas Schuh
2614f123fd doc: Convert INSTALL instructions to Markdown 2015-03-24 12:41:43 +00:00
Andreas Schuh
eb89101a1a doc: Replace README by previous NEWS in Markdown format 2015-03-24 12:34:22 +00:00
Andreas Schuh
2a40e19137 cmake: Add advanced cache entries for GFLAGS_NAMESPACE and GFLAGS_INCLUDE_DIR 2015-03-24 12:33:52 +00:00
Andreas Schuh
376ef823be cmake: Do not cache GFLAGS_NAMESPACE and GFLAGS_INCLUDE_DIR.
These CMake variables are now set to a default which both maintains binary backwards compatibility with previous versions of the library, but at the same time allows already the use of the new "gflags" namespace instead of "google". Users may still override the default using the -D option of cmake, for example, when they use the library directly as submodule in their own project and prefer a different namespace/installation directory.
2014-07-17 11:21:36 +01:00
Andreas Schuh
76cbe0d003 Change default GFLAGS_NAMESPACE to "google;gflags" and add GFLAGS_INCLUDE_DIR with default "gflags" to cache.
This ensures binary compatibility with previous 2.x release versions while allowing users to refer to the gflags library symbols using the preferred "gflags" namespace identifier.
2014-07-17 02:45:50 +01:00
Andreas Schuh
2b81a76bed fix: Include guard of alternative "gflags" namespace header. 2014-07-17 02:14:41 +01:00
Andreas Schuh
659b440f9e Support alternative namespaces in GFLAGS_NAMESPACE CMake variable.
The first element in the GFLAGS_NAMESPACE list is used as primary/default namespace. The symbols are then imported from this primary namespace into each of the other alternative namespaces with the using keyword. This is in particular used to maintain backwards compatibility with previous gflags library versions that used the "google" namespace instead of the new default "gflags" namespace.
2014-05-02 14:56:58 +01:00
Andreas Schuh
a93de007a6 Define GFLAGS_NAMESPACE in public headers.
This avoids any mistakes where once @GFLAGS_NAMESPACE@ was used in public .h.in files, or the #define GFLAGS_NAMESPACE in internal source files.
2014-05-02 12:00:35 +01:00
Andreas Schuh
05b155ff59 Merge remote-tracking branch 'google/bugfix/#82-shared-library-versioning' 2014-05-02 11:13:18 +01:00
Andreas Schuh
cd7aece14e Use major version number only as SOVERSION. 2014-05-02 11:12:05 +01:00
Andreas Schuh
b8c6fef385 Merge remote-tracking branch 'google/bugfix/#82-shared-library-versioning' 2014-05-01 20:44:09 +01:00
Andreas Schuh
bf889786c2 Set VERSION property of library targets to <major>.<minor>. 2014-05-01 20:16:16 +01:00
Andreas Schuh
e160474c52 Merge remote-tracking branch 'google/develop' 2014-05-01 20:00:11 +01:00
Andreas Schuh
6828323bc6 Merge pull request #10 from ivaxer/doc-namespace-rename
doc: rename namespace from google (deprecated) to gflags (default)
2014-05-01 19:59:36 +01:00
Andreas Schuh
31f0e290d6 Use LIB_INSTALL_DIR to initialize LIBRARY_INSTALL_DIR.
In particular the Fedora package maintainers pass LIB_INSTALL_DIR instead of LIBRARY_INSTALL_DIR.
2014-05-01 19:58:25 +01:00
Andreas Schuh
3c30390ac4 Merge remote-tracking branch 'google/master' into develop 2014-05-01 19:49:53 +01:00
Andreas Schuh
e9144aa159 Make LIBRARY_INSTALL_DIR configurable by the user. 2014-05-01 19:49:24 +01:00
Andreas Schuh
44d1d163cc Merge pull request #9 from ivaxer/lib-suffix
Append LIB_SUFFIX to LIBRARY_INSTALL_DIR.
2014-05-01 19:40:03 +01:00
John Khvatov
d9d06b99a4 doc: rename namespace from google (deprecated) to gflags (default) 2014-05-01 05:21:38 +04:00
John Khvatov
55490439d0 cmake: append LIB_SUFFIX to LIBRARY_INSTALL_DIR 2014-05-01 04:11:54 +04:00
Andreas Schuh
e65f49a4cd Merge remote-tracking branch 'google/master' into develop 2014-04-07 17:09:39 +01:00
Andreas Schuh
dc2b2c7fec Merge pull request #8 from shawke/patch-1
Fix compatibility of CMakeCXXInformation.cmake module with older versions of CMake
2014-04-07 17:08:17 +01:00
shawke
cac974eb07 Fix compatibility with older versions of CMake
The "SONAME_FLAG" was introduced in CMake 2.8.9, while the current CMake scripts require 2.8.4 (first line of CMakeLists.txt). Increasing the required CMake version will block building in less recent OSes (e.g., for Ubuntu 12.04 LTS, the latest version from the official repositories is currently 2.8.7). The more compatible solution will be to use the old variable name, i.e. the one which was used before CMake was patched.

NB: this issue is triggered upon specifying -DBUILD_SHARED_LIBS=ON.

Related bug report: http://public.kitware.com/Bug/view.php?id=13884 
Commit which implemented this new variable: http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e1409ac5
2014-04-07 18:03:26 +02:00
Andreas Schuh
44a58145e3 Merge remote-tracking branch 'google/release' into develop 2014-03-30 15:44:24 +01:00
Andreas Schuh
07031f9703 Merge remote-tracking branch 'google/release' 2014-03-30 15:41:29 +01:00
Andreas Schuh
4003103499 Add ChangeLog entries for release 2.1.1. 2014-03-30 15:41:02 +01:00
Andreas Schuh
cf0619e458 Merge remote-tracking branch 'google/release' into develop 2014-03-30 15:35:13 +01:00
Andreas Schuh
eb3b78a4ff Merge remote-tracking branch 'google/release' 2014-03-30 15:34:40 +01:00
Andreas Schuh
ef5c5474b2 Set CPACK_PACKAGE_ARCHITECTURE to darwin on Mac OS. 2014-03-30 15:34:13 +01:00
Andreas Schuh
0890b699e9 Add NEWS of release version 2.1.1. 2014-03-30 15:18:26 +01:00
Andreas Schuh
eb5e1f7fe4 Bump version to 2.1.1. 2014-03-30 15:17:49 +01:00
Andreas Schuh
7bc160b304 Merge remote-tracking branch 'google/develop' into release 2014-03-30 15:16:35 +01:00
Andreas Schuh
dc8543a473 Add test which uses gflags_declare.h.
Update issue 79
Added a test which uses gflags_declare.h as any other project would use it to avoid such avoidable build configuration mistakes.
2014-03-30 15:16:00 +01:00
Andreas Schuh
9a257c0b66 Merge remote-tracking branch 'google/develop' into release 2014-03-30 14:46:28 +01:00
Andreas Schuh
94c23575c7 Update NEWS. 2014-03-27 01:45:47 +00:00
Andreas Schuh
0f2751ebfb Merge branch 'develop' of github.com:schuhschuh/gflags into develop 2014-03-27 01:30:30 +00:00
Andreas Schuh
020dc487c3 Merge branch 'refs/heads/bugfix/#77-@GFLAGS_IS_A_DLL@-expands-to-empty' into develop 2014-03-27 01:29:02 +00:00
Andreas Schuh
0c6e5fdb3f Add GFLAGS_INCLUDE_DIR CMake variable (Fixes issue #80).
Both GFLAGS_NAMESPACE and GFLAGS_INCLUDE_DIR can be used to customize the installation of the gflags library. One specifies the C++ namespace name of the gflags symbols, the other the include subdirectory path of the public header files. By default, both are set to "gflags", but other Google libraries still expect "google" as C++ namespace name, but not necessarily also include path.
2014-03-27 01:14:24 +00:00
Andreas Schuh
38c4402f58 Use GFLAGS_IS_A_DLL=1 in public headers if BUILD_SHARED_LIBS is enabled (Fixes issue #77). 2014-03-27 01:14:24 +00:00
Andreas Schuh
7c80cfd87c Remove devel package content summary from README 2014-03-27 01:11:30 +00:00
Andreas Schuh
30d045d0ec Merge remote-tracking branch 'google/feature/#80-configurable-include-path' into develop 2014-03-27 01:09:49 +00:00
Andreas Schuh
aff8ef820a Add GFLAGS_INCLUDE_DIR CMake variable (Fixes issue #80).
Both GFLAGS_NAMESPACE and GFLAGS_INCLUDE_DIR can be used to customize the installation of the gflags library. One specifies the C++ namespace name of the gflags symbols, the other the include subdirectory path of the public header files. By default, both are set to "gflags", but other Google libraries still expect "google" as C++ namespace name, but not necessarily also include path.
2014-03-27 01:09:20 +00:00
Andreas Schuh
38213112a5 Replace GFLAGS_NAMESPACE by @GFLAGS_NAMESPACE@ in gflags_declare.h (Fixes issue #79). 2014-03-26 19:37:01 +00:00
Andreas Schuh
4aa1984c51 Merge remote-tracking branch 'google/bugfix/#77-@GFLAGS_IS_A_DLL@-expands-to-empty' into develop 2014-03-26 19:33:24 +00:00
Andreas Schuh
6040eac5b3 Use GFLAGS_IS_A_DLL=1 in public headers if BUILD_SHARED_LIBS is enabled (Fixes issue #77). 2014-03-25 15:30:37 +00:00
Andreas Schuh
09f7800768 Use GFLAGS_IS_A_DLL=1 in public headers if BUILD_SHARED_LIBS is enabled (Fixes issue #77). 2014-03-25 15:29:56 +00:00
Andreas Schuh
bbe1895559 Remove devel package content summary from README 2014-03-22 01:00:11 +00:00
Andreas Schuh
3fd9fa7000 Resolve conflicts upon pull. 2014-03-20 21:25:35 +00:00
Andreas Schuh
cf40f73c40 Set package architecture to i386 when compiling with -m32. 2014-03-20 20:56:05 +00:00
Andreas Schuh
0e1c5ce039 Merge remote-tracking branch 'google/release' into develop 2014-03-20 20:29:11 +00:00
Andreas Schuh
2a9ef084a9 Merge remote-tracking branch 'google/hotfix/rpm-package-architecture' into release 2014-03-20 20:27:48 +00:00
Andreas Schuh
0c15028124 Merge remote-tracking branch 'google/hotfix/rpm-package-architecture' 2014-03-20 20:24:30 +00:00
Andreas Schuh
d699559081 Fix architecture used for RPM packages and DEB/RPM package file names. 2014-03-20 20:21:30 +00:00
Andreas Schuh
04a30c86de Merge remote-tracking branch 'google/release' into 'master'.
Conflicts:
	gflags-vs2003.sln
	gflags-vs2010.sln
	gflags-vs2012.sln
	vsprojects/gflags_unittest/gflags_unittest-vs2010.vcxproj
	vsprojects/libgflags/libgflags-vs2010.vcxproj
2014-03-20 16:37:14 +00:00
Andreas Schuh
882db5d018 Mention Git branching model in NEWS. 2014-03-20 16:35:30 +00:00
Andreas Schuh
33e2cbe2c6 Add release notes. 2014-03-20 16:32:54 +00:00
Andreas Schuh
3e96a19026 Change version to 2.1.0, i.e., use common semantic versioning system including patch number for bug fix releases. 2014-03-20 16:19:00 +00:00
Andreas Schuh
0100be50ec Add missing entry to ChangeLog for v2.1 release. 2014-03-20 16:15:10 +00:00
Andreas Schuh
76f2ffadb4 Add ChangeLog entries for v2.1 release. 2014-03-20 16:02:15 +00:00
Andreas Schuh
978c567d02 Ignore packages subdirectory (if it exists). 2014-03-20 04:43:01 +00:00
Andreas Schuh
06ad5027d2 Merge branch 'refs/heads/feature/cpack-package-generation' into develop 2014-03-20 04:38:03 +00:00
Andreas Schuh
a49a656f1e Use dpkg --print-architecture also for RPM generator. 2014-03-20 04:24:57 +00:00
Andreas Schuh
e8890f274a Set additional DEB CPack variables in package.cmake.in. 2014-03-20 04:20:15 +00:00
Andreas Schuh
fc6e079cfc Change package vendor to just a name. 2014-03-20 04:09:02 +00:00
Andreas Schuh
52bf642cf8 Remove brief description from README to avoid duplicate appearance in RPM and other packages. 2014-03-20 04:06:27 +00:00
Andreas Schuh
4b1ca7d5f1 Add missing year to ChangeLog entry. RPM is now generated successfully. 2014-03-20 03:53:50 +00:00
Andreas Schuh
4258af12b7 Remove separating lines from ChangeLog again. 2014-03-20 03:51:30 +00:00
Andreas Schuh
313e39e323 Add missing name to ChangeLog entry and further format changes. 2014-03-20 03:49:21 +00:00
Andreas Schuh
dc9674ee46 Remove time fields from ChangeLog entries which are not compatible with RPM spec. 2014-03-20 03:42:22 +00:00
Andreas Schuh
b6f61ab0ce Fix bugs in package configuration file. 2014-03-20 03:38:59 +00:00
Andreas Schuh
26a35dd2e4 Convert ChangeLog to format allowed in RPM spec. 2014-03-20 03:35:15 +00:00
Andreas Schuh
37a9a90d1d Set RPM CPack variables already in CMakeList.txt. 2014-03-20 03:27:13 +00:00
Andreas Schuh
516e028901 Set RPM generator specific variables. 2014-03-20 03:23:08 +00:00
Andreas Schuh
13fe86b8fe Correct CPack package description file. 2014-03-20 03:22:57 +00:00
Andreas Schuh
bf139ea0a8 Fix build of threaded library on Unix by adding the appropriate link library. 2014-03-20 03:04:44 +00:00
Andreas Schuh
cb62c00354 Change mode of text file. 2014-03-20 02:14:30 +00:00
Andreas Schuh
9ecc4cab3b Enable packaging of library using CPack. 2014-03-20 02:11:44 +00:00
Andreas Schuh
ec4ddb403a Revert "Added Git ignore file to prevent build files being seen as changed files"
This reverts commit fb21f3cca0.
2014-03-19 17:56:32 +00:00
Andreas Schuh
ddc5357419 Add link dependency on shlwapi.lib during build configuration instead of #pragma comment statement. Use this library also on MinGW. 2014-03-19 17:32:23 +00:00
Andreas Schuh
9242578bc1 Look for shlwapi.h also in case of MinGW. 2014-03-19 17:15:36 +00:00
Andreas Schuh
acb460af9e Use strtoll as defined by windows_port.h for strto64. 2014-03-19 16:53:19 +00:00
Andreas Schuh
41181669d1 Use OS_WINDOWS #define instead of _WIN32 and WINDOWS.
The OS_WINDOWS #define has previously been used in gflags.cc before the CMake migration.
2014-03-19 16:46:56 +00:00
Andreas Schuh
dbc09f12db Merge remote-tracking branch 'github/cmake-migration' 2014-03-19 16:08:35 +00:00
Andreas Schuh
13025b119f Remove GFLAGS_NAMESPACE and version macros from public headers again. 2014-03-19 16:05:02 +00:00
Andreas Schuh
0b116eb439 Simplify check for strtoll and strtoq. 2014-03-19 15:56:26 +00:00
Andreas Schuh
5250372ab6 Fix conditional compilation of tests using glob expressions. 2014-03-19 15:55:43 +00:00
Andreas Schuh
9d686e7107 Add .gitattributes file to normalize all files to LF. 2014-03-19 14:48:03 +00:00
unknown
3d142b88d7 Convert line endings to Unix format. 2014-03-19 15:27:08 +01:00
Andreas Schuh
8566bcf1eb Replace GFLAGS_HAVE_* #defines by HAVE_* again. 2014-03-19 14:24:52 +00:00
Andreas Schuh
6e9f41669e No need to export CommandLineFlagInfo data only structure from DLL. 2014-03-19 11:35:30 +00:00
Andreas Schuh
d8c6a552aa Fix bug in SafeFOpen showing up in Cygwin. Errno only guaranteed to be set on failure. 2014-03-19 11:29:43 +00:00
Andreas Schuh
b18fe77ecd Fix check for pthreads library on Ubuntu. 2014-03-18 22:39:59 +00:00
Andreas Schuh
b8f5717416 Add missing CheckTypeSizeMap.cmake.in file.
Copied from CMake master branch.
2014-03-18 22:06:13 +00:00
Andreas Schuh
492ac156bc Fix DLL build on Windows and use PathMatchSpec instead of fnmatch.
Expose as few system variables as possible through public interface.
Perform STRIP_FLAGS_HELP test using CMake instead of Bash.
Change file path separator used by gflags_reporting.cc to backslash on Windwos.
2014-03-18 22:03:10 +00:00
Andreas Schuh
cf92ec3bf0 Modify CheckTypeSize.cmake module so it works with older CMake versions. 2014-03-18 21:59:48 +00:00
Andreas Schuh
1e0b54c6ed Fix unit tests for Windows and CygWin. 2014-03-17 21:49:10 +00:00
Andreas Schuh
e491f0161d Add missing errno.h include statement and use int instead of errno_t. 2014-03-17 21:38:21 +00:00
Andreas Schuh
e31f179ae0 Fix up use of SafeFOpen. 2014-03-17 21:27:01 +00:00
Andreas Schuh
6b7be9a00a Enable test case which tests invalid negative value for uint64 flag. 2014-03-17 21:22:51 +00:00
Andreas Schuh
a0dca4df0c Create temporary directory for unit tests in specified --test_tmpdir if possible. 2014-03-17 21:21:59 +00:00
Andreas Schuh
eeb4db3234 Use _strtoi64 and _strtoui64 on Windows. 2014-03-17 21:21:21 +00:00
Andreas Schuh
107681258b Fix VS linker warning regarding locally defined FLAGS_tryfromenv symbol. 2014-03-17 21:20:24 +00:00
Andreas Schuh
8d3797cd15 Fix VS security warnings using SafeGetEnv and SafeFOpen utility functions. 2014-03-17 21:19:35 +00:00
Andreas Schuh
8d93bca20a Minor CMake coding style change of version_numbers function. 2014-03-17 21:16:31 +00:00
Andreas Schuh
0d9486f9a3 Pass --test_tmpdir and --srcdir to unittests. 2014-03-17 21:15:52 +00:00
Andreas Schuh
505686bd7a Require at least CMake 2.8.4 to avoid Cygwin legacy warning. 2014-03-17 20:54:48 +00:00
Andreas Schuh
c94e9bec36 Add missing execute_test.cmake script. 2014-03-17 16:12:56 +00:00
Andreas Schuh
bf918e630f Rename FindThreadsCXX module. 2014-03-17 13:44:03 +00:00
Andreas Schuh
33ee7ad6ef Fix typo in documentation and path of execute_test.cmake script. 2014-03-17 13:41:46 +00:00
Andreas Schuh
cb00fb9ec7 Remove obsolete set(GFLAGS_INTTYPES_FORMAT) call. 2014-03-17 13:39:10 +00:00
Andreas Schuh
c6a9986fa0 Minor style change to be consistent. 2014-03-17 13:39:10 +00:00
Andreas Schuh
7b63ae8f8a Fix preprocessor conditions to use new GFLAGS_* defines. 2014-03-17 13:33:26 +00:00
Andreas Schuh
9b3c4a81c2 Modify CheckCXXLibraryExists to use CMakeFiles directory. 2014-03-17 13:25:04 +00:00
Andreas Schuh
f1e7b37c48 Add CheckCXXLibraryExists.cmake module and use it in FindTreadsCXX.cmake. 2014-03-17 13:17:44 +00:00
Andreas Schuh
1b1b61d305 Fix previous change of FindThreadsCxx.cmake by copying needed source file from CMake installation, changing the file name extension only. 2014-03-17 12:38:41 +00:00
Andreas Schuh
c5627a75bc Use CheckForPthreads.cxx to find pthreads library on Ubuntu. 2014-03-17 12:35:28 +00:00
Andreas Schuh
6e4c22e982 Merge pull request #7 from andy-held/cmake-migration
Fix case in CMake module includes.
2014-03-17 12:16:26 +00:00
Andreas Franek
f479174573 * fixed letter case of included file names
* C language definition is needed for CheckForPthreads.c
2014-03-17 09:38:15 +01:00
Andreas Schuh
a4c4a01a37 Check if pthread_rwlock_t is available and use it if so. 2014-03-15 14:31:21 +00:00
Andreas Schuh
8477f3174e Fix build with Xcode 5, system checks, set LANGUAGE to CXX. 2014-03-15 14:15:33 +00:00
Andreas Schuh
f0f565fb0f Remove obsolete gflags_unittest.sh script. 2014-03-14 20:34:30 +00:00
Andreas Schuh
8a563cfca3 Migrate unit tests to CMake/CTest. Fix preprocessor directive in gflags_unittest.cc. 2014-03-14 20:32:37 +00:00
Andreas Schuh
15bc2d6c15 Issue #73 Merge gflags_config.h into gflags_declare.h. Configuration of gflags.h no longer needed. 2014-03-14 16:29:51 +00:00
Andreas Schuh
70eac23c1b Issue #73 Fix missing STL DLL export warnings of Visual Studio according to KB168958. 2014-03-14 16:08:52 +00:00
Andreas Schuh
b2180eb52c Fix build on Windows using Visual Studio. Add gflags_config.h. 2014-03-14 15:28:34 +00:00
Andreas Schuh
efc6908bce Add header files to add_library targets so they show up in IDEs. 2014-03-14 13:29:11 +00:00
Andreas Schuh
eb92d6edce Merge pull request #5 from Photonios/master
Add .gitignore for typical auxiliary files on Windows, renamed projects to match VS version, added x64 to VS2010.
2013-11-27 09:51:19 -08:00
Swen Kooij
38b662ab07 Renamed projects in VS2003 solution file to match the filename 2013-11-27 18:05:06 +01:00
Swen Kooij
2bd1aeeeb7 Renamed projects in VS2012 solution file to match the filename 2013-11-27 18:04:40 +01:00
Photonios
d0882077b3 Added configuration options for x64 to vs2010 solution/project file 2013-11-22 17:32:40 +01:00
Photonios
fb21f3cca0 Added Git ignore file to prevent build files being seen as changed files 2013-11-22 17:31:07 +01:00
Andreas Schuh
0c65228956 Minor update of README. 2013-11-06 20:56:03 +00:00
Andreas Schuh
3900860906 Ignore .DS_Store files of OS X. 2013-11-05 12:09:52 +00:00
Andreas Schuh
01d810e3c0 Be more specific about what to ignore. 2013-11-05 12:03:29 +00:00
Andreas Schuh
48316bd345 Merge pull request #3 from dominichamon/cmake-migration
Adding gitignore for generated files
2013-11-05 03:56:17 -08:00
Andreas Schuh
27c0c9ef79 Merge pull request #4 from daniperez/cmake-migration
Exporting binary tree to CMake registry
2013-11-04 16:56:31 -08:00
Dani Perez
459e529168 exporting binary tree to CMake registry
This eases integration with other applications making use
of gflags without needing to install it in the system.
find_package looks in the registry for existing software.
2013-10-22 23:03:27 +02:00
Dominic Hamon
99f52df612 Adding gitignore for generated files 2013-09-20 14:14:23 -07:00
Andreas Schuh
667c52be59 Remove reference to README_windows. 2013-08-01 03:53:59 +01:00
Andreas Schuh
3c0cd06b6d Document finding and linking to gflags using CMake. 2013-08-01 03:46:29 +01:00
Andreas Schuh
1c9f065dd0 Add negative compilation tests. 2013-08-01 03:31:47 +01:00
Andreas Schuh
7abcbdcbbd Add gflags library which is built with NO_THREADS definition. 2013-08-01 02:04:37 +01:00
Andreas Schuh
ac3cb02be8 Add missing unittest2 and unittest3 executables. 2013-08-01 01:59:32 +01:00
Andreas Schuh
126f36b826 Enable build and execution of tests again using CTest. 2013-08-01 01:47:13 +01:00
Andreas Schuh
620557ccbc Install Bash completion script. 2013-08-01 01:06:36 +01:00
Andreas Schuh
5564469b96 Give basic CMake based build instructions in INSTALL file. 2013-08-01 00:52:46 +01:00
Andreas Schuh
7a07439cf6 Set PACKAGE_VERSION_EXACT to FALSE if major.minor version is not equal to the requested version. 2013-08-01 00:27:40 +01:00
Andreas Schuh
2ec91bffad Move definition of configure_sources CMake function to utils module. 2013-08-01 00:17:53 +01:00
Andreas Schuh
ffbc1cea57 Use gflags as target name instead of PACKAGE_NAME to not make things unnecessarily generic. 2013-08-01 00:17:13 +01:00
Andreas Schuh
6ec7d7f81e Fix relative path to installation prefix in CMake config file. 2013-08-01 00:10:15 +01:00
Andreas Schuh
43a33dcd53 Install CMake config file inside lib/ directory on Unix. 2013-08-01 00:01:21 +01:00
Andreas Schuh
42a0018843 Configure and install CMake package configuration file to help find_package locate the gflags package. 2013-07-31 23:55:50 +01:00
Andreas Schuh
6f2a78a26f Fix configuration on Windows and add src directory to include path. 2013-05-22 11:02:04 +01:00
Andreas Schuh
4eb2cb223b Add missing windows portability definitions. 2013-05-22 00:06:08 +01:00
Andreas Schuh
f7e89ba9ea Move public header files to src/ subdirectory. Copy them to <prefix>/include/<ns>/ upon installation. 2013-04-21 03:38:25 +01:00
Andreas Schuh
3624d33ae5 Set CMAKE_BUILD_TYPE to Release by default. Require CMake >=2.8. 2013-04-21 03:09:43 +01:00
Andreas Schuh
392eb67dbf Add CMakeLists.txt and adapt source files accordingly. 2013-04-21 03:05:35 +01:00
Andreas Schuh
2eed08d94a Move public header files to separate subdirectory. 2013-04-21 00:11:52 +01:00
Andreas Schuh
5ed8ae17a9 Remove build tool related files, operating system packages, and move unit tests to separate subdirectory. 2013-04-21 00:06:37 +01:00
Andreas Schuh
4328de857d Update NEWS: Git repository hosted on GitHub.
git-svn-id: https://gflags.googlecode.com/svn/trunk@84 6586e3c6-dcc4-952a-343f-ff74eb82781d
2013-04-20 22:49:37 +00:00
Andreas Schuh
dba41e672c Test commit via git-svn, only adding blank lines to NEWS.
git-svn-id: https://gflags.googlecode.com/svn/trunk@83 6586e3c6-dcc4-952a-343f-ff74eb82781d
2013-04-20 22:14:36 +00:00
Andreas Schuh
45a53dea87 Add DEFINE_validator macro for convenient registration of a flag validator.
git-svn-id: https://gflags.googlecode.com/svn/trunk@82 6586e3c6-dcc4-952a-343f-ff74eb82781d
2013-04-20 18:35:34 +00:00
Andreas Schuh
8011f61247 Use static_cast to avoid comparison of signed and unsigned integer warning in util.h.
git-svn-id: https://gflags.googlecode.com/svn/trunk@81 6586e3c6-dcc4-952a-343f-ff74eb82781d
2013-01-14 15:11:53 +00:00
Andreas Schuh
f098a54822 Fix deprecation warnings of VC++ regarding strdup and unlink. Add solution files for VS 2010 and VS 2012.
git-svn-id: https://gflags.googlecode.com/svn/trunk@80 6586e3c6-dcc4-952a-343f-ff74eb82781d
2012-11-20 14:48:22 +00:00
Andreas Schuh
1235a6d519 Add "build/" subdirectory to ignore list.
git-svn-id: https://gflags.googlecode.com/svn/trunk@79 6586e3c6-dcc4-952a-343f-ff74eb82781d
2012-11-11 20:33:21 +00:00
Andreas Schuh
6b215b0a3a Use project name (gflags) within include guards to avoid conflict with gperftools as reported by chen3feng (issue #62, http://code.google.com/p/gflags/issues/detail?id=62).
git-svn-id: https://gflags.googlecode.com/svn/trunk@78 6586e3c6-dcc4-952a-343f-ff74eb82781d
2012-11-11 20:32:35 +00:00
Andreas Schuh
e88280ed85 Fix "invalid suffix on literal; C++11 requires a space between literal and identifier" errors as reported by http://code.google.com/p/gflags/issues/detail?id=54.
git-svn-id: https://gflags.googlecode.com/svn/trunk@77 6586e3c6-dcc4-952a-343f-ff74eb82781d
2012-05-29 15:19:11 +00:00
Craig Silverstein
8306eef3ec Fixed a typo in the email address.
git-svn-id: https://gflags.googlecode.com/svn/trunk@76 6586e3c6-dcc4-952a-343f-ff74eb82781d
2012-02-02 22:49:44 +00:00
Craig Silverstein
f18772936d Wed Jan 25 15:09:14 2012 Google Inc. <google-gflags@googlegroups.com>
* gflags: version 2.0
	* Changed the 'official' gflags email in setup.py/etc
	* Renamed google-gflags.sln to gflags.sln
	* Changed copyright text to reflect Google's relinquished ownership


git-svn-id: https://gflags.googlecode.com/svn/trunk@74 6586e3c6-dcc4-952a-343f-ff74eb82781d
2012-01-25 23:59:40 +00:00
Craig Silverstein
ec7c7a209d Tue Dec 20 19:48:57 2011 Google Inc. <opensource@google.com>
* google-gflags: version 1.7
	* Add CommandLineFlagInfo::flag_ptr pointing to current storage (musji)
	* PORTING: flush after writing to stderr, needed on cygwin
	* PORTING: Clean up the GFLAGS_DLL_DECL stuff better
	* Fix a bug in StringPrintf() that affected large strings (csilvers)
	* Die at configure-time when g++ isn't installed


git-svn-id: https://gflags.googlecode.com/svn/trunk@72 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-12-21 04:28:52 +00:00
Craig Silverstein
80912052d0 Clarify thread-safety comment for FlagSaver.
Tested:
blaze test base:commandlineflags_unittest

R=csilvers
DELTA=4  (3 added, 0 deleted, 1 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=3791


git-svn-id: https://gflags.googlecode.com/svn/trunk@71 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-12-01 01:58:29 +00:00
Craig Silverstein
be2da58d73 The last bit of rolling back commandlineflag categories:
remove the 'categories' field from CommandLineFlagInfo.  (Note
the code to fill this field was removed from
FillComandLineFlagInfo previously, so it's been an empty
string for some time now.)

R=ncalvin
DELTA=1  (0 added, 1 deleted, 0 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=3616


git-svn-id: https://gflags.googlecode.com/svn/trunk@70 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-11-03 23:37:01 +00:00
Craig Silverstein
2535e43dd2 Get rid of the old FlagRegisterer constructor.
R=jkline,georgevdd
DELTA=27  (0 added, 27 deleted, 0 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=3609


git-svn-id: https://gflags.googlecode.com/svn/trunk@69 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-11-03 23:28:30 +00:00
Craig Silverstein
c23c6c6fc8 Starting the rollback of flag categories.
I left in the old FlagRegisterer constructor.
I also left in 'categories' in CommandLineFlagInfo for now,
though I never use it.  I doubt anyone else does either, but I
want to minimize the number of ways this rollback can break
the build.  I will remove it in a subsequent CL.

R=ncalvin
DELTA=121  (28 added, 55 deleted, 38 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=3574


git-svn-id: https://gflags.googlecode.com/svn/trunk@68 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-11-03 23:25:32 +00:00
Craig Silverstein
17a627a413 Add a 'flag_ptr' field to CommandLineFlagInfo that points to the current storage of the flag (i.e. &FLAGS_foo).
R=csilvers
DELTA=15  (15 added, 0 deleted, 0 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=3301


git-svn-id: https://gflags.googlecode.com/svn/trunk@67 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-11-03 23:18:00 +00:00
Craig Silverstein
ee44191125 A user reported a bug that configure should die when g++ isn't
installed, but wasn't:
http://code.google.com/p/google-perftools/issues/detail?id=217

This turned out to be a bug in autoconf:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=357378

The workaround is simple: check for CXX before checking for
CC.  This means that if g++ is installed but gcc isn't, we
won't die (at cc-checking time), but I tested, and the
configure script dies later.  In any case, it seems unlikely
someone would have a c++ compiler installed but not a c
compiler.

This fixes the 4 opensource projects I work on that are
susceptible to this.

R=iant
DELTA=1437  (694 added, 694 deleted, 49 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=3222


git-svn-id: https://gflags.googlecode.com/svn/trunk@66 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-11-03 23:16:21 +00:00
Craig Silverstein
9bf7e65f08 Now I can get rid of the old constructor!
R=jkline,ncalvin
DELTA=28  (0 added, 27 deleted, 1 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=3169


git-svn-id: https://gflags.googlecode.com/svn/trunk@65 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-11-03 23:12:52 +00:00
Craig Silverstein
6b70a75081 http://code.google.com/p/google-gflags/issues/detail?id=45
reports that the error isn't always getting flushed on
cygwin.  So do that explicitly.

R=desovski
DELTA=1  (1 added, 0 deleted, 0 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=3140


git-svn-id: https://gflags.googlecode.com/svn/trunk@64 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-11-03 23:11:24 +00:00
Craig Silverstein
29f02f9896 Report category names via the xml help output (but not, yet,
during 'normal' help output).

R=ncalvin
DELTA=3  (3 added, 0 deleted, 0 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=3066


git-svn-id: https://gflags.googlecode.com/svn/trunk@63 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-11-03 23:09:49 +00:00
Craig Silverstein
10caa99e2d Add back in a backwards-compatible constructor for
FlagRegisterer.

Because this backwards-compatible API is intended to be
short-lived, I did it in the simplest, least invasive way
possible, which involved cutting-and-pasting.

R=ncalvin,jkline
DELTA=27  (27 added, 0 deleted, 0 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=3065


git-svn-id: https://gflags.googlecode.com/svn/trunk@62 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-11-03 23:09:19 +00:00
Craig Silverstein
874aed5db7 NOTE: I'm checking this in just to have a record in source control of the idea. We've decided for now it doesn't make sense to go forward with flag categories -- and the __VA_ARGS__ for macros has caused lots of problems with uncaught accidental commas, already -- so a future commit will back this out. (Actually, it's all a series of commits, for annoying technical reasons.)
Add support for flag categories.

In this CL, all you can do is set categories in the DEFINE_*
macros and then retrieve them via GetCommandLineFlagInfo and
similar.

In future CLs, we will start to give some semantic meaning to
particular flag values, as described in the designdoc.  In
particular, we will start to use flag categories to revamp
--help output.

Implementation-wise: to keep categories an optional macro
argument, I had to use __VA_ARGS__, which means future gflags
releases will no longer work with MSVC 7.1.  We're at MSVC 10
now, so I'm pretty much ok with that.

The downside of __VA_ARGS__ is there is no error if you
specify more args after the ones we expect.  To get around
that, I only use __VA_ARGS_ in this idiom:
static const OptionalDefineArgs var = { __VA_ARGS__ };
The new OptionalDefineArgs struct defines all the args that
may be optionally specified in the DEFINE_* macros.  For now,
that's only the 'categories' arg, though in theory more could be
added later.

R=titus,ncalvin
DELTA=92  (54 added, 3 deleted, 35 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=3057


git-svn-id: https://gflags.googlecode.com/svn/trunk@61 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-11-03 23:08:41 +00:00
Craig Silverstein
1b8e9bab5e Clean up the 'GFLAGS_DLL_DECL' stuff better: reduce use outside of windows/ directory.
R=jyrki
DELTA=33  (0 added, 27 deleted, 6 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=3016


git-svn-id: https://gflags.googlecode.com/svn/trunk@60 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-08-18 11:39:20 +00:00
Craig Silverstein
beb69a876b Fix a bug in StringPrintf() that caused it to not print large strings properly.
R=nilton
DELTA=1  (0 added, 0 deleted, 1 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=2886


git-svn-id: https://gflags.googlecode.com/svn/trunk@59 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-08-04 00:02:52 +00:00
Craig Silverstein
8233556d44 Add a new unittest case, that tests the --help output for a
really long helpstring.  Opensource gflags had a bug where we
were cutting off the output too soon; this test should protect
against such a thing.

R=nilton
DELTA=16  (16 added, 0 deleted, 0 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=2885


git-svn-id: https://gflags.googlecode.com/svn/trunk@58 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-08-04 00:02:39 +00:00
Craig Silverstein
404970d679 Ready to release gflags 1.6!
* google-gflags: version 1.6
* BUGFIX: Fix a bug where we were leaving out a required $(top_srcdir)
* Fix definition of clstring (jyrki)
* Split up flag declares into its own file (jyrki)
* Add --version support (csilvers)
* Update teh README for gflags with static libs
* Update acx_pthread.m4 for nostdlib
* Change REparseCommandLineFlags to return void (csilvers)
* Some doc typofixes and example augmentation (various)

R=jperkins
DELTA=44  (41 added, 0 deleted, 3 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=2838


git-svn-id: https://gflags.googlecode.com/svn/trunk@56 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-07-30 02:57:58 +00:00
Craig Silverstein
a923d3338e It turns out we don't want all this dll-decl stuff for mingw.
So make the #ifdef correct for mscv-but-not-mingw.

I think the right fix would be to take all this logic out and
insert it via a MOE directive, just for the windows versions
of these files.  This is what ctemplate does.  But it's a
more-major change, and I'm looking to get this release out
today, so I'm submitting this (TBR), since it's a much more
minor change.


Revision created by MOE tool push_codebase.
MOE_MIGRATION=2837


git-svn-id: https://gflags.googlecode.com/svn/trunk@55 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-07-30 02:55:58 +00:00
Craig Silverstein
357b3d9d0b mingw fixes:
1) mingw needs an #include to have access to mkdir.

2) It needs to always #include port.h (this is an identical
bit of code, in configure.ac, that I have in other opensource
projects for mingw support.)

3) I moved some code from port.cc to port.h, so I didn't have
to add logic to link in port.cc for mingw.

Last change before new release!  (*knock on wood*)  Submitting
TBR so I can get the release out today.  This isn't exactly a
trivial change, so I'm chary to submit TBR, but it's pretty
isolated to windows and mingw, and I've tested on those
platforms to make sure they compile and all tests pass.

DELTA=70  (37 added, 30 deleted, 3 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=2823


git-svn-id: https://gflags.googlecode.com/svn/trunk@54 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-07-29 22:49:50 +00:00
Craig Silverstein
b5cdac9950 A few autotools files that it loosk like aren't needed by the latest
version of autotools (taht we're using now).  Get rid of them to clean
up the svn tree.  Also get rid of the 'python' file -- I don't know
what that is, but it's been a long time since the python version of
gflags has moved to its own project.


git-svn-id: https://gflags.googlecode.com/svn/trunk@53 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-07-29 05:43:14 +00:00
Craig Silverstein
917f4e7bf3 Some reorganization that results from a new method I'm moving to to
maintaining this opensource tree.  Some of this reorganization is
entirely a result of reorganization: blank lines in a few different
places, etc.  Here are the others:

1) I've added a new file, util.h, with lots of new, helpful routines,
most notably StringPrintf (printf returning a string).  I've also
moved some routines from the .cc and unittest.cc file here, such as
the CHECK macros, testing framework, and #ifdefs for 16-bit ints.
Quite a bit of code was rewritten to use these new routines.

2) I noticed that the special-case setenv() code was only needed for
windows systems, so I moved it to port.h/cc.

3) I also had to add a new vsnprintf wrapper in port.h/cc, to support
StringPrintf.

4) A few places I used an old name, commandlineflags, instead of
gflags.  Most or all of these should be fixed now.

5) Some of my copyright dates weren't quite right.  Fixed them up.

6) In some .cc files, I added using directives to not have to use
std:: so much.

7) I've added a minor new test, adding 10000 or so flags to see how
the system scales.

8) Some compile-warning fixes, such as int -> size_t when appropriate,
and better protected #defines in mutex.h

9) The .h files gained some logic defining GFLAGS_DLL_DECL.  This is
true even for .h files outside the windows directory, which will never
have these dll issues.  But one big advantage of my new organization
is auto-generating the windows versions of these files from the unix
versions, so there's some unnecessary (but harmless) duplication as a
result.

10) Fixed a bug in rpm.sh which would cause an unnecessary crash when
dpkg was missing.


git-svn-id: https://gflags.googlecode.com/svn/trunk@52 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-07-29 04:26:49 +00:00
Craig Silverstein
b7ea065962 Update to automake 1.10.1 (from 1.9), and downdate to autoconf 2.62
(from 2.65).  I'm moving to a new system for maintaining the
opensource version, which involves using a 'hermetic' version of
autotools, and those are the versions installed in the hermetic
system.  There shouldn't be a user-noticeable change here.


git-svn-id: https://gflags.googlecode.com/svn/trunk@51 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-07-29 03:48:59 +00:00
Craig Silverstein
69ecf71511 * Minor correction for doc of shorthelp (soerenme, mecarson)
* Fix a bug where we were leaving out a required $(top_srcdir)


git-svn-id: https://gflags.googlecode.com/svn/trunk@50 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-07-28 06:19:07 +00:00
Craig Silverstein
eacb7924c8 Update the windows version of the .h's to match the unix version.
git-svn-id: https://gflags.googlecode.com/svn/trunk@49 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-05-19 21:32:31 +00:00
Craig Silverstein
ac2abfc8c8 * Split up flag declares into its own file (jyrki)
* Add --version support (csilvers)
	* Fix doc typo (sudit)
	* Update the README instructions for gflags with static libs (csilvers)


git-svn-id: https://gflags.googlecode.com/svn/trunk@48 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-04-21 19:22:43 +00:00
Craig Silverstein
b4bf72b051 Add support for specifying a version number (SetVersionString()),
which is then displayed in --version.


git-svn-id: https://gflags.googlecode.com/svn/trunk@47 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-03-03 22:26:24 +00:00
Craig Silverstein
71e1be97d8 * Update acx_pthread.m4 for nostdlib (liujisi)
* Typo fix in docs (bogdand)
        * Change ReparseCommandLineFlags to return void (csilvers)


git-svn-id: https://gflags.googlecode.com/svn/trunk@46 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-03-02 08:05:17 +00:00
Craig Silverstein
24b4c59e69 Mon Jan 24 16:11:35 2011 Google Inc. <opensource@google.com>
* google-gflags: version 1.5
	* Better reporting of current vs default value (handler)
	* Add API for cleaning up of memory at program-exit (jmarantz)
	* Fix macros to work inside namespaces (csilvers)
	* Use our own string typedef in case string is redefined (csilvers)
	* Updated to autoconf 2.65


git-svn-id: https://gflags.googlecode.com/svn/trunk@44 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-01-25 00:36:41 +00:00
Craig Silverstein
0baf4ab4f6 * Remove reference to InitGoogle (csilvers)
* Remove superfluous friend declaration (mec)
	* Better reporting of current vs default value (handler)
	* Allow cleaning up of memory at program-exit (jmarantz)
	* Put CompileAssert in correct namespace (csilvers)


git-svn-id: https://gflags.googlecode.com/svn/trunk@43 6586e3c6-dcc4-952a-343f-ff74eb82781d
2011-01-14 21:58:28 +00:00
Craig Silverstein
84b18ac090 * Use our own string typedef so macro is never confused (csilvers)
* Set up configure.ac to give proper library version numbers (csilvers)
	* Update from autoconf 2.64 to 2.65.  Also hermeticize libtool a bit


git-svn-id: https://gflags.googlecode.com/svn/trunk@42 6586e3c6-dcc4-952a-343f-ff74eb82781d
2010-11-16 23:21:00 +00:00
Craig Silverstein
3c624b701e Wed Oct 13 17:40:12 2010 Google Inc. <opensource@google.com>
* google-gflags: version 1.4
	* Add a check to prevent passing 0 to DEFINE_string (jorg)
	* Reduce compile (.o) size (jyrki)
	* Some small changes to quiet debug compiles (alexk)
	* PORTING: better support static linking on windows (csilvers)
	* DOCUMENTATION: change default values, use validators, etc.
	* Update the NEWS file to be non-empty
	* Add pkg-config (.pc) files for libgflags and libgflags_nothreads


git-svn-id: https://gflags.googlecode.com/svn/trunk@40 6586e3c6-dcc4-952a-343f-ff74eb82781d
2010-10-14 01:17:43 +00:00
Craig Silverstein
c44e0559cf * Reduce .o size by decomposing switches (jyrki)
* Document how to change the default flag value (csilvers)
	* Add a windows-specific README (csilvers)
	* A few comment updates (wojtekm)


git-svn-id: https://gflags.googlecode.com/svn/trunk@39 6586e3c6-dcc4-952a-343f-ff74eb82781d
2010-09-16 18:53:42 +00:00
Craig Silverstein
20500a9e59 * Added a contentful NEWS file (csilvers)
* Fixed email address in maintainers to actually work (csilvers)
	* Update docs with info on validators (wojtekm)


git-svn-id: https://gflags.googlecode.com/svn/trunk@38 6586e3c6-dcc4-952a-343f-ff74eb82781d
2010-05-07 21:33:49 +00:00
Craig Silverstein
31226b61f2 * Get rid of unnecessary c++ aliasing violation (csilvers)
* Better error message on parse failure (tstromberg)


git-svn-id: https://gflags.googlecode.com/svn/trunk@37 6586e3c6-dcc4-952a-343f-ff74eb82781d
2010-03-10 00:37:33 +00:00
Craig Silverstein
31c8edc53e Mon Jan 4 18:09:30 2010 Google Inc. <opensource@google.com>
* google-gflags: version 1.3
	* PORTABILITY: can now build and run tests under MSVC (csilvers)
	* Remove the python gflags code, which is now its own package (tansell)
	* Clarify that "last flag wins" in the docs (csilvers)
	* Comment danger of using GetAllFlags in validators (wojtekm)
	* PORTABILITY: Some fixes necessary for c++0x (mboerger)
	* Makefile fix: $(srcdir) -> $(top_srcdir) in one place (csilvres)
	* INSTALL: autotools to autoconf v2.64 + automake v1.11 (csilvers)


git-svn-id: https://gflags.googlecode.com/svn/trunk@35 6586e3c6-dcc4-952a-343f-ff74eb82781d
2010-01-05 02:25:45 +00:00
Craig Silverstein
ab3d7650dc * PORTING: Add windows (MSVC) support (csilvers)
* Comment danger of using GetAllFlags in validators (wojtekm)
	* Add python support for gnu_getopt (hobe)
	* DEFINE_list now accepts a list as a default (dsturtevant)
	* TMPDIR -> TEST_TMPDIR in Makefile, fixing objcopy behavior (csilvers)
	* Fix the 'cp' command to use $(top_srcdir) in the Makefile (csilvers)



git-svn-id: https://gflags.googlecode.com/svn/trunk@34 6586e3c6-dcc4-952a-343f-ff74eb82781d
2009-11-10 16:33:51 +00:00
Craig Silverstein
688ea02a69 Thu Sep 10 12:53:04 2009 Google Inc. <opensource@google.com>
* google-gflags: version 1.2
	* PORTABILITY: can now build and run tests under mingw (csilvers)
	* Using a string arg for a bool flag is a compile-time error (rbayardo)
	* Add --helpxml to gflags.py (salcianu)
	* Protect against a hypothetical global d'tor mutex problem (csilvers)
	* BUGFIX: can now define a flag after 'using namespace google' (hamaji)


git-svn-id: https://gflags.googlecode.com/svn/trunk@32 6586e3c6-dcc4-952a-343f-ff74eb82781d
2009-09-11 00:15:50 +00:00
Craig Silverstein
de718176a2 Oops, I accidentally left this out of SVN! See
http://code.google.com/p/google-gflags/issues/detail?id=24


git-svn-id: https://gflags.googlecode.com/svn/trunk@31 6586e3c6-dcc4-952a-343f-ff74eb82781d
2009-07-17 21:43:52 +00:00
Craig Silverstein
5a3c7f8598 Tue Apr 14 12:35:25 2009 Google Inc. <opensource@google.com>
* google-gflags: version 1.1
	* Add both foo and nofoo for boolean flags, with --undefok (andychu)
	* Better document how validators work (wojtekm)
	* Improve binary-detection for bash-completion (mtamsky)
	* Python: Add a concept of "key flags", used with --help (salcianu)
	* Python: Robustify flag_values (salcianu)
	* Python: Add a new DEFINE_bool alias (keir, andrewliu)
	* Python: Do module introspection based on module name (dsturtevant)
	* Fix autoconf a bit better, especially on windows and solaris (ajenjo)
	* BUG FIX: gflags_nothreads was linking against the wrong lib (ajenjo)
	* BUG FIX: threads-detection failed on FreeBSD; replace it (ajenjo)
	* PORTABILITY: Quiet an internal compiler error with SUSE 10 (csilvers)
	* PORTABILITY: Update deb.sh for more recenty debuilds (csilvers)
	* PORTABILITY: #include more headers to satify new gcc's (csilvers)
	* INSTALL: Updated to autoconf 2.61 and libtool 1.5.26 (csilvers)


git-svn-id: https://gflags.googlecode.com/svn/trunk@29 6586e3c6-dcc4-952a-343f-ff74eb82781d
2009-04-15 21:57:04 +00:00
Craig Silverstein
e0b71e5758 Thu Sep 18 12:58:05 2008 Google Inc. <opensource@google.com>
* google-gflags: version 1.0rc2
	* Report current flag values in --helpxml (hdn)
	* Fix compilation troubles with gcc 4.3.3 (simonb)
	* BUG FIX: I was missing a std:: in DECLARE_string (csilvers)
	* BUG FIX: Clarify in docs how to specify --bool flags (csilvers)
	* BUG FIX: Fix --helpshort for source files not in a subdir (csilvers)
	* BUG FIX: Fix python unittest for 64-bit builds (bcmills)


git-svn-id: https://gflags.googlecode.com/svn/trunk@27 6586e3c6-dcc4-952a-343f-ff74eb82781d
2008-09-19 19:32:05 +00:00
Craig Silverstein
67914687b8 Tue Aug 19 16:15:48 2008 Google Inc. <opensource@google.com>
* google-gflags: version 1.0rc1
	* Move #include files from google/ to gflags/ (csilvers)
	* Small optimizations to reduce binary (library) size (jyrki)
	* BUGFIX: forgot a std:: in one of the .h files (csilvers)
	* Speed up locking by making sure calls are inlined (ajenjo)
	* 64-BIT COMPATIBILITY: Use %PRId64 instead of %lld (csilvers)
	* PORTABILITY: fix Makefile to work with Cygwin (ajenjo)
	* PORTABILITY: fix code to compile under Visual Studio (ajenjo)
	* PORTABILITY: fix code to compile under Solaris 10 with CC (csilvers)


git-svn-id: https://gflags.googlecode.com/svn/trunk@25 6586e3c6-dcc4-952a-343f-ff74eb82781d
2008-08-21 00:50:59 +00:00
Craig Silverstein
c79c32d98c Mon Jul 21 23:01:38 2008 Google Inc. <opensource@google.com>
* google-gflags: version 0.9
	* Add the ability to validate a command-line flag (csilvers)
	* Add completion support for commandline flags in bash (daven)
	* Add -W compile flags to Makefile, when using gcc (csilvers)
	* Allow helpstring to be NULL (cristianoc)
	* Improved documentation of classes in the .cc file (csilvers)
	* Fix python bug with AppendFlagValues + shortnames (jjtswan)
	* Use bool instead of int for boolean flags in gflags.py (bcmills)
	* Simplify the way we declare flags, now more foolproof (csilvers)
	* Better error messages when bool flags collide (colohan)
	* Only evaluate DEFINE_foo macro args once (csilvers)


git-svn-id: https://gflags.googlecode.com/svn/trunk@23 6586e3c6-dcc4-952a-343f-ff74eb82781d
2008-07-22 23:29:39 +00:00
Craig Silverstein
83911c12f3 Wed Mar 26 15:20:18 2008 Google Inc. <opensource@google.com>
* google-gflags: version 0.8
	* Export DescribeOneFlag() in the API
	* Add support for automatic line wrapping at 80 cols for gflags.py
	* Bugfix: do not treat an isolated "-" the same as an isolated "--"
	* Update rpm spec to point to Google Code rather than sourceforge (!)
	* Improve documentation (including documenting thread-safety)
	* Improve #include hygiene
	* Improve testing


git-svn-id: https://gflags.googlecode.com/svn/trunk@21 6586e3c6-dcc4-952a-343f-ff74eb82781d
2008-03-27 20:11:07 +00:00
Craig Silverstein
585a44a0c0 Thu Oct 18 11:33:20 2007 Google Inc. <opensource@google.com>
* google-gflags: version 0.7
	* Deal even more correctly with libpthread not linked in (csilvers)
	* Add STRIP_LOG, an improved DO_NOT_SHOW_COMMANDLINE_HELP (sioffe)
	* Be more accurate printing default flag values in --help (dsturtevant)
	* Reduce .o file size a bit by using shorter namespace names (jeff)
	* Use relative install path, so 'setup.py --home' works (csilvers)
	* Notice when a boolean flag has a non-boolean default (bnmouli)
	* Broaden --helpshort to match foo-main.cc and foo_main.cc (hendrie)
	* Fix "no modules match" message for --helpshort, etc (hendrie)


git-svn-id: https://gflags.googlecode.com/svn/trunk@19 6586e3c6-dcc4-952a-343f-ff74eb82781d
2007-10-18 20:08:26 +00:00
Craig Silverstein
eb2083998d Wed Aug 15 07:35:51 2007 Google Inc. <opensource@google.com>
* google-gflags: version 0.6
	* Deal correctly with case that libpthread is not linked in (csilvers)
	* Update Makefile/tests so we pass "make distcheck" (csilvers)
	* Document and test that last assignment to a flag wins (wan)


git-svn-id: https://gflags.googlecode.com/svn/trunk@17 6586e3c6-dcc4-952a-343f-ff74eb82781d
2007-08-15 19:44:54 +00:00
Craig Silverstein
2b66a84406 Tue Jun 12 15:23:42 2007 Google Inc. <opensource@google.com>
* google-gflags: version 0.5
	* Include all m4 macros in the distribution (csilvers)
	* Python: Fix broken data_files field in setup.py (sidlon)
	* Python: better string serliaizing and unparsing (abo, csimmons)
	* Fix checks for NaN and inf to work with Mac OS X (csilvers)


git-svn-id: https://gflags.googlecode.com/svn/trunk@15 6586e3c6-dcc4-952a-343f-ff74eb82781d
2007-06-12 23:59:42 +00:00
Craig Silverstein
690172b4d8 Thu Apr 19 15:15:07 2007 Google Inc. <opensource@google.com>
* google-gflags: version 0.4
	* Remove is_default from GetCommandLineFlagInfo (csilvers)
	* Portability fixes: includes, strtoll, gcc4.3 errors (csilvers)
	* A few doc typo cleanups (csilvers)


git-svn-id: https://gflags.googlecode.com/svn/trunk@13 6586e3c6-dcc4-952a-343f-ff74eb82781d
2007-04-20 21:16:33 +00:00
Craig Silverstein
290da389e5 Wed Mar 28 12:15:56 2007 Google Inc. <opensource@google.com>
* google-gflags: version 0.3
	* python portability fix: use popen instead of subprocess (csilvers)
	* Add is_default to CommandLineFlagInfo (pchien)
	* Make docs a bit prettier (csilvers)
	* Actually include the python files in the distribution! :-/ (csilvers)


git-svn-id: https://gflags.googlecode.com/svn/trunk@11 6586e3c6-dcc4-952a-343f-ff74eb82781d
2007-03-28 21:54:07 +00:00
91 changed files with 8973 additions and 46739 deletions

3
.gitattributes vendored Normal file
View file

@ -0,0 +1,3 @@
# treat all files in this repository as text files
# and normalize them to LF line endings when committed
* text

51
.github/workflows/test.yml vendored Normal file
View file

@ -0,0 +1,51 @@
name: Build and Run Tests
on:
push:
branches:
- master
pull_request:
branches:
- master
concurrency:
group: test-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
# - macos-latest
# - windows-latest
cmake:
- '4.0'
- '3.31'
fail-fast: false
permissions:
contents: write
steps:
- name: Checkout Project
uses: actions/checkout@v4
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@802fa1a2c4e212495c05bf94dba2704a92a472be # v2.0.2
with:
cmake-version: ${{ matrix.cmake }}
- name: Setup Ninja
uses: seanmiddleditch/gha-setup-ninja@3b1f8f94a2f8254bd26914c4ab9474d4f0015f67 # v6
- name: Configure CMake
run: |
cmake -B build -G Ninja \
-D CMAKE_CXX_COMPILER=clang++ \
-D CMAKE_BUILD_TYPE=Release \
-D GFLAGS_BUILD_SHARED_LIBS=ON \
-D GFLAGS_BUILD_STATIC_LIBS=ON \
-D GFLAGS_BUILD_TESTING=ON
- name: Build Tests
run: cmake --build build --config Release
- name: Run Tests
run: cd build && ctest

25
.gitignore vendored Normal file
View file

@ -0,0 +1,25 @@
/xcode/
/build/
/builds/
/build-*/
/_build/
.DS_Store
CMakeCache.txt
DartConfiguration.tcl
Makefile
CMakeFiles/
/Testing/
/include/gflags/config.h
/include/gflags/gflags_completions.h
/include/gflags/gflags_declare.h
/include/gflags/gflags.h
/lib/
/test/gflags_unittest_main.cc
/test/gflags_unittest-main.cc
/packages/
CMakeLists.txt.user
/bazel-bin
/bazel-genfiles
/bazel-gflags
/bazel-out
/bazel-testlogs

View file

@ -1,2 +0,0 @@
opensource@google.com

2
AUTHORS.txt Normal file
View file

@ -0,0 +1,2 @@
google-gflags@googlegroups.com

26
BUILD Normal file
View file

@ -0,0 +1,26 @@
# Bazel (http://bazel.io/) BUILD file for gflags.
#
# See INSTALL.md for instructions for adding gflags to a Bazel workspace.
licenses(["notice"])
exports_files([
"src/gflags_completions.sh",
"COPYING.txt",
])
config_setting(
name = "x64_windows",
values = {"cpu": "x64_windows"},
)
config_setting(
name = "android",
values = {"crosstool_top": "//external:android/crosstool"},
)
load(":bazel/gflags.bzl", "gflags_library", "gflags_sources")
(hdrs, srcs) = gflags_sources(namespace=["google", "gflags"])
gflags_library(hdrs=hdrs, srcs=srcs, threads=0)
gflags_library(hdrs=hdrs, srcs=srcs, threads=1)

754
CMakeLists.txt Normal file
View file

@ -0,0 +1,754 @@
## CMake configuration file of gflags project
##
## This CMakeLists.txt defines some gflags specific configuration variables
## using the "gflags_define" utility macro. The default values of these variables
## can be overridden either on the CMake command-line using the -D option of
## the cmake command or in a super-project which includes the gflags source
## tree by setting the GFLAGS_<varname> CMake variables before adding the
## gflags source directory via CMake's "add_subdirectory" command. Only when
## the non-cached variable GFLAGS_IS_SUBPROJECT has a value equivalent to FALSE,
## these configuration variables are added to the CMake cache so they can be
## edited in the CMake GUI. By default, GFLAGS_IS_SUBPROJECT is set to TRUE when
## the CMAKE_SOURCE_DIR is not identical to the directory of this CMakeLists.txt
## file, i.e., the top-level directory of the gflags project source tree.
##
## When this project is a subproject (GFLAGS_IS_SUBPROJECT is TRUE), the default
## settings are such that only the static single-threaded library is built without
## installation of the gflags files. The "gflags::gflags" target is in this case an ALIAS
## library target for the "gflags_nothreads_static" library target. Targets which
## depend on the gflags library should link to the "gflags::gflags" library target.
##
## Example CMakeLists.txt of user project which requires separate gflags installation:
## cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
##
## project(Foo)
##
## find_package(gflags REQUIRED)
##
## add_executable(foo src/foo.cc)
## target_link_libraries(foo gflags::gflags)
##
## Example CMakeLists.txt of user project which requires separate single-threaded static gflags installation:
## cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
##
## project(Foo)
##
## find_package(gflags COMPONENTS nothreads_static)
##
## add_executable(foo src/foo.cc)
## target_link_libraries(foo gflags::gflags)
##
## Example CMakeLists.txt of super-project which contains gflags source tree:
## cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
##
## project(Foo)
##
## add_subdirectory(gflags)
##
## add_executable(foo src/foo.cc)
## target_link_libraries(foo gflags::gflags)
##
## Variables to configure the source files:
## - GFLAGS_IS_A_DLL
## - GFLAGS_NAMESPACE
## - GFLAGS_ATTRIBUTE_UNUSED
## - GFLAGS_INTTYPES_FORMAT
##
## Variables to configure the build:
## - GFLAGS_SOVERSION
## - GFLAGS_BUILD_SHARED_LIBS
## - GFLAGS_BUILD_STATIC_LIBS
## - GFLAGS_BUILD_gflags_LIB
## - GFLAGS_BUILD_gflags_nothreads_LIB
## - GFLAGS_BUILD_TESTING
## - GFLAGS_BUILD_PACKAGING
##
## Variables to configure the installation:
## - GFLAGS_INCLUDE_DIR
## - GFLAGS_LIBRARY_INSTALL_DIR or LIB_INSTALL_DIR or LIB_SUFFIX
## - GFLAGS_INSTALL_HEADERS
## - GFLAGS_INSTALL_SHARED_LIBS
## - GFLAGS_INSTALL_STATIC_LIBS
cmake_minimum_required (VERSION 3.5 FATAL_ERROR)
if (POLICY CMP0042)
cmake_policy (SET CMP0042 NEW)
endif ()
if (POLICY CMP0048)
cmake_policy (SET CMP0048 NEW)
endif ()
if (POLICY CMP0063)
cmake_policy (SET CMP0063 NEW)
endif ()
# ----------------------------------------------------------------------------
# includes
include ("${CMAKE_CURRENT_SOURCE_DIR}/cmake/utils.cmake")
# ----------------------------------------------------------------------------
# package information
set (PACKAGE_NAME "gflags")
set (PACKAGE_VERSION "2.2.2")
set (PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
set (PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}")
set (PACKAGE_BUGREPORT "https://github.com/gflags/gflags/issues")
set (PACKAGE_DESCRIPTION "A commandline flags library that allows for distributed flags.")
set (PACKAGE_URL "http://gflags.github.io/gflags")
project (${PACKAGE_NAME} VERSION ${PACKAGE_VERSION} LANGUAGES CXX)
if (CMAKE_VERSION VERSION_LESS 3.4)
# C language still needed because the following required CMake modules
# (or their dependencies, respectively) are not correctly handling
# the case where only CXX is enabled
# - CheckTypeSize.cmake (fixed in CMake 3.1, cf. https://cmake.org/Bug/view.php?id=14056)
# - FindThreads.cmake (fixed in CMake 3.4, cf. https://cmake.org/Bug/view.php?id=14905)
enable_language (C)
endif ()
version_numbers (
${PACKAGE_VERSION}
PACKAGE_VERSION_MAJOR
PACKAGE_VERSION_MINOR
PACKAGE_VERSION_PATCH
)
# shared library ABI version number, can be overridden by package maintainers
# using -DGFLAGS_SOVERSION=XXX on the command-line
if (GFLAGS_SOVERSION)
set (PACKAGE_SOVERSION "${GFLAGS_SOVERSION}")
else ()
# TODO: Change default SOVERSION back to PACKAGE_VERSION_MAJOR with the
# next increase of major version number (i.e., 3.0.0 -> SOVERSION 3)
# The <major>.<minor> SOVERSION should be used for the 2.x releases
# versions only which temporarily broke the API by changing the default
# namespace from "google" to "gflags".
set (PACKAGE_SOVERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}")
endif ()
# when gflags is included as subproject (e.g., as Git submodule/subtree) in the source
# tree of a project that uses it, no variables should be added to the CMake cache;
# users may set the non-cached variable GFLAGS_IS_SUBPROJECT before add_subdirectory(gflags)
if (NOT DEFINED GFLAGS_IS_SUBPROJECT)
if ("^${CMAKE_SOURCE_DIR}$" STREQUAL "^${PROJECT_SOURCE_DIR}$")
set (GFLAGS_IS_SUBPROJECT FALSE)
else ()
set (GFLAGS_IS_SUBPROJECT TRUE)
endif ()
endif ()
# prefix for package variables in CMake configuration file
string (TOUPPER "${PACKAGE_NAME}" PACKAGE_PREFIX)
# convert file path on Windows with back slashes to path with forward slashes
# otherwise this causes an issue with the cmake_install.cmake script
file (TO_CMAKE_PATH "${CMAKE_INSTALL_PREFIX}" CMAKE_INSTALL_PREFIX)
# ----------------------------------------------------------------------------
# options
# maintain binary backwards compatibility with gflags library version <= 2.0,
# but at the same time enable the use of the preferred new "gflags" namespace
gflags_define (STRING NAMESPACE "Name(s) of library namespace (separate multiple options by semicolon)" "google;${PACKAGE_NAME}" "${PACKAGE_NAME}")
gflags_property (NAMESPACE ADVANCED TRUE)
set (GFLAGS_NAMESPACE_SECONDARY "${NAMESPACE}")
list (REMOVE_DUPLICATES GFLAGS_NAMESPACE_SECONDARY)
if (NOT GFLAGS_NAMESPACE_SECONDARY)
message (FATAL_ERROR "GFLAGS_NAMESPACE must be set to one (or more) valid C++ namespace identifier(s separated by semicolon \";\").")
endif ()
foreach (ns IN LISTS GFLAGS_NAMESPACE_SECONDARY)
if (NOT ns MATCHES "^[a-zA-Z][a-zA-Z0-9_]*$")
message (FATAL_ERROR "GFLAGS_NAMESPACE contains invalid namespace identifier: ${ns}")
endif ()
endforeach ()
list (GET GFLAGS_NAMESPACE_SECONDARY 0 GFLAGS_NAMESPACE)
list (REMOVE_AT GFLAGS_NAMESPACE_SECONDARY 0)
# cached build options when gflags is not a subproject, otherwise non-cached CMake variables
# usage: gflags_define(BOOL <name> <doc> <default> [<subproject default>])
gflags_define (BOOL BUILD_SHARED_LIBS "Request build of shared libraries." OFF OFF)
gflags_define (BOOL BUILD_STATIC_LIBS "Request build of static libraries (default if BUILD_SHARED_LIBS is OFF)." OFF ON)
gflags_define (BOOL BUILD_gflags_LIB "Request build of the multi-threaded gflags library." ON OFF)
gflags_define (BOOL BUILD_gflags_nothreads_LIB "Request build of the single-threaded gflags library." ON ON)
gflags_define (BOOL BUILD_PACKAGING "Enable build of distribution packages using CPack." OFF OFF)
gflags_define (BOOL BUILD_TESTING "Enable build of the unit tests and their execution using CTest." OFF OFF)
gflags_define (BOOL INSTALL_HEADERS "Request installation of headers and other development files." ON OFF)
gflags_define (BOOL INSTALL_SHARED_LIBS "Request installation of shared libraries." ON ON)
gflags_define (BOOL INSTALL_STATIC_LIBS "Request installation of static libraries." ON OFF)
gflags_define (BOOL REGISTER_BUILD_DIR "Request entry of build directory in CMake's package registry." OFF OFF)
gflags_define (BOOL REGISTER_INSTALL_PREFIX "Request entry of installed package in CMake's package registry." ON OFF)
gflags_define (BOOL EXPORT_NAMESPACE_SET "Request export namespace targets set." ON ON)
gflags_define (BOOL EXPORT_NONAMESPACE_SET "Request export nonamespace targets set." ON OFF)
gflags_property (BUILD_STATIC_LIBS ADVANCED TRUE)
gflags_property (INSTALL_HEADERS ADVANCED TRUE)
gflags_property (INSTALL_SHARED_LIBS ADVANCED TRUE)
gflags_property (INSTALL_STATIC_LIBS ADVANCED TRUE)
if (NOT GFLAGS_IS_SUBPROJECT)
foreach (varname IN ITEMS CMAKE_INSTALL_PREFIX)
gflags_property (${varname} ADVANCED FALSE)
endforeach ()
foreach (varname IN ITEMS CMAKE_CONFIGURATION_TYPES CMAKE_OSX_ARCHITECTURES CMAKE_OSX_DEPLOYMENT_TARGET CMAKE_OSX_SYSROOT)
gflags_property (${varname} ADVANCED TRUE)
endforeach ()
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CXX_FLAGS)
gflags_set (CMAKE_BUILD_TYPE Release)
endif ()
if (CMAKE_CONFIGURATION_TYPES)
gflags_property (CMAKE_BUILD_TYPE STRINGS "${CMAKE_CONFIGURATION_TYPES}")
endif ()
endif () # NOT GFLAGS_IS_SUBPROJECT
if (NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS)
set (BUILD_STATIC_LIBS ON)
endif ()
if (NOT BUILD_gflags_LIB AND NOT BUILD_gflags_nothreads_LIB)
message (FATAL_ERROR "At least one of [GFLAGS_]BUILD_gflags_LIB and [GFLAGS_]BUILD_gflags_nothreads_LIB must be ON.")
endif ()
gflags_define (STRING INCLUDE_DIR "Name of include directory of installed header files relative to CMAKE_INSTALL_PREFIX/include/" "${PACKAGE_NAME}")
gflags_property (INCLUDE_DIR ADVANCED TRUE)
file (TO_CMAKE_PATH "${INCLUDE_DIR}" INCLUDE_DIR)
if (IS_ABSOLUTE INCLUDE_DIR)
message (FATAL_ERROR "[GFLAGS_]INCLUDE_DIR must be a path relative to CMAKE_INSTALL_PREFIX/include/")
endif ()
if (INCLUDE_DIR MATCHES "^\\.\\.[/\\]")
message (FATAL_ERROR "[GFLAGS_]INCLUDE_DIR must not start with parent directory reference (../)")
endif ()
set (GFLAGS_INCLUDE_DIR "${INCLUDE_DIR}")
# ----------------------------------------------------------------------------
# system checks
include (CheckTypeSize)
include (CheckIncludeFileCXX)
include (CheckCXXSymbolExists)
if (WIN32 AND NOT CYGWIN)
set (OS_WINDOWS 1)
else ()
set (OS_WINDOWS 0)
endif ()
if (MSVC)
set (HAVE_SYS_TYPES_H 1)
set (HAVE_STDDEF_H 1) # used by CheckTypeSize module
set (HAVE_UNISTD_H 0)
set (HAVE_SYS_STAT_H 1)
set (HAVE_SHLWAPI_H 1)
if (MSVC_VERSION VERSION_LESS 1600)
check_include_file_cxx ("stdint.h" HAVE_STDINT_H)
bool_to_int (HAVE_STDINT_H) # used in #if directive
else ()
set (HAVE_STDINT_H 1)
endif ()
if (MSVC_VERSION VERSION_LESS 1800)
check_include_file_cxx ("inttypes.h" HAVE_INTTYPES_H)
bool_to_int (HAVE_INTTYPES_H) # used in #if directive
else ()
set (HAVE_INTTYPES_H 1)
endif ()
else ()
foreach (fname IN ITEMS unistd stdint inttypes sys/types sys/stat fnmatch)
string (TOUPPER "${fname}" FNAME)
string (REPLACE "/" "_" FNAME "${FNAME}")
if (NOT HAVE_${FNAME}_H)
check_include_file_cxx ("${fname}.h" HAVE_${FNAME}_H)
endif ()
endforeach ()
if (NOT HAVE_FNMATCH_H AND OS_WINDOWS)
check_include_file_cxx ("shlwapi.h" HAVE_SHLWAPI_H)
endif ()
# the following are used in #if directives not #ifdef
bool_to_int (HAVE_STDINT_H)
bool_to_int (HAVE_SYS_TYPES_H)
bool_to_int (HAVE_INTTYPES_H)
endif ()
gflags_define (STRING INTTYPES_FORMAT "Format of integer types: \"C99\" (uint32_t), \"BSD\" (u_int32_t), \"VC7\" (__int32)" "")
gflags_property (INTTYPES_FORMAT STRINGS "C99;BSD;VC7")
gflags_property (INTTYPES_FORMAT ADVANCED TRUE)
if (NOT INTTYPES_FORMAT)
set (TYPES uint32_t u_int32_t)
if (MSVC)
list (INSERT TYPES 0 __int32)
endif ()
foreach (type IN LISTS TYPES)
check_type_size (${type} ${type} LANGUAGE CXX)
if (HAVE_${type})
break ()
endif ()
endforeach ()
if (HAVE_uint32_t)
gflags_set (INTTYPES_FORMAT C99)
elseif (HAVE_u_int32_t)
gflags_set (INTTYPES_FORMAT BSD)
elseif (HAVE___int32)
gflags_set (INTTYPES_FORMAT VC7)
else ()
gflags_property (INTTYPES_FORMAT ADVANCED FALSE)
message (FATAL_ERROR "Do not know how to define a 32-bit integer quantity on your system!"
" Neither uint32_t, u_int32_t, nor __int32 seem to be available."
" Set [GFLAGS_]INTTYPES_FORMAT to either C99, BSD, or VC7 and try again.")
endif ()
endif ()
# use of special characters in strings to circumvent bug #0008226
if ("^${INTTYPES_FORMAT}$" STREQUAL "^WIN$")
gflags_set (INTTYPES_FORMAT VC7)
endif ()
if (NOT INTTYPES_FORMAT MATCHES "^(C99|BSD|VC7)$")
message (FATAL_ERROR "Invalid value for [GFLAGS_]INTTYPES_FORMAT! Choose one of \"C99\", \"BSD\", or \"VC7\"")
endif ()
set (GFLAGS_INTTYPES_FORMAT "${INTTYPES_FORMAT}")
set (GFLAGS_INTTYPES_FORMAT_C99 0)
set (GFLAGS_INTTYPES_FORMAT_BSD 0)
set (GFLAGS_INTTYPES_FORMAT_VC7 0)
set ("GFLAGS_INTTYPES_FORMAT_${INTTYPES_FORMAT}" 1)
if (MSVC)
set (HAVE_strtoll 0)
set (HAVE_strtoq 0)
else ()
check_cxx_symbol_exists (strtoll stdlib.h HAVE_STRTOLL)
if (NOT HAVE_STRTOLL)
check_cxx_symbol_exists (strtoq stdlib.h HAVE_STRTOQ)
endif ()
endif ()
if (BUILD_gflags_LIB)
set (CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package (Threads)
if (Threads_FOUND AND CMAKE_USE_PTHREADS_INIT)
set (HAVE_PTHREAD 1)
check_type_size (pthread_rwlock_t RWLOCK LANGUAGE CXX)
else ()
set (HAVE_PTHREAD 0)
endif ()
if (UNIX AND NOT HAVE_PTHREAD)
if (CMAKE_HAVE_PTHREAD_H)
set (what "library")
else ()
set (what ".h file")
endif ()
message (FATAL_ERROR "Could not find pthread${what}. Check the log file"
"\n\t${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
"\nor disable the build of the multi-threaded gflags library (BUILD_gflags_LIB=OFF).")
endif ()
else ()
set (HAVE_PTHREAD 0)
endif ()
# ----------------------------------------------------------------------------
# source files - excluding root subdirectory and/or .in suffix
set (PUBLIC_HDRS
"gflags.h"
"gflags_declare.h"
"gflags_completions.h"
)
if (GFLAGS_NAMESPACE_SECONDARY)
set (INCLUDE_GFLAGS_NS_H "// Import gflags library symbols into alternative/deprecated namespace(s)")
foreach (ns IN LISTS GFLAGS_NAMESPACE_SECONDARY)
string (TOUPPER "${ns}" NS)
set (gflags_ns_h "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/gflags_${ns}.h")
configure_file ("${PROJECT_SOURCE_DIR}/src/gflags_ns.h.in" "${gflags_ns_h}" @ONLY)
list (APPEND PUBLIC_HDRS "${gflags_ns_h}")
set (INCLUDE_GFLAGS_NS_H "${INCLUDE_GFLAGS_NS_H}\n#include \"gflags_${ns}.h\"")
endforeach ()
else ()
set (INCLUDE_GFLAGS_NS_H)
endif ()
set (PRIVATE_HDRS
"defines.h"
"config.h"
"util.h"
"mutex.h"
)
set (GFLAGS_SRCS
"gflags.cc"
"gflags_reporting.cc"
"gflags_completions.cc"
)
if (OS_WINDOWS)
list (APPEND PRIVATE_HDRS "windows_port.h")
list (APPEND GFLAGS_SRCS "windows_port.cc")
endif ()
# ----------------------------------------------------------------------------
# configure source files
if (NOT DEFINED GFLAGS_ATTRIBUTE_UNUSED)
if (CMAKE_COMPILER_IS_GNUCXX)
set (GFLAGS_ATTRIBUTE_UNUSED "__attribute((unused))")
else ()
set (GFLAGS_ATTRIBUTE_UNUSED)
endif ()
endif ()
# whenever we build a shared library (DLL on Windows), configure the public
# headers of the API for use of this shared library rather than the optionally
# also build statically linked library; users can override GFLAGS_DLL_DECL
# in particular, this done by setting the INTERFACE_COMPILE_DEFINITIONS of
# static libraries to include an empty definition for GFLAGS_DLL_DECL
if (NOT DEFINED GFLAGS_IS_A_DLL)
if (BUILD_SHARED_LIBS)
set (GFLAGS_IS_A_DLL 1)
else ()
set (GFLAGS_IS_A_DLL 0)
endif ()
endif ()
configure_headers (PUBLIC_HDRS ${PUBLIC_HDRS})
configure_sources (PRIVATE_HDRS ${PRIVATE_HDRS})
configure_sources (GFLAGS_SRCS ${GFLAGS_SRCS})
# ----------------------------------------------------------------------------
# output directories
if (NOT GFLAGS_IS_SUBPROJECT)
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin")
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "lib")
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "lib")
endif ()
# Set postfixes for generated libraries based on buildtype.
set(CMAKE_RELEASE_POSTFIX "")
set(CMAKE_DEBUG_POSTFIX "_debug")
# ----------------------------------------------------------------------------
# installation directories
if (OS_WINDOWS AND NOT MINGW)
set (RUNTIME_INSTALL_DIR "bin")
set (LIBRARY_INSTALL_DIR "lib")
set (INCLUDE_INSTALL_DIR "include")
set (CONFIG_INSTALL_DIR "lib/cmake/${PACKAGE_NAME}")
set (PKGCONFIG_INSTALL_DIR)
else ()
set (RUNTIME_INSTALL_DIR bin)
# The LIB_INSTALL_DIR and LIB_SUFFIX variables are used by the Fedora
# package maintainers. Also package maintainers of other distribution
# packages need to be able to specify the name of the library directory.
if (NOT GFLAGS_LIBRARY_INSTALL_DIR AND LIB_INSTALL_DIR)
set (GFLAGS_LIBRARY_INSTALL_DIR "${LIB_INSTALL_DIR}")
endif ()
gflags_define (PATH LIBRARY_INSTALL_DIR "Directory of installed libraries, e.g., \"lib64\"" "lib${LIB_SUFFIX}")
gflags_property (LIBRARY_INSTALL_DIR ADVANCED TRUE)
set (INCLUDE_INSTALL_DIR include)
set (CONFIG_INSTALL_DIR ${LIBRARY_INSTALL_DIR}/cmake/${PACKAGE_NAME})
set (PKGCONFIG_INSTALL_DIR ${LIBRARY_INSTALL_DIR}/pkgconfig)
endif ()
# ----------------------------------------------------------------------------
# add library targets
set (TARGETS)
# static vs. shared
foreach (TYPE IN ITEMS STATIC SHARED)
if (BUILD_${TYPE}_LIBS)
string (TOLOWER "${TYPE}" type)
# whether or not targets are a DLL
if (OS_WINDOWS AND "^${TYPE}$" STREQUAL "^SHARED$")
set (GFLAGS_IS_A_DLL 1)
else ()
set (GFLAGS_IS_A_DLL 0)
endif ()
# filename suffix for static libraries on Windows for MSVC toolchain only
if (OS_WINDOWS AND NOT MINGW AND "^${TYPE}$" STREQUAL "^STATIC$")
set (type_suffix "_${type}")
else ()
set (type_suffix "")
endif ()
# multi-threaded vs. single-threaded
foreach (opts IN ITEMS "" _nothreads)
if (BUILD_gflags${opts}_LIB)
set (target_name "gflags${opts}_${type}")
add_library (${target_name} ${TYPE} ${GFLAGS_SRCS} ${PRIVATE_HDRS} ${PUBLIC_HDRS})
set_target_properties (${target_name} PROPERTIES
OUTPUT_NAME "gflags${opts}${type_suffix}"
VERSION "${PACKAGE_VERSION}"
SOVERSION "${PACKAGE_SOVERSION}"
)
set (include_dirs "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>")
if (INSTALL_HEADERS)
list (APPEND include_dirs "$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>")
endif ()
target_include_directories (${target_name}
PUBLIC "${include_dirs}"
PRIVATE "${PROJECT_SOURCE_DIR}/src;${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}"
)
target_compile_definitions (${target_name} PUBLIC GFLAGS_IS_A_DLL=${GFLAGS_IS_A_DLL})
if (opts MATCHES "nothreads")
target_compile_definitions (${target_name} PRIVATE NO_THREADS)
elseif (CMAKE_USE_PTHREADS_INIT)
target_link_libraries (${target_name} ${CMAKE_THREAD_LIBS_INIT})
endif ()
if (HAVE_SHLWAPI_H)
target_link_libraries (${target_name} shlwapi.lib)
endif ()
list (APPEND TARGETS ${target_name})
# add convenience make target for build of both shared and static libraries
if (NOT GFLAGS_IS_SUBPROJECT)
if (NOT TARGET gflags${opts})
add_custom_target (gflags${opts})
endif ()
add_dependencies (gflags${opts} ${target_name})
endif ()
endif ()
endforeach ()
endif ()
endforeach ()
# add ALIAS target for use in super-project, prefer static over shared, single-threaded over multi-threaded
if (GFLAGS_IS_SUBPROJECT)
foreach (type IN ITEMS static shared)
foreach (opts IN ITEMS "_nothreads" "")
if (TARGET gflags${opts}_${type})
# Define "gflags" alias for super-projects treating targets of this library as part of their own project
# (also for backwards compatibility with gflags 2.2.1 which only defined this alias)
add_library (gflags ALIAS gflags${opts}_${type})
# Define "gflags::gflags" alias for projects that support both find_package(gflags) and add_subdirectory(gflags)
add_library (gflags::gflags ALIAS gflags${opts}_${type})
break ()
endif ()
endforeach ()
if (TARGET gflags::gflags)
break ()
endif ()
endforeach ()
endif ()
# ----------------------------------------------------------------------------
# installation rules
set (EXPORT_NAME ${PACKAGE_NAME}-targets)
file (RELATIVE_PATH INSTALL_PREFIX_REL2CONFIG_DIR "${CMAKE_INSTALL_PREFIX}/${CONFIG_INSTALL_DIR}" "${CMAKE_INSTALL_PREFIX}")
configure_file (cmake/config.cmake.in "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config-install.cmake" @ONLY)
configure_file (cmake/version.cmake.in "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config-version.cmake" @ONLY)
if (BUILD_SHARED_LIBS AND INSTALL_SHARED_LIBS)
foreach (opts IN ITEMS "" _nothreads)
if (BUILD_gflags${opts}_LIB)
install (TARGETS gflags${opts}_shared
EXPORT ${EXPORT_NAME}
RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR}
LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${LIBRARY_INSTALL_DIR}
)
endif ()
endforeach ()
endif ()
if (BUILD_STATIC_LIBS AND INSTALL_STATIC_LIBS)
foreach (opts IN ITEMS "" _nothreads)
if (BUILD_gflags${opts}_LIB)
install (TARGETS gflags${opts}_static
EXPORT ${EXPORT_NAME}
RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR}
LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${LIBRARY_INSTALL_DIR}
)
endif ()
endforeach ()
endif ()
if (INSTALL_HEADERS)
install (FILES ${PUBLIC_HDRS} DESTINATION ${INCLUDE_INSTALL_DIR}/${GFLAGS_INCLUDE_DIR})
install (
FILES "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config-install.cmake"
RENAME ${PACKAGE_NAME}-config.cmake
DESTINATION ${CONFIG_INSTALL_DIR}
)
install (
FILES "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config-version.cmake"
DESTINATION ${CONFIG_INSTALL_DIR}
)
if (EXPORT_NAMESPACE_SET)
install (
EXPORT ${EXPORT_NAME}
NAMESPACE ${PACKAGE_NAME}::
DESTINATION ${CONFIG_INSTALL_DIR}
)
endif ()
if (EXPORT_NONAMESPACE_SET)
install (
EXPORT ${EXPORT_NAME}
FILE ${PACKAGE_NAME}-nonamespace-targets.cmake
DESTINATION ${CONFIG_INSTALL_DIR}
)
endif ()
if (UNIX)
install (PROGRAMS src/gflags_completions.sh DESTINATION ${RUNTIME_INSTALL_DIR})
endif ()
if (PKGCONFIG_INSTALL_DIR)
configure_file ("cmake/package.pc.in" "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}.pc" @ONLY)
install (FILES "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}.pc" DESTINATION "${PKGCONFIG_INSTALL_DIR}")
endif ()
endif ()
# ----------------------------------------------------------------------------
# support direct use of build tree
set (INSTALL_PREFIX_REL2CONFIG_DIR .)
if (EXPORT_NAMESPACE_SET)
export (
TARGETS ${TARGETS}
NAMESPACE ${PACKAGE_NAME}::
FILE "${PROJECT_BINARY_DIR}/${EXPORT_NAME}.cmake"
)
endif ()
if (EXPORT_NONAMESPACE_SET)
export (
TARGETS ${TARGETS}
FILE "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-nonamespace-targets.cmake"
)
endif ()
if (REGISTER_BUILD_DIR)
export (PACKAGE ${PACKAGE_NAME})
endif ()
if (REGISTER_INSTALL_PREFIX)
register_gflags_package(${CONFIG_INSTALL_DIR})
endif ()
configure_file (cmake/config.cmake.in "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-config.cmake" @ONLY)
# ----------------------------------------------------------------------------
# testing - MUST follow the generation of the build tree config file
if (BUILD_TESTING)
include (CTest)
add_subdirectory (test)
endif ()
# ----------------------------------------------------------------------------
# packaging
if (BUILD_PACKAGING)
if (NOT BUILD_SHARED_LIBS AND NOT INSTALL_HEADERS)
message (WARNING "Package will contain static libraries without headers!"
"\nRecommended options for generation of runtime package:"
"\n BUILD_SHARED_LIBS=ON"
"\n BUILD_STATIC_LIBS=OFF"
"\n INSTALL_HEADERS=OFF"
"\n INSTALL_SHARED_LIBS=ON"
"\nRecommended options for generation of development package:"
"\n BUILD_SHARED_LIBS=ON"
"\n BUILD_STATIC_LIBS=ON"
"\n INSTALL_HEADERS=ON"
"\n INSTALL_SHARED_LIBS=ON"
"\n INSTALL_STATIC_LIBS=ON"
)
endif ()
# default package generators
if (APPLE)
set (PACKAGE_GENERATOR "PackageMaker")
set (PACKAGE_SOURCE_GENERATOR "TGZ;ZIP")
elseif (UNIX)
set (PACKAGE_GENERATOR "DEB;RPM")
set (PACKAGE_SOURCE_GENERATOR "TGZ;ZIP")
else ()
set (PACKAGE_GENERATOR "ZIP")
set (PACKAGE_SOURCE_GENERATOR "ZIP")
endif ()
# used package generators
set (CPACK_GENERATOR "${PACKAGE_GENERATOR}" CACHE STRING "List of binary package generators (CPack).")
set (CPACK_SOURCE_GENERATOR "${PACKAGE_SOURCE_GENERATOR}" CACHE STRING "List of source package generators (CPack).")
mark_as_advanced (CPACK_GENERATOR CPACK_SOURCE_GENERATOR)
# some package generators (e.g., PackageMaker) do not allow .md extension
configure_file ("${CMAKE_CURRENT_LIST_DIR}/README.md" "${CMAKE_CURRENT_BINARY_DIR}/README.txt" COPYONLY)
# common package information
set (CPACK_PACKAGE_VENDOR "Andreas Schuh")
set (CPACK_PACKAGE_CONTACT "google-gflags@googlegroups.com")
set (CPACK_PACKAGE_NAME "${PACKAGE_NAME}")
set (CPACK_PACKAGE_VERSION "${PACKAGE_VERSION}")
set (CPACK_PACKAGE_VERSION_MAJOR "${PACKAGE_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${PACKAGE_VERSION_MINOR}")
set (CPACK_PACKAGE_VERSION_PATCH "${PACKAGE_VERSION_PATCH}")
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE_DESCRIPTION}")
set (CPACK_RESOURCE_FILE_WELCOME "${CMAKE_CURRENT_BINARY_DIR}/README.txt")
set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_LIST_DIR}/COPYING.txt")
set (CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_BINARY_DIR}/README.txt")
set (CPACK_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
set (CPACK_OUTPUT_FILE_PREFIX packages)
set (CPACK_PACKAGE_RELOCATABLE TRUE)
set (CPACK_MONOLITHIC_INSTALL TRUE)
# RPM package information -- used in cmake/package.cmake.in also for DEB
set (CPACK_RPM_PACKAGE_GROUP "Development/Libraries")
set (CPACK_RPM_PACKAGE_LICENSE "BSD")
set (CPACK_RPM_PACKAGE_URL "${PACKAGE_URL}")
set (CPACK_RPM_CHANGELOG_FILE "${CMAKE_CURRENT_LIST_DIR}/ChangeLog.txt")
if (INSTALL_HEADERS)
set (CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_LIST_DIR}/doc/index.html")
else ()
set (CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_LIST_DIR}/cmake/README_runtime.txt")
endif ()
# system/architecture
if (WINDOWS)
if (CMAKE_CL_64)
set (CPACK_SYSTEM_NAME "win64")
else ()
set (CPACK_SYSTEM_NAME "win32")
endif ()
set (CPACK_PACKAGE_ARCHITECTURE)
elseif (APPLE)
set (CPACK_PACKAGE_ARCHITECTURE darwin)
else ()
string (TOLOWER "${CMAKE_SYSTEM_NAME}" CPACK_SYSTEM_NAME)
if (CMAKE_CXX_FLAGS MATCHES "-m32")
set (CPACK_PACKAGE_ARCHITECTURE i386)
else ()
execute_process (
COMMAND dpkg --print-architecture
RESULT_VARIABLE RV
OUTPUT_VARIABLE CPACK_PACKAGE_ARCHITECTURE
)
if (RV EQUAL 0)
string (STRIP "${CPACK_PACKAGE_ARCHITECTURE}" CPACK_PACKAGE_ARCHITECTURE)
else ()
execute_process (COMMAND uname -m OUTPUT_VARIABLE CPACK_PACKAGE_ARCHITECTURE)
if (CPACK_PACKAGE_ARCHITECTURE MATCHES "x86_64")
set (CPACK_PACKAGE_ARCHITECTURE amd64)
else ()
set (CPACK_PACKAGE_ARCHITECTURE i386)
endif ()
endif ()
endif ()
endif ()
# source package settings
set (CPACK_SOURCE_TOPLEVEL_TAG "source")
set (CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
set (CPACK_SOURCE_IGNORE_FILES "/\\\\.git/;\\\\.swp$;\\\\.#;/#;\\\\.*~;cscope\\\\.*;/[Bb]uild[.+-_a-zA-Z0-9]*/")
# default binary package settings
set (CPACK_INCLUDE_TOPLEVEL_DIRECTORY TRUE)
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_SYSTEM_NAME}")
if (CPACK_PACKAGE_ARCHITECTURE)
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CPACK_PACKAGE_ARCHITECTURE}")
endif ()
# generator specific configuration file
#
# allow package maintainers to use their own configuration file
# $ cmake -DCPACK_PROJECT_CONFIG_FILE:FILE=/path/to/package/config
if (NOT CPACK_PROJECT_CONFIG_FILE)
configure_file (
"${CMAKE_CURRENT_LIST_DIR}/cmake/package.cmake.in"
"${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-package.cmake" @ONLY
)
set (CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-package.cmake")
endif ()
include (CPack)
endif () # BUILD_PACKAGING
if (NOT GFLAGS_IS_SUBPROJECT AND NOT TARGET uninstall)
configure_file (
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" @ONLY
)
add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
endif ()

View file

@ -1,14 +0,0 @@
Wed Dec 13 12:37:19 2006 Google Inc. <opensource@google.com>
* google-gflags: initial release:
The gflags package contains a library that implements commandline
flags processing. As such it's a replacement for getopt(). It
has increased flexibility, including built-in support for C++
types like string, and the ability to define flags in the source
file in which they're used.
Mon Jan 22 15:33:06 2007 Google Inc. <opensource@google.com>
* google-gflags: version 0.2
* added support for python commandlineflags, as well as c++
* gflags2man, a script to turn flags into a man page (dchristian)

276
ChangeLog.txt Normal file
View file

@ -0,0 +1,276 @@
* Sun Nov 11 2018 - Andreas Schuh <andreas.schuh.84@gmail.com>
- gflags: version 2.2.2
Fixed 267: Support build with GCC option "-fvisibility=hidden".
Fixed 262: Declare FLAGS_no##name variables as static to avoid "previous extern" warning.
Fixed 261: Declare FlagRegisterer ctor explicit template instanations as extern in header
Fixed 257: Build with _UNICODE support on Windows.
Fixed 233/234/235: Move CMake defines that are unused by Bazel to separate header; makes config.h private again
Fixed 228: Build with recent MinGW versions that define setenv.
Fixed 226: Remove obsolete and unused CleanFileName code
Merged 266: Various PVS Studio and GCC warnings.
Merged 258: Fix build with some Clang variants that define "restrict" macro.
Merged 252: Update documentation on how to use Bazel.
Merged 249: Use "_debug" postfix for debug libraries.
Merged 247: CMake "project" VERSION; no enable_testing(); "gflags::" import target prefix.
Merged 246: Add Bazel-on-Windows support.
Merged 239: Use GFLAGS_NAMESPACE instead of "gflags" in test executable.
Merged 237: Removed unused functions; fixes compilation with -Werror compiler option.
Merged 232: Fix typo in Bazel's BUILD definition
Merged 230: Remove using ::fLS::clstring.
Merged 221: Add convenience 'uninstall' target
* Tue Jul 11 2017 - Andreas Schuh <andreas.schuh.84@gmail.com>
- gflags: version 2.2.1
- Link to online documentation in README
- Merged 194: Include utils by file instead of CMAKE_MODULE_PATH search
- Merged 195: Remove unused program_name variable
- Merged 196: Enable language C for older CMake versions when needed
- Merged 202: Changed include directory in bazel build
- Merged 207: Mark single argument constructors in mutex.h as explicit
- Merged 209: Use inttypes.h on VC++ 2013 and later
- Merged 212: Fix statically linked gflags library with MSVC
- Merged 213: Modify installation paths on Windows for vcpkg
- Merged 215: Fix static initialization order fiasco caused by global registry lock
- Merged 216: Fix use of ARGC in CMake macros
- Merged 222: Static code analyzer error regarding strncmp with empty kRootDir
- Merged 224: Check HAVE_STDINT_H or HAVE_INTTYPES_H for older MSVC versions
* Fri Nov 25 2016 - Andreas Schuh <andreas.schuh.84@gmail.com>
- gflags: version 2.2.0
- Merged 178: Implicitly convert dashes in option names to underscores
- Merged 159: CI builds and automatic tests with Travis CI and AppVeyor
- Merged 158: Use enum for flag value types
- Merged 126: File name postfix for static libraries on Windows
- Closed issue 120: Configure and install gflags.pc file for pkg-config users
- Fixed issue 127: snprintf already defined when building with MSVC 2015
- Fixed issue 51/138: Memory leaks reported by valgrind
- Fixed issue 173: Validate flags only once
- Fixed issue 168: Unsigned and signed comparison in gflags_reporting.cc
- Fixed issues 176/153: Add -lpthread link argument to Bazel build, refactor BUILD rules
- Fixed issue 89: Add GFLAGS_IS_A_DLL to imported CMake target INTERFACE_COMPILE_DEFINITIONS
- Fixed issue 104: Set INTERFACE_INCLUDE_DIRECTORIES of exported CMake targets
- Fixed issue 174: Missing gflags-targets.cmake file after installation
- Fixed issue 186: Error linking to gflags IMPLIB with MSVC using CMake
- Closed issue 106: Add example project to test use of gflags library
* Tue Mar 24 2014 - Andreas Schuh <andreas.schuh.84@gmail.com>
- gflags: version 2.1.2
- Moved project to GitHub
- Added GFLAGS_NAMESPACE definition to gflags_declare.h
- Fixed issue 94: Keep "google" as primary namespace and import symbols into "gflags" namespace
- Fixed issue 96: Fix binary ABI compatibility with gflags 2.0 using "google" as primary namespace
- Fixed issue 97/101: Removed (patched) CMake modules and enabled C language instead
- Fixed issue 103: Set CMake policy CMP0042 to silence warning regarding MACOS_RPATH setting
* Sun Mar 20 2014 - Andreas Schuh <google-gflags@googlegroups.com>
- gflags: version 2.1.1
- Fixed issue 77: GFLAGS_IS_A_DLL expands to empty string in gflags_declare.h
- Fixed issue 79: GFLAGS_NAMESPACE not expanded to actual namespace in gflags_declare.h
- Fixed issue 80: Allow include path to differ from GFLAGS_NAMESPACE
* Thu Mar 20 2014 - Andreas Schuh <google-gflags@googlegroups.com>
- gflags: version 2.1.0
- Build system configuration using CMake instead of autotools
- CPack packaging support for Debian/Ubuntu, Red Hat, and Mac OS X
- Fixed issue 54: Fix "invalid suffix on literal" (C++11)
- Fixed issue 57: Use _strdup instead of strdup on Windows
- Fixed issue 62: Change all preprocessor include guards to start with GFLAGS_
- Fixed issue 64: Add DEFINE_validator macro
- Fixed issue 73: Warnings in Visual Studio 2010 and unable to compile unit test
* Wed Jan 25 2012 - Google Inc. <google-gflags@googlegroups.com>
- gflags: version 2.0
- Changed the 'official' gflags email in setup.py/etc
- Renamed google-gflags.sln to gflags.sln
- Changed copyright text to reflect Google's relinquished ownership
* Tue Dec 20 2011 - Google Inc. <opensource@google.com>
- google-gflags: version 1.7
- Add CommandLineFlagInfo::flag_ptr pointing to current storage (musji)
- PORTING: flush after writing to stderr, needed on cygwin
- PORTING: Clean up the GFLAGS_DLL_DECL stuff better
- Fix a bug in StringPrintf() that affected large strings (csilvers)
- Die at configure-time when g++ isn't installed
* Fri Jul 29 2011 - Google Inc. <opensource@google.com>
- google-gflags: version 1.6
- BUGFIX: Fix a bug where we were leaving out a required $(top_srcdir)
- Fix definition of clstring (jyrki)
- Split up flag declares into its own file (jyrki)
- Add --version support (csilvers)
- Update the README for gflags with static libs
- Update acx_pthread.m4 for nostdlib
- Change ReparseCommandLineFlags to return void (csilvers)
- Some doc typofixes and example augmentation (various)
* Mon Jan 24 2011 - Google Inc. <opensource@google.com>
- google-gflags: version 1.5
- Better reporting of current vs default value (handler)
- Add API for cleaning up of memory at program-exit (jmarantz)
- Fix macros to work inside namespaces (csilvers)
- Use our own string typedef in case string is redefined (csilvers)
- Updated to autoconf 2.65
* Wed Oct 13 2010 - Google Inc. <opensource@google.com>
- google-gflags: version 1.4
- Add a check to prevent passing 0 to DEFINE_string (jorg)
- Reduce compile (.o) size (jyrki)
- Some small changes to quiet debug compiles (alexk)
- PORTING: better support static linking on windows (csilvers)
- DOCUMENTATION: change default values, use validators, etc.
- Update the NEWS file to be non-empty
- Add pkg-config (.pc) files for libgflags and libgflags_nothreads
* Mon Jan 4 2010 - Google Inc. <opensource@google.com>
- google-gflags: version 1.3
- PORTABILITY: can now build and run tests under MSVC (csilvers)
- Remove the python gflags code, which is now its own package (tansell)
- Clarify that "last flag wins" in the docs (csilvers)
- Comment danger of using GetAllFlags in validators (wojtekm)
- PORTABILITY: Some fixes necessary for c++0x (mboerger)
- Makefile fix: $(srcdir) -> $(top_srcdir) in one place (csilvres)
- INSTALL: autotools to autoconf v2.64 + automake v1.11 (csilvers)
* Thu Sep 10 2009 - Google Inc. <opensource@google.com>
- google-gflags: version 1.2
- PORTABILITY: can now build and run tests under mingw (csilvers)
- Using a string arg for a bool flag is a compile-time error (rbayardo)
- Add --helpxml to gflags.py (salcianu)
- Protect against a hypothetical global d'tor mutex problem (csilvers)
- BUGFIX: can now define a flag after 'using namespace google' (hamaji)
* Tue Apr 14 2009 - Google Inc. <opensource@google.com>
- google-gflags: version 1.1
- Add both foo and nofoo for boolean flags, with --undefok (andychu)
- Better document how validators work (wojtekm)
- Improve binary-detection for bash-completion (mtamsky)
- Python: Add a concept of "key flags", used with --help (salcianu)
- Python: Robustify flag_values (salcianu)
- Python: Add a new DEFINE_bool alias (keir, andrewliu)
- Python: Do module introspection based on module name (dsturtevant)
- Fix autoconf a bit better, especially on windows and solaris (ajenjo)
- BUG FIX: gflags_nothreads was linking against the wrong lib (ajenjo)
- BUG FIX: threads-detection failed on FreeBSD; replace it (ajenjo)
- PORTABILITY: Quiet an internal compiler error with SUSE 10 (csilvers)
- PORTABILITY: Update deb.sh for more recently debuilds (csilvers)
- PORTABILITY: #include more headers to satisfy new gcc's (csilvers)
- INSTALL: Updated to autoconf 2.61 and libtool 1.5.26 (csilvers)
* Fri Oct 3 2008 - Google Inc. <opensource@google.com>
- google-gflags: version 1.0
- Add a missing newline to an error string (bcmills)
- (otherwise exactly the same as gflags 1.0rc2)
* Thu Sep 18 2008 - Google Inc. <opensource@google.com>
- google-gflags: version 1.0rc2
- Report current flag values in --helpxml (hdn)
- Fix compilation troubles with gcc 4.3.3 (simonb)
- BUG FIX: I was missing a std:: in DECLARE_string (csilvers)
- BUG FIX: Clarify in docs how to specify --bool flags (csilvers)
- BUG FIX: Fix --helpshort for source files not in a subdir (csilvers)
- BUG FIX: Fix python unittest for 64-bit builds (bcmills)
* Tue Aug 19 2008 - Google Inc. <opensource@google.com>
- google-gflags: version 1.0rc1
- Move #include files from google/ to gflags/ (csilvers)
- Small optimizations to reduce binary (library) size (jyrki)
- BUGFIX: forgot a std:: in one of the .h files (csilvers)
- Speed up locking by making sure calls are inlined (ajenjo)
- 64-BIT COMPATIBILITY: Use %PRId64 instead of %lld (csilvers)
- PORTABILITY: fix Makefile to work with Cygwin (ajenjo)
- PORTABILITY: fix code to compile under Visual Studio (ajenjo)
- PORTABILITY: fix code to compile under Solaris 10 with CC (csilvers)
* Mon Jul 21 2008 - Google Inc. <opensource@google.com>
- google-gflags: version 0.9
- Add the ability to validate a command-line flag (csilvers)
- Add completion support for commandline flags in bash (daven)
- Add -W compile flags to Makefile, when using gcc (csilvers)
- Allow helpstring to be NULL (cristianoc)
- Improved documentation of classes in the .cc file (csilvers)
- Fix python bug with AppendFlagValues + shortnames (jjtswan)
- Use bool instead of int for boolean flags in gflags.py (bcmills)
- Simplify the way we declare flags, now more foolproof (csilvers)
- Better error messages when bool flags collide (colohan)
- Only evaluate DEFINE_foo macro args once (csilvers)
* Wed Mar 26 2008 - Google Inc. <opensource@google.com>
- google-gflags: version 0.8
- Export DescribeOneFlag() in the API
- Add support for automatic line wrapping at 80 cols for gflags.py
- Bugfix: do not treat an isolated "-" the same as an isolated "--"
- Update rpm spec to point to Google Code rather than sourceforge (!)
- Improve documentation (including documenting thread-safety)
- Improve #include hygiene
- Improve testing
* Thu Oct 18 2007 - Google Inc. <opensource@google.com>
- google-gflags: version 0.7
- Deal even more correctly with libpthread not linked in (csilvers)
- Add STRIP_LOG, an improved DO_NOT_SHOW_COMMANDLINE_HELP (sioffe)
- Be more accurate printing default flag values in --help (dsturtevant)
- Reduce .o file size a bit by using shorter namespace names (jeff)
- Use relative install path, so 'setup.py --home' works (csilvers)
- Notice when a boolean flag has a non-boolean default (bnmouli)
- Broaden --helpshort to match foo-main.cc and foo_main.cc (hendrie)
- Fix "no modules match" message for --helpshort, etc (hendrie)
* Wed Aug 15 2007 - Google Inc. <opensource@google.com>
- google-gflags: version 0.6
- Deal correctly with case that libpthread is not linked in (csilvers)
- Update Makefile/tests so we pass "make distcheck" (csilvers)
- Document and test that last assignment to a flag wins (wan)
* Tue Jun 12 2007 - Google Inc. <opensource@google.com>
- google-gflags: version 0.5
- Include all m4 macros in the distribution (csilvers)
- Python: Fix broken data_files field in setup.py (sidlon)
- Python: better string serializing and unparsing (abo, csimmons)
- Fix checks for NaN and inf to work with Mac OS X (csilvers)
* Thu Apr 19 2007 - Google Inc. <opensource@google.com>
- google-gflags: version 0.4
- Remove is_default from GetCommandLineFlagInfo (csilvers)
- Portability fixes: includes, strtoll, gcc4.3 errors (csilvers)
- A few doc typo cleanups (csilvers)
* Wed Mar 28 2007 - Google Inc. <opensource@google.com>
- google-gflags: version 0.3
- python portability fix: use popen instead of subprocess (csilvers)
- Add is_default to CommandLineFlagInfo (pchien)
- Make docs a bit prettier (csilvers)
- Actually include the python files in the distribution! :-/ (csilvers)
* Mon Jan 22 2007 - Google Inc. <opensource@google.com>
- google-gflags: version 0.2
- added support for python commandlineflags, as well as c++
- gflags2man, a script to turn flags into a man page (dchristian)
* Wed Dec 13 2006 - Google Inc. <opensource@google.com>
- google-gflags: version 0.1

230
INSTALL
View file

@ -1,230 +0,0 @@
Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. (Caching is
disabled by default to prevent problems with accidental use of stale
cache files.)
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only need
`configure.ac' if you want to change it or regenerate `configure' using
a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not support the `VPATH'
variable, you have to compile the package for one architecture at a
time in the source code directory. After you have installed the
package for one architecture, use `make distclean' before reconfiguring
for another architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the `--target=TYPE' option to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
will cause the specified gcc to be used as the C compiler (unless it is
overridden in the site shell script).
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

97
INSTALL.md Normal file
View file

@ -0,0 +1,97 @@
# Installing a binary distribution package
No official binary distribution packages are provided by the gflags developers.
There may, however, be binary packages available for your operating system.
Please consult also the package repositories of your Linux distribution.
On Debian/Ubuntu Linux, gflags can be installed using the following command:
sudo apt-get install libgflags-dev
On macOS, [Homebrew](https://brew.sh/) includes a formula for gflags:
brew install gflags
# Compiling the source code with Bazel
To use gflags in a [Bazel](http://bazel.io) project, map it in as an external
dependency by editing your WORKSPACE file:
git_repository(
name = "com_github_gflags_gflags",
commit = "<INSERT COMMIT SHA HERE>",
remote = "https://github.com/gflags/gflags.git",
)
You can then add `@com_github_gflags_gflags//:gflags` to the `deps` section of a
`cc_binary` or `cc_library` rule, and `#include <gflags/gflags.h>` to include it
in your source code.
# Compiling the source code with vcpkg
You can download and install gflags using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
vcpkg install gflags
The gflags port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
# Compiling the source code with CMake
The build system of gflags is since version 2.1 based on [CMake](http://cmake.org).
The common steps to build, test, and install software are therefore:
1. Extract source files.
2. Create build directory and change to it.
3. Run CMake to configure the build tree.
4. Build the software using selected build tool.
5. Test the built software.
6. Install the built files.
On Unix-like systems with GNU Make as build tool, these build steps can be
summarized by the following sequence of commands executed in a shell,
where ```$package``` and ```$version``` are shell variables which represent
the name of this package and the obtained version of the software.
$ tar xzf gflags-$version-source.tar.gz
$ cd gflags-$version
$ mkdir build && cd build
$ ccmake ..
- Press 'c' to configure the build system and 'e' to ignore warnings.
- Set CMAKE_INSTALL_PREFIX and other CMake variables and options.
- Continue pressing 'c' until the option 'g' is available.
- Then press 'g' to generate the configuration files for GNU Make.
$ make
$ make test (optional)
$ make install (optional)
In the following, only gflags-specific CMake settings available to
configure the build and installation are documented. Note that most of these
variables are for advanced users and binary package maintainers only.
They usually do not have to be modified.
CMake Option | Description
--------------------------- | -------------------------------------------------------
CMAKE_INSTALL_PREFIX | Installation directory, e.g., "/usr/local" on Unix and "C:\Program Files\gflags" on Windows.
BUILD_SHARED_LIBS | Request build of dynamic link libraries.
BUILD_STATIC_LIBS | Request build of static link libraries. Implied if BUILD_SHARED_LIBS is OFF.
BUILD_PACKAGING | Enable binary package generation using CPack.
BUILD_TESTING | Build tests for execution by CTest.
BUILD_NC_TESTS | Request inclusion of negative compilation tests (requires Python).
BUILD_CONFIG_TESTS | Request inclusion of package configuration tests (requires Python).
BUILD_gflags_LIBS | Request build of multi-threaded gflags libraries (if threading library found).
BUILD_gflags_nothreads_LIBS | Request build of single-threaded gflags libraries.
GFLAGS_NAMESPACE | Name of the C++ namespace to be used by the gflags library. Note that the public source header files are installed in a subdirectory named after this namespace. To maintain backwards compatibility with the Google Commandline Flags, set this variable to "google". The default is "gflags".
GFLAGS_INTTYPES_FORMAT | String identifying format of built-in integer types.
GFLAGS_INCLUDE_DIR | Name of headers installation directory relative to CMAKE_INSTALL_PREFIX.
LIBRARY_INSTALL_DIR | Name of library installation directory relative to CMAKE_INSTALL_PREFIX.
INSTALL_HEADERS | Request installation of public header files.

4
MODULE.bazel Normal file
View file

@ -0,0 +1,4 @@
module(
name = "gflags",
compatibility_level = 1,
)

View file

@ -1,77 +0,0 @@
## This is a boilerplate file for Google opensource projects.
## To make it useful, replace <<TEXT>> with actual text for your project.
## Also, look at comments with "## double hashes" to see if any are worth
## uncommenting or modifying.
## Process this file with automake to produce Makefile.in
# Make sure that when we re-make ./configure, we get the macros we need
ACLOCAL_AMFLAGS = -I `pwd`/../autoconf
# This is so we can #include <google/foo>
AM_CPPFLAGS = -I$(top_srcdir)/src
googleincludedir = $(includedir)/google
## The .h files you want to install (that is, .h files that people
## who install this package can include in their own applications.)
googleinclude_HEADERS = src/google/gflags.h
docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION)
## This is for HTML and other documentation you want to install.
## Add your documentation files (in doc/) in addition to these
## top-level boilerplate files. Also add a TODO file if you have one.
dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \
doc/gflags.html
## The libraries (.so's) you want to install
lib_LTLIBRARIES =
## unittests you want to run when people type 'make check'.
## TESTS is for binary unittests, check_SCRIPTS for script-based unittests.
## TESTS_ENVIRONMENT sets environment variables for when you run unittest,
## but it only seems to take effect for *binary* unittests (argh!)
TESTS =
TESTS_ENVIRONMENT =
check_SCRIPTS =
# Every time you add a unittest to check_SCRIPTS, add it here too
noinst_SCRIPTS =
## vvvv RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS
lib_LTLIBRARIES += libgflags.la
libgflags_la_SOURCES = $(googleinclude_HEADERS) src/config.h \
src/gflags.cc src/gflags_reporting.cc
libgflags_la_CXXFLAGS = $(PTRHEAD_CFLAGS) -DNDEBUG
libgflags_la_LDFLAGS = $(PTRHEAD_CFLAGS)
libgflags_la_LIBADD = $(PTHREAD_LIBS)
TESTS += gflags_unittest
gflags_unittest_SOURCES = $(googleinclude_HEADERS) src/config.h \
src/gflags_unittest.cc
gflags_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
gflags_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
gflags_unittest_LDADD = libgflags.la $(PTHREAD_LIBS)
check_SCRIPTS += gflags_unittest_sh
noinst_SCRIPTS += src/gflags_unittest.sh
gflags_unittest_sh: gflags_unittest
$(top_srcdir)/src/gflags_unittest.sh $(PWD)/$<
## ^^^^ END OF RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS
## This should always include $(TESTS), but may also include other
## binaries that you compile but don't want automatically installed.
noinst_PROGRAMS = $(TESTS)
rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec
@cd packages && ./rpm.sh ${PACKAGE} ${VERSION}
deb: dist-gzip packages/deb.sh packages/deb/*
@cd packages && ./deb.sh ${PACKAGE} ${VERSION}
libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status --recheck
EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \
libtool $(SCRIPTS)

View file

@ -1,833 +0,0 @@
# Makefile.in generated by automake 1.9.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = .
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
noinst_PROGRAMS = $(am__EXEEXT_1)
DIST_COMMON = README $(am__configure_deps) $(dist_doc_DATA) \
$(googleinclude_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(top_srcdir)/configure \
$(top_srcdir)/src/config.h.in \
$(top_srcdir)/src/google/gflags.h.in AUTHORS COPYING ChangeLog \
INSTALL NEWS compile config.guess config.sub depcomp \
install-sh ltmain.sh missing mkinstalldirs
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno configure.status.lineno
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/src/config.h
CONFIG_CLEAN_FILES = src/google/gflags.h
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" \
"$(DESTDIR)$(googleincludedir)"
libLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(lib_LTLIBRARIES)
am__DEPENDENCIES_1 =
libgflags_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
am__objects_1 =
am_libgflags_la_OBJECTS = $(am__objects_1) libgflags_la-gflags.lo \
libgflags_la-gflags_reporting.lo
libgflags_la_OBJECTS = $(am_libgflags_la_OBJECTS)
am__EXEEXT_1 = gflags_unittest$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)
am_gflags_unittest_OBJECTS = $(am__objects_1) \
gflags_unittest-gflags_unittest.$(OBJEXT)
gflags_unittest_OBJECTS = $(am_gflags_unittest_OBJECTS)
gflags_unittest_DEPENDENCIES = libgflags.la $(am__DEPENDENCIES_1)
SCRIPTS = $(noinst_SCRIPTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/src
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(libgflags_la_SOURCES) $(gflags_unittest_SOURCES)
DIST_SOURCES = $(libgflags_la_SOURCES) $(gflags_unittest_SOURCES)
dist_docDATA_INSTALL = $(INSTALL_DATA)
DATA = $(dist_doc_DATA)
googleincludeHEADERS_INSTALL = $(INSTALL_HEADER)
HEADERS = $(googleinclude_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
am__remove_distdir = \
{ test ! -d $(distdir) \
|| { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
&& rm -fr $(distdir); }; }
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
distuninstallcheck_listfiles = find . -type f -print
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
F77 = @F77@
FFLAGS = @FFLAGS@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_LIBS = @PTHREAD_LIBS@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
ac_cv___attribute__ = @ac_cv___attribute__@
ac_cv_have___uint16 = @ac_cv_have___uint16@
ac_cv_have_inttypes_h = @ac_cv_have_inttypes_h@
ac_cv_have_stdint_h = @ac_cv_have_stdint_h@
ac_cv_have_systypes_h = @ac_cv_have_systypes_h@
ac_cv_have_u_int16_t = @ac_cv_have_u_int16_t@
ac_cv_have_uint16_t = @ac_cv_have_uint16_t@
ac_google_end_namespace = @ac_google_end_namespace@
ac_google_namespace = @ac_google_namespace@
ac_google_start_namespace = @ac_google_start_namespace@
acx_pthread_config = @acx_pthread_config@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
# Make sure that when we re-make ./configure, we get the macros we need
ACLOCAL_AMFLAGS = -I `pwd`/../autoconf
# This is so we can #include <google/foo>
AM_CPPFLAGS = -I$(top_srcdir)/src
googleincludedir = $(includedir)/google
googleinclude_HEADERS = src/google/gflags.h
docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION)
dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \
doc/gflags.html
lib_LTLIBRARIES = libgflags.la
TESTS = gflags_unittest
TESTS_ENVIRONMENT =
check_SCRIPTS = gflags_unittest_sh
# Every time you add a unittest to check_SCRIPTS, add it here too
noinst_SCRIPTS = src/gflags_unittest.sh
libgflags_la_SOURCES = $(googleinclude_HEADERS) src/config.h \
src/gflags.cc src/gflags_reporting.cc
libgflags_la_CXXFLAGS = $(PTRHEAD_CFLAGS) -DNDEBUG
libgflags_la_LDFLAGS = $(PTRHEAD_CFLAGS)
libgflags_la_LIBADD = $(PTHREAD_LIBS)
gflags_unittest_SOURCES = $(googleinclude_HEADERS) src/config.h \
src/gflags_unittest.cc
gflags_unittest_CXXFLAGS = $(PTHREAD_CFLAGS)
gflags_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
gflags_unittest_LDADD = libgflags.la $(PTHREAD_LIBS)
EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \
libtool $(SCRIPTS)
all: all-am
.SUFFIXES:
.SUFFIXES: .cc .lo .o .obj
am--refresh:
@:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \
cd $(srcdir) && $(AUTOMAKE) --gnu \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: $(am__configure_deps)
cd $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
src/config.h: src/stamp-h1
@if test ! -f $@; then \
rm -f src/stamp-h1; \
$(MAKE) src/stamp-h1; \
else :; fi
src/stamp-h1: $(top_srcdir)/src/config.h.in $(top_builddir)/config.status
@rm -f src/stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status src/config.h
$(top_srcdir)/src/config.h.in: $(am__configure_deps)
cd $(top_srcdir) && $(AUTOHEADER)
rm -f src/stamp-h1
touch $@
distclean-hdr:
-rm -f src/config.h src/stamp-h1
src/google/gflags.h: $(top_builddir)/config.status $(top_srcdir)/src/google/gflags.h.in
cd $(top_builddir) && $(SHELL) ./config.status $@
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
f=$(am__strip_dir) \
echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
$(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
else :; fi; \
done
uninstall-libLTLIBRARIES:
@$(NORMAL_UNINSTALL)
@set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
p=$(am__strip_dir) \
echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
$(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
done
clean-libLTLIBRARIES:
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" != "$$p" || dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libgflags.la: $(libgflags_la_OBJECTS) $(libgflags_la_DEPENDENCIES)
$(CXXLINK) -rpath $(libdir) $(libgflags_la_LDFLAGS) $(libgflags_la_OBJECTS) $(libgflags_la_LIBADD) $(LIBS)
clean-noinstPROGRAMS:
@list='$(noinst_PROGRAMS)'; for p in $$list; do \
f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
echo " rm -f $$p $$f"; \
rm -f $$p $$f ; \
done
gflags_unittest$(EXEEXT): $(gflags_unittest_OBJECTS) $(gflags_unittest_DEPENDENCIES)
@rm -f gflags_unittest$(EXEEXT)
$(CXXLINK) $(gflags_unittest_LDFLAGS) $(gflags_unittest_OBJECTS) $(gflags_unittest_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gflags_unittest-gflags_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgflags_la-gflags.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgflags_la-gflags_reporting.Plo@am__quote@
.cc.o:
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
.cc.obj:
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.cc.lo:
@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
libgflags_la-gflags.lo: src/gflags.cc
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgflags_la_CXXFLAGS) $(CXXFLAGS) -MT libgflags_la-gflags.lo -MD -MP -MF "$(DEPDIR)/libgflags_la-gflags.Tpo" -c -o libgflags_la-gflags.lo `test -f 'src/gflags.cc' || echo '$(srcdir)/'`src/gflags.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libgflags_la-gflags.Tpo" "$(DEPDIR)/libgflags_la-gflags.Plo"; else rm -f "$(DEPDIR)/libgflags_la-gflags.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gflags.cc' object='libgflags_la-gflags.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgflags_la_CXXFLAGS) $(CXXFLAGS) -c -o libgflags_la-gflags.lo `test -f 'src/gflags.cc' || echo '$(srcdir)/'`src/gflags.cc
libgflags_la-gflags_reporting.lo: src/gflags_reporting.cc
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgflags_la_CXXFLAGS) $(CXXFLAGS) -MT libgflags_la-gflags_reporting.lo -MD -MP -MF "$(DEPDIR)/libgflags_la-gflags_reporting.Tpo" -c -o libgflags_la-gflags_reporting.lo `test -f 'src/gflags_reporting.cc' || echo '$(srcdir)/'`src/gflags_reporting.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libgflags_la-gflags_reporting.Tpo" "$(DEPDIR)/libgflags_la-gflags_reporting.Plo"; else rm -f "$(DEPDIR)/libgflags_la-gflags_reporting.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gflags_reporting.cc' object='libgflags_la-gflags_reporting.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgflags_la_CXXFLAGS) $(CXXFLAGS) -c -o libgflags_la-gflags_reporting.lo `test -f 'src/gflags_reporting.cc' || echo '$(srcdir)/'`src/gflags_reporting.cc
gflags_unittest-gflags_unittest.o: src/gflags_unittest.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gflags_unittest_CXXFLAGS) $(CXXFLAGS) -MT gflags_unittest-gflags_unittest.o -MD -MP -MF "$(DEPDIR)/gflags_unittest-gflags_unittest.Tpo" -c -o gflags_unittest-gflags_unittest.o `test -f 'src/gflags_unittest.cc' || echo '$(srcdir)/'`src/gflags_unittest.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/gflags_unittest-gflags_unittest.Tpo" "$(DEPDIR)/gflags_unittest-gflags_unittest.Po"; else rm -f "$(DEPDIR)/gflags_unittest-gflags_unittest.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gflags_unittest.cc' object='gflags_unittest-gflags_unittest.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gflags_unittest_CXXFLAGS) $(CXXFLAGS) -c -o gflags_unittest-gflags_unittest.o `test -f 'src/gflags_unittest.cc' || echo '$(srcdir)/'`src/gflags_unittest.cc
gflags_unittest-gflags_unittest.obj: src/gflags_unittest.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gflags_unittest_CXXFLAGS) $(CXXFLAGS) -MT gflags_unittest-gflags_unittest.obj -MD -MP -MF "$(DEPDIR)/gflags_unittest-gflags_unittest.Tpo" -c -o gflags_unittest-gflags_unittest.obj `if test -f 'src/gflags_unittest.cc'; then $(CYGPATH_W) 'src/gflags_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/gflags_unittest.cc'; fi`; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/gflags_unittest-gflags_unittest.Tpo" "$(DEPDIR)/gflags_unittest-gflags_unittest.Po"; else rm -f "$(DEPDIR)/gflags_unittest-gflags_unittest.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gflags_unittest.cc' object='gflags_unittest-gflags_unittest.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gflags_unittest_CXXFLAGS) $(CXXFLAGS) -c -o gflags_unittest-gflags_unittest.obj `if test -f 'src/gflags_unittest.cc'; then $(CYGPATH_W) 'src/gflags_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/gflags_unittest.cc'; fi`
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
install-dist_docDATA: $(dist_doc_DATA)
@$(NORMAL_INSTALL)
test -z "$(docdir)" || $(mkdir_p) "$(DESTDIR)$(docdir)"
@list='$(dist_doc_DATA)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f=$(am__strip_dir) \
echo " $(dist_docDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(docdir)/$$f'"; \
$(dist_docDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(docdir)/$$f"; \
done
uninstall-dist_docDATA:
@$(NORMAL_UNINSTALL)
@list='$(dist_doc_DATA)'; for p in $$list; do \
f=$(am__strip_dir) \
echo " rm -f '$(DESTDIR)$(docdir)/$$f'"; \
rm -f "$(DESTDIR)$(docdir)/$$f"; \
done
install-googleincludeHEADERS: $(googleinclude_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(googleincludedir)" || $(mkdir_p) "$(DESTDIR)$(googleincludedir)"
@list='$(googleinclude_HEADERS)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f=$(am__strip_dir) \
echo " $(googleincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(googleincludedir)/$$f'"; \
$(googleincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(googleincludedir)/$$f"; \
done
uninstall-googleincludeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(googleinclude_HEADERS)'; for p in $$list; do \
f=$(am__strip_dir) \
echo " rm -f '$(DESTDIR)$(googleincludedir)/$$f'"; \
rm -f "$(DESTDIR)$(googleincludedir)/$$f"; \
done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
check-TESTS: $(TESTS)
@failed=0; all=0; xfail=0; xpass=0; skip=0; \
srcdir=$(srcdir); export srcdir; \
list='$(TESTS)'; \
if test -n "$$list"; then \
for tst in $$list; do \
if test -f ./$$tst; then dir=./; \
elif test -f $$tst; then dir=; \
else dir="$(srcdir)/"; fi; \
if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
*" $$tst "*) \
xpass=`expr $$xpass + 1`; \
failed=`expr $$failed + 1`; \
echo "XPASS: $$tst"; \
;; \
*) \
echo "PASS: $$tst"; \
;; \
esac; \
elif test $$? -ne 77; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
*" $$tst "*) \
xfail=`expr $$xfail + 1`; \
echo "XFAIL: $$tst"; \
;; \
*) \
failed=`expr $$failed + 1`; \
echo "FAIL: $$tst"; \
;; \
esac; \
else \
skip=`expr $$skip + 1`; \
echo "SKIP: $$tst"; \
fi; \
done; \
if test "$$failed" -eq 0; then \
if test "$$xfail" -eq 0; then \
banner="All $$all tests passed"; \
else \
banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
fi; \
else \
if test "$$xpass" -eq 0; then \
banner="$$failed of $$all tests failed"; \
else \
banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
fi; \
fi; \
dashes="$$banner"; \
skipped=""; \
if test "$$skip" -ne 0; then \
skipped="($$skip tests were not run)"; \
test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
dashes="$$skipped"; \
fi; \
report=""; \
if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
report="Please report to $(PACKAGE_BUGREPORT)"; \
test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
dashes="$$report"; \
fi; \
dashes=`echo "$$dashes" | sed s/./=/g`; \
echo "$$dashes"; \
echo "$$banner"; \
test -z "$$skipped" || echo "$$skipped"; \
test -z "$$report" || echo "$$report"; \
echo "$$dashes"; \
test "$$failed" -eq 0; \
else :; fi
distdir: $(DISTFILES)
$(am__remove_distdir)
mkdir $(distdir)
$(mkdir_p) $(distdir)/doc $(distdir)/packages $(distdir)/packages/rpm $(distdir)/src $(distdir)/src/google
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r $(distdir)
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
dist-bzip2: distdir
tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
$(am__remove_distdir)
dist-tarZ: distdir
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__remove_distdir)
dist-shar: distdir
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
$(am__remove_distdir)
dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
$(am__remove_distdir)
dist dist-all: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
esac
chmod -R a-w $(distdir); chmod a+w $(distdir)
mkdir $(distdir)/_build
mkdir $(distdir)/_inst
chmod a-w $(distdir)
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& cd $(distdir)/_build \
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
$(DISTCHECK_CONFIGURE_FLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
distuninstallcheck \
&& chmod -R a-w "$$dc_install_base" \
&& ({ \
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
} || { rm -rf "$$dc_destdir"; exit 1; }) \
&& rm -rf "$$dc_destdir" \
&& $(MAKE) $(AM_MAKEFLAGS) dist \
&& rm -rf $(DIST_ARCHIVES) \
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck
$(am__remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
distuninstallcheck:
@cd $(distuninstallcheck_dir) \
&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
|| { echo "ERROR: files left after uninstall:" ; \
if test -n "$(DESTDIR)"; then \
echo " (check DESTDIR support)"; \
fi ; \
$(distuninstallcheck_listfiles) ; \
exit 1; } >&2
distcleancheck: distclean
@if test '$(srcdir)' = . ; then \
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
exit 1 ; \
fi
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left in build directory after distclean:" ; \
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS)
$(MAKE) $(AM_MAKEFLAGS) check-TESTS
check: check-am
all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(DATA) \
$(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(googleincludedir)"; do \
test -z "$$dir" || $(mkdir_p) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
clean-noinstPROGRAMS mostlyclean-am
distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am: install-dist_docDATA install-googleincludeHEADERS
install-exec-am: install-libLTLIBRARIES
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-dist_docDATA uninstall-googleincludeHEADERS \
uninstall-info-am uninstall-libLTLIBRARIES
.PHONY: CTAGS GTAGS all all-am am--refresh check check-TESTS check-am \
clean clean-generic clean-libLTLIBRARIES clean-libtool \
clean-noinstPROGRAMS ctags dist dist-all dist-bzip2 dist-gzip \
dist-shar dist-tarZ dist-zip distcheck distclean \
distclean-compile distclean-generic distclean-hdr \
distclean-libtool distclean-tags distcleancheck distdir \
distuninstallcheck dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am \
install-dist_docDATA install-exec install-exec-am \
install-googleincludeHEADERS install-info install-info-am \
install-libLTLIBRARIES install-man install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags uninstall uninstall-am uninstall-dist_docDATA \
uninstall-googleincludeHEADERS uninstall-info-am \
uninstall-libLTLIBRARIES
gflags_unittest_sh: gflags_unittest
$(top_srcdir)/src/gflags_unittest.sh $(PWD)/$<
rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec
@cd packages && ./rpm.sh ${PACKAGE} ${VERSION}
deb: dist-gzip packages/deb.sh packages/deb/*
@cd packages && ./deb.sh ${PACKAGE} ${VERSION}
libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status --recheck
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

16
README
View file

@ -1,16 +0,0 @@
This repository contains both a C++ and a python implementation of the
Google commandline flags module. Documentation for the C++
implementation is in doc/. Documentation for the python
implementation is at the top of gflags/flags.py.
See INSTALL for (generic) installation instructions for C++: basically
./configure && make && make install
To install the python module, run
cd python; python ./setup.py install
When you install the python library, you also get a helper
application, gflags2man.py, installed into /usr/local/bin. You can
run gflags2man.py to create an instant man page, with all the
commandline flags and their docs, for any C++ or python program you've
written using the gflags library.

319
README.md Normal file
View file

@ -0,0 +1,319 @@
[![tests](https://github.com/gflags/gflags/actions/workflows/test.yml/badge.svg)](https://github.com/gflags/gflags/actions/workflows/test.yml)
The documentation of the gflags library is available online at https://gflags.github.io/gflags/.
11 November 2018
----------------
I've just released gflags 2.2.2.
This maintenance release improves life of Bazel users (no more "config.h" leaking into global include paths),
fixes build with recent MinGW versions, and silences a number of static code analyzer and compiler warnings.
The build targets exported by the CMake configuration of this library are now also prefixed by the package
name "gflags::" following a more recent (unwritten) CMake convention. The unprefixed target names are still
supported to avoid that dependent projects have to be modified due to this change in imported target names.
Please report any further issues with this release using the GitHub issue tracker.
11 July 2017
------------
I've just released gflags 2.2.1.
This maintenance release primarily fixes build issues on Windows and
false alarms reported by static code analyzers.
Please report any further issues with this release using the GitHub issue tracker.
25 November 2016
----------------
I've finally released gflags 2.2.0.
This release adds support for use of the gflags library as external dependency
not only in projects using CMake, but also [Bazel](https://bazel.build/),
or [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/).
One new minor feature is added in this release: when a command flag argument
contains dashes, these are implicitly converted to underscores.
This is to allow those used to separate words of the flag name by dashes
to do so, while the flag variable names are required to use underscores.
Memory leaks reported by valgrind should be resolved by this release.
This release fixes build errors with MS Visual Studio 2015.
Please report any further issues with this release using the GitHub issue tracker.
24 March 2015
-------------
I've just released gflags 2.1.2.
This release completes the namespace change fixes. In particular,
it restores binary ABI compatibility with release version 2.0.
The deprecated "google" namespace is by default still kept as
primary namespace while symbols are imported into the new "gflags" namespace.
This can be overridden using the CMake variable GFLAGS_NAMESPACE.
Other fixes of the build configuration are related to the (patched)
CMake modules FindThreads.cmake and CheckTypeSize.cmake. These have
been removed and instead the C language is enabled again even though
gflags is written in C++ only.
This release also marks the complete move of the gflags project
from Google Code to GitHub. Email addresses of original issue
reporters got lost in the process. Given the age of most issue reports,
this should be negligible.
Please report any further issues using the GitHub issue tracker.
30 March 2014
-------------
I've just released gflags 2.1.1.
This release fixes a few bugs in the configuration of gflags\_declare.h
and adds a separate GFLAGS\_INCLUDE\_DIR CMake variable to the build configuration.
Setting GFLAGS\_NAMESPACE to "google" no longer changes also the include
path of the public header files. This allows the use of the library with
other Google projects such as glog which still use the deprecated "google"
namespace for the gflags library, but include it as "gflags/gflags.h".
20 March 2014
-------------
I've just released gflags 2.1.
The major changes are the use of CMake for the build configuration instead
of the autotools and packaging support through CPack. The default namespace
of all C++ symbols is now "gflags" instead of "google". This can be
configured via the GFLAGS\_NAMESPACE variable.
This release compiles with all major compilers without warnings and passed
the unit tests on Ubuntu 12.04, Windows 7 (Visual Studio 2008 and 2010,
Cygwin, MinGW), and Mac OS X (Xcode 5.1).
The SVN repository on Google Code is now frozen and replaced by a Git
repository such that it can be used as Git submodule by projects. The main
hosting of this project remains at Google Code. Thanks to the distributed
character of Git, I can push (and pull) changes from both GitHub and Google Code
in order to keep the two public repositories in sync.
When fixing an issue for a pull request through either of these hosting
platforms, please reference the issue number as
[described here](https://code.google.com/p/support/wiki/IssueTracker#Integration_with_version_control).
For the further development, I am following the
[Git branching model](http://nvie.com/posts/a-successful-git-branching-model/)
with feature branch names prefixed by "feature/" and bugfix branch names
prefixed by "bugfix/", respectively.
Binary and source [packages](https://github.com/schuhschuh/gflags/releases) are available on GitHub.
14 January 2014
---------------
The migration of the build system to CMake is almost complete.
What remains to be done is rewriting the tests in Python such they can be
executed on non-Unix platforms and splitting them up into separate CTest tests.
Though merging these changes into the master branch yet remains to be done,
it is recommended to already start using the
[cmake-migration](https://github.com/schuhschuh/gflags/tree/cmake-migration) branch.
20 April 2013
-------------
More than a year has past since I (Andreas) took over the maintenance for
`gflags`. Only few minor changes have been made since then, much to my regret.
To get more involved and stimulate participation in the further
development of the library, I moved the project source code today to
[GitHub](https://github.com/schuhschuh/gflags).
I believe that the strengths of [Git](http://git-scm.com/) will allow for better community collaboration
as well as ease the integration of changes made by others. I encourage everyone
who would like to contribute to send me pull requests.
Git's lightweight feature branches will also provide the right tool for more
radical changes which should only be merged back into the master branch
after these are complete and implement the desired behavior.
The SVN repository remains accessible at Google Code and I will keep the
master branch of the Git repository hosted at GitHub and the trunk of the
Subversion repository synchronized. Initially, I was going to simply switch the
Google Code project to Git, but in this case the SVN repository would be
frozen and force everyone who would like the latest development changes to
use Git as well. Therefore I decided to host the public Git repository at GitHub
instead.
Please continue to report any issues with gflags on Google Code. The GitHub project will
only be used to host the Git repository.
One major change of the project structure I have in mind for the next weeks
is the migration from autotools to [CMake](http://www.cmake.org/).
Check out the (unstable!)
[cmake-migration](https://github.com/schuhschuh/gflags/tree/cmake-migration)
branch on GitHub for details.
25 January 2012
---------------
I've just released gflags 2.0.
The `google-gflags` project has been renamed to `gflags`. I
(csilvers) am stepping down as maintainer, to be replaced by Andreas
Schuh. Welcome to the team, Andreas! I've seen the energy you have
around gflags and the ideas you have for the project going forward,
and look forward to having you on the team.
I bumped the major version number up to 2 to reflect the new community
ownership of the project. All the [changes](ChangeLog.txt)
are related to the renaming. There are no functional changes from
gflags 1.7. In particular, I've kept the code in the namespace
`google`, though in a future version it should be renamed to `gflags`.
I've also kept the `/usr/local/include/google/` subdirectory as
synonym of `/usr/local/include/gflags/`, though the former name has
been obsolete for some time now.
18 January 2011
---------------
The `google-gflags` Google Code page has been renamed to
`gflags`, in preparation for the project being renamed to
`gflags`. In the coming weeks, I'll be stepping down as
maintainer for the gflags project, and as part of that Google is
relinquishing ownership of the project; it will now be entirely
community run. The name change reflects that shift.
20 December 2011
----------------
I've just released gflags 1.7. This is a minor release; the major
change is that `CommandLineFlagInfo` now exports the address in memory
where the flag is located. There has also been a bugfix involving
very long --help strings, and some other minor [changes](ChangeLog.txt).
29 July 2011
------------
I've just released gflags 1.6. The major new feature in this release
is support for setting version info, so that --version does something
useful.
One minor change has required bumping the library number:
`ReparseCommandlineFlags` now returns `void` instead of `int` (the int
return value was always meaningless). Though I doubt anyone ever used
this (meaningless) return value, technically it's a change to the ABI
that requires a version bump. A bit sad.
There's also a procedural change with this release: I've changed the
internal tools used to integrate Google-supplied patches for gflags
into the opensource release. These new tools should result in more
frequent updates with better change descriptions. They will also
result in future `ChangeLog` entries being much more verbose (for better
or for worse).
See the [ChangeLog](ChangeLog.txt) for a full list of changes for this release.
24 January 2011
---------------
I've just released gflags 1.5. This release has only minor changes
from 1.4, including some slightly better reporting in --help, and
an new memory-cleanup function that can help when running gflags-using
libraries under valgrind. The major change is to fix up the macros
(`DEFINE_bool` and the like) to work more reliably inside namespaces.
If you have not had a problem with these macros, and don't need any of
the other changes described, there is no need to upgrade. See the
[ChangeLog](ChangeLog.txt) for a full list of changes for this release.
11 October 2010
---------------
I've just released gflags 1.4. This release has only minor changes
from 1.3, including some documentation tweaks and some work to make
the library smaller. If 1.3 is working well for you, there's no
particular reason to upgrade.
4 January 2010
--------------
I've just released gflags 1.3. gflags now compiles under MSVC, and
all tests pass. I **really** never thought non-unix-y Windows folks
would want gflags, but at least some of them do.
The major news, though, is that I've separated out the python package
into its own library, [python-gflags](http://code.google.com/p/python-gflags).
If you're interested in the Python version of gflags, that's the place to
get it now.
10 September 2009
-----------------
I've just released gflags 1.2. The major change from gflags 1.1 is it
now compiles under MinGW (as well as cygwin), and all tests pass. I
never thought Windows folks would want unix-style command-line flags,
since they're so different from the Windows style, but I guess I was
wrong!
The other changes are minor, such as support for --htmlxml in the
python version of gflags.
15 April 2009
-------------
I've just released gflags 1.1. It has only minor changes fdrom gflags
1.0 (see the [ChangeLog](ChangeLog.txt) for details).
The major change is that I moved to a new system for creating .deb and .rpm files.
This allows me to create x86\_64 deb and rpm files.
In the process of moving to this new system, I noticed an
inconsistency: the tar.gz and .rpm files created libraries named
libgflags.so, but the deb file created libgoogle-gflags.so. I have
fixed the deb file to create libraries like the others. I'm no expert
in debian packaging, but I believe this has caused the package name to
change as well. Please let me know (at
[[mailto:google-gflags@googlegroups.com](mailto:google-gflags@googlegroups.com)
google-gflags@googlegroups.com]) if this causes problems for you --
especially if you know of a fix! I would be happy to change the deb
packages to add symlinks from the old library name to the new
(libgoogle-gflags.so -> libgflags.so), but that is beyond my knowledge
of how to make .debs.
If you've tried to install a .rpm or .deb and it doesn't work for you,
let me know. I'm excited to finally have 64-bit package files, but
there may still be some wrinkles in the new system to iron out.
1 October 2008
--------------
gflags 1.0rc2 was out for a few weeks without any issues, so gflags
1.0 is now released. This is much like gflags 0.9. The major change
is that the .h files have been moved from `/usr/include/google` to
`/usr/include/gflags`. While I have backwards-compatibility
forwarding headeds in place, please rewrite existing code to say
```
#include <gflags/gflags.h>
```
instead of
```
#include <google/gflags.h>
```
I've kept the default namespace to google. You can still change with
with the appropriate flag to the configure script (`./configure
--help` to see the flags). If you have feedback as to whether the
default namespace should change to gflags, which would be a
non-backwards-compatible change, send mail to
`google-gflags@googlegroups.com`!
Version 1.0 also has some neat new features, like support for bash
commandline-completion of help flags. See the [ChangeLog](ChangeLog.txt)
for more details.
If I don't hear any bad news for a few weeks, I'll release 1.0-final.

6
WORKSPACE Normal file
View file

@ -0,0 +1,6 @@
# Copyright 2006 Google Inc. All Rights Reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the COPYING.txt file.
# Bazel (http://bazel.io/) WORKSPACE file for gflags.
workspace(name="com_github_gflags_gflags")

7186
aclocal.m4 vendored

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,5 @@
cc_binary(
name = "expand_template",
srcs = ["expand_template.cc"],
visibility = ["//visibility:public"],
)

View file

@ -0,0 +1,63 @@
#include <fstream>
#include <regex>
#include <streambuf>
#include <string>
#include <string.h>
#include <vector>
struct Substitution {
std::basic_regex<char> regex;
std::string replacement;
};
// Simple app that does a regex search-and-replace on a template
// and outputs the result.
//
// To invoke:
// expand_template
// --template PATH
// --output PATH
// regex0;replacement0
// regex1;replacement1
// ...
//
// Since it's only used as a private implementation detail of a rule and not
// user invoked we don't bother with error checking.
int main(int argc, const char** argv) {
// Parse args.
const char* template_path = nullptr;
const char* output_path = nullptr;
std::vector<Substitution> substitutions;
for (int i = 1; i < argc; ++i) {
const char* arg = argv[i];
if (strcmp(arg, "--template") == 0) {
template_path = argv[++i];
} else if (strcmp(arg, "--output") == 0) {
output_path = argv[++i];
} else {
const char* mid = strchr(arg, ';');
if (mid != nullptr) {
substitutions.push_back(Substitution{
std::basic_regex<char>(arg, mid - arg),
std::string(mid + 1),
});
}
}
}
// Read template.
std::ifstream ifs(template_path);
std::string str(std::istreambuf_iterator<char>(ifs),
(std::istreambuf_iterator<char>()));
// Apply regexes.
for (const auto& subst : substitutions) {
str = std::regex_replace(str, subst.regex, subst.replacement);
}
// Output file.
std::ofstream file(output_path);
file << str;
return 0;
}

View file

@ -0,0 +1,35 @@
def _impl(ctx):
args = ctx.actions.args()
args.add("--template", ctx.file.template)
args.add("--output", ctx.outputs.out)
args.add_all([k + ';' + v for k, v in ctx.attr.substitutions.items()])
ctx.actions.run(
executable = ctx.executable._bin,
arguments = [args],
inputs = [ctx.file.template],
outputs = [ctx.outputs.out],
)
return [
DefaultInfo(
files = depset(direct = [ctx.outputs.out]),
runfiles = ctx.runfiles(files = [ctx.outputs.out]),
),
]
expanded_template = rule(
implementation = _impl,
attrs = {
"out": attr.output(mandatory = True),
"template": attr.label(
allow_single_file = True,
mandatory = True,
),
"substitutions": attr.string_dict(),
"_bin": attr.label(
default = "//bazel/expanded_template:expand_template",
executable = True,
allow_single_file = True,
cfg = "host",
),
},
)

108
bazel/gflags.bzl Normal file
View file

@ -0,0 +1,108 @@
load("//bazel/expanded_template:expanded_template.bzl", "expanded_template")
# ------------------------------------------------------------------------------
# Add native rules to configure source files
def gflags_sources(namespace = ["google", "gflags"]):
expanded_template(
name = "gflags_declare_h",
template = "src/gflags_declare.h.in",
out = "gflags_declare.h",
substitutions = {
"@GFLAGS_NAMESPACE@": namespace[0],
"@(HAVE_STDINT_H|HAVE_SYS_TYPES_H|HAVE_INTTYPES_H|GFLAGS_INTTYPES_FORMAT_C99)@": "1",
"@([A-Z0-9_]+)@": "0",
},
)
gflags_ns_h_files = []
for ns in namespace[1:]:
gflags_ns_h_file = "gflags_{}.h".format(ns)
expanded_template(
name = gflags_ns_h_file.replace(".", "_"),
template = "src/gflags_ns.h.in",
out = gflags_ns_h_file,
substitutions = {
"@ns@": ns,
"@NS@": ns.upper(),
},
)
gflags_ns_h_files.append(gflags_ns_h_file)
expanded_template(
name = "gflags_h",
template = "src/gflags.h.in",
out = "gflags.h",
substitutions = {
"@GFLAGS_ATTRIBUTE_UNUSED@": "",
"@INCLUDE_GFLAGS_NS_H@": "\n".join(["#include \"gflags/{}\"".format(hdr) for hdr in gflags_ns_h_files]),
},
)
expanded_template(
name = "gflags_completions_h",
template = "src/gflags_completions.h.in",
out = "gflags_completions.h",
substitutions = {
"@GFLAGS_NAMESPACE@": namespace[0],
},
)
hdrs = [":gflags_h", ":gflags_declare_h", ":gflags_completions_h"]
hdrs.extend([":" + hdr.replace(".", "_") for hdr in gflags_ns_h_files])
srcs = [
"src/config.h",
"src/gflags.cc",
"src/gflags_completions.cc",
"src/gflags_reporting.cc",
"src/mutex.h",
"src/util.h",
] + select({
"//:x64_windows": [
"src/windows_port.cc",
"src/windows_port.h",
],
"//conditions:default": [],
})
return [hdrs, srcs]
# ------------------------------------------------------------------------------
# Add native rule to build gflags library
def gflags_library(hdrs = [], srcs = [], threads = 1):
name = "gflags"
copts = [
"-DGFLAGS_BAZEL_BUILD",
"-DGFLAGS_INTTYPES_FORMAT_C99",
"-DGFLAGS_IS_A_DLL=0",
# macros otherwise defined by CMake configured defines.h file
"-DHAVE_STDINT_H",
"-DHAVE_SYS_TYPES_H",
"-DHAVE_INTTYPES_H",
"-DHAVE_SYS_STAT_H",
"-DHAVE_STRTOLL",
"-DHAVE_STRTOQ",
"-DHAVE_RWLOCK",
] + select({
"//:x64_windows": [
"-DOS_WINDOWS",
],
"//conditions:default": [
"-DHAVE_UNISTD_H",
"-DHAVE_FNMATCH_H",
"-DHAVE_PTHREAD",
],
})
linkopts = []
if threads:
linkopts += select({
"//:android": [],
"//:x64_windows": [],
"//conditions:default": ["-lpthread"],
})
else:
name += "_nothreads"
copts += ["-DNO_THREADS"]
native.cc_library(
name = name,
hdrs = hdrs,
srcs = srcs,
copts = copts,
linkopts = linkopts,
visibility = ["//visibility:public"],
include_prefix = "gflags",
)

4
cmake/README_runtime.txt Normal file
View file

@ -0,0 +1,4 @@
This package contains runtime libraries only which are required
by applications that use these libraries for the commandline flags
processing. If you want to develop such application, download
and install the development package instead.

View file

@ -0,0 +1,26 @@
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
if (NOT DEFINED CMAKE_INSTALL_PREFIX)
set (CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@")
endif ()
message(${CMAKE_INSTALL_PREFIX})
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif(NOT "${rm_retval}" STREQUAL 0)
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
endforeach(file)

183
cmake/config.cmake.in Normal file
View file

@ -0,0 +1,183 @@
## gflags CMake configuration file
# library version information
set (@PACKAGE_PREFIX@_VERSION_STRING "@PACKAGE_VERSION@")
set (@PACKAGE_PREFIX@_VERSION_MAJOR @PACKAGE_VERSION_MAJOR@)
set (@PACKAGE_PREFIX@_VERSION_MINOR @PACKAGE_VERSION_MINOR@)
set (@PACKAGE_PREFIX@_VERSION_PATCH @PACKAGE_VERSION_PATCH@)
# import targets
if (NOT DEFINED @PACKAGE_PREFIX@_USE_TARGET_NAMESPACE)
set (@PACKAGE_PREFIX@_USE_TARGET_NAMESPACE FALSE)
endif ()
if (@PACKAGE_PREFIX@_USE_TARGET_NAMESPACE)
include ("${CMAKE_CURRENT_LIST_DIR}/@EXPORT_NAME@.cmake")
set (@PACKAGE_PREFIX@_TARGET_NAMESPACE @PACKAGE_NAME@)
else ()
include ("${CMAKE_CURRENT_LIST_DIR}/@PACKAGE_NAME@-nonamespace-targets.cmake")
set (@PACKAGE_PREFIX@_TARGET_NAMESPACE)
endif ()
if (@PACKAGE_PREFIX@_TARGET_NAMESPACE)
set (@PACKAGE_PREFIX@_TARGET_PREFIX ${@PACKAGE_PREFIX@_TARGET_NAMESPACE}::)
else ()
set (@PACKAGE_PREFIX@_TARGET_PREFIX)
endif ()
# installation prefix
get_filename_component (CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component (_INSTALL_PREFIX "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_PREFIX_REL2CONFIG_DIR@" ABSOLUTE)
# include directory
#
# Newer versions of CMake set the INTERFACE_INCLUDE_DIRECTORIES property
# of the imported targets. It is hence not necessary to add this path
# manually to the include search path for targets which link to gflags.
set (@PACKAGE_PREFIX@_INCLUDE_DIR "${_INSTALL_PREFIX}/@INCLUDE_INSTALL_DIR@")
if (@PACKAGE_NAME@_FIND_COMPONENTS)
foreach (@PACKAGE_NAME@_FIND_COMPONENT IN LISTS @PACKAGE_NAME@_FIND_COMPONENTS)
if (@PACKAGE_NAME@_FIND_REQUIRED_${@PACKAGE_NAME@_FIND_COMPONENT} AND NOT TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_${@PACKAGE_NAME@_FIND_COMPONENT})
message (FATAL_ERROR "Package @PACKAGE_NAME@ was installed without required component ${@PACKAGE_PREFIX@_TARGET_PREFIX}${@PACKAGE_NAME@_FIND_COMPONENT}!")
endif ()
endforeach ()
list (GET @PACKAGE_NAME@_FIND_COMPONENTS 0 @PACKAGE_NAME@_FIND_COMPONENT)
else ()
set (@PACKAGE_NAME@_FIND_COMPONENT)
endif ()
# default settings of @PACKAGE_PREFIX@_SHARED and @PACKAGE_PREFIX@_NOTHREADS
#
# It is recommended to use either one of the following find_package commands
# instead of setting the @PACKAGE_PREFIX@_(SHARED|NOTHREADS) variables:
# - find_package(@PACKAGE_NAME@ REQUIRED)
# - find_package(@PACKAGE_NAME@ COMPONENTS nothreads_static)
# - find_package(@PACKAGE_NAME@ COMPONENTS nothreads_shared)
# - find_package(@PACKAGE_NAME@ COMPONENTS static)
# - find_package(@PACKAGE_NAME@ COMPONENTS shared)
if (NOT DEFINED @PACKAGE_PREFIX@_SHARED)
if (DEFINED @PACKAGE_NAME@_SHARED)
set (@PACKAGE_PREFIX@_SHARED ${@PACKAGE_NAME@_SHARED})
elseif (@PACKAGE_NAME@_FIND_COMPONENT)
if (@PACKAGE_NAME@_FIND_COMPONENT MATCHES "shared")
set (@PACKAGE_PREFIX@_SHARED TRUE)
else ()
set (@PACKAGE_PREFIX@_SHARED FALSE)
endif ()
elseif (TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_shared OR TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_nothreads_shared)
set (@PACKAGE_PREFIX@_SHARED TRUE)
else ()
set (@PACKAGE_PREFIX@_SHARED FALSE)
endif ()
endif ()
if (NOT DEFINED @PACKAGE_PREFIX@_NOTHREADS)
if (DEFINED @PACKAGE_NAME@_NOTHREADS)
set (@PACKAGE_PREFIX@_NOTHREADS ${@PACKAGE_NAME@_NOTHREADS})
elseif (@PACKAGE_NAME@_FIND_COMPONENT)
if (@PACKAGE_NAME@_FIND_COMPONENT MATCHES "nothreads")
set (@PACKAGE_PREFIX@_NOTHREADS TRUE)
else ()
set (@PACKAGE_PREFIX@_NOTHREADS FALSE)
endif ()
elseif (TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_static OR TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_shared)
set (@PACKAGE_PREFIX@_NOTHREADS FALSE)
else ()
set (@PACKAGE_PREFIX@_NOTHREADS TRUE)
endif ()
endif ()
# choose imported library target
if (NOT @PACKAGE_PREFIX@_TARGET)
if (@PACKAGE_NAME@_TARGET)
set (@PACKAGE_PREFIX@_TARGET ${@PACKAGE_NAME@_TARGET})
elseif (@PACKAGE_PREFIX@_SHARED)
if (@PACKAGE_PREFIX@_NOTHREADS)
set (@PACKAGE_PREFIX@_TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_nothreads_shared)
else ()
set (@PACKAGE_PREFIX@_TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_shared)
endif ()
else ()
if (@PACKAGE_PREFIX@_NOTHREADS)
set (@PACKAGE_PREFIX@_TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_nothreads_static)
else ()
set (@PACKAGE_PREFIX@_TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@_static)
endif ()
endif ()
endif ()
if (NOT TARGET ${@PACKAGE_PREFIX@_TARGET})
message (FATAL_ERROR "Your @PACKAGE_NAME@ installation does not contain a ${@PACKAGE_PREFIX@_TARGET} library target!"
" Try a different combination of @PACKAGE_PREFIX@_SHARED and @PACKAGE_PREFIX@_NOTHREADS.")
endif ()
# add more convenient "${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@" import target
if (NOT TARGET ${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@)
if (@PACKAGE_PREFIX@_SHARED)
add_library (${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@ SHARED IMPORTED)
else ()
add_library (${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@ STATIC IMPORTED)
endif ()
# copy INTERFACE_* properties
foreach (_@PACKAGE_PREFIX@_PROPERTY_NAME IN ITEMS
COMPILE_DEFINITIONS
COMPILE_FEATURES
COMPILE_OPTIONS
INCLUDE_DIRECTORIES
LINK_LIBRARIES
POSITION_INDEPENDENT_CODE
)
get_target_property (_@PACKAGE_PREFIX@_PROPERTY_VALUE ${@PACKAGE_PREFIX@_TARGET} INTERFACE_${_@PACKAGE_PREFIX@_PROPERTY_NAME})
if (_@PACKAGE_PREFIX@_PROPERTY_VALUE)
set_target_properties(${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@ PROPERTIES
INTERFACE_${_@PACKAGE_PREFIX@_PROPERTY_NAME} "${_@PACKAGE_PREFIX@_PROPERTY_VALUE}"
)
endif ()
endforeach ()
# copy IMPORTED_*_<CONFIG> properties
get_target_property (_@PACKAGE_PREFIX@_CONFIGURATIONS ${@PACKAGE_PREFIX@_TARGET} IMPORTED_CONFIGURATIONS)
set_target_properties (${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@ PROPERTIES IMPORTED_CONFIGURATIONS "${_@PACKAGE_PREFIX@_CONFIGURATIONS}")
foreach (_@PACKAGE_PREFIX@_PROPERTY_NAME IN ITEMS
IMPLIB
LOCATION
LINK_DEPENDENT_LIBRARIES
LINK_INTERFACE_LIBRARIES
LINK_INTERFACE_LANGUAGES
LINK_INTERFACE_MULTIPLICITY
NO_SONAME
SONAME
)
foreach (_@PACKAGE_PREFIX@_CONFIG IN LISTS _@PACKAGE_PREFIX@_CONFIGURATIONS)
get_target_property (_@PACKAGE_PREFIX@_PROPERTY_VALUE ${@PACKAGE_PREFIX@_TARGET} IMPORTED_${_@PACKAGE_PREFIX@_PROPERTY_NAME}_${_@PACKAGE_PREFIX@_CONFIG})
if (_@PACKAGE_PREFIX@_PROPERTY_VALUE)
set_target_properties(${@PACKAGE_PREFIX@_TARGET_PREFIX}@PACKAGE_NAME@ PROPERTIES
IMPORTED_${_@PACKAGE_PREFIX@_PROPERTY_NAME}_${_@PACKAGE_PREFIX@_CONFIG} "${_@PACKAGE_PREFIX@_PROPERTY_VALUE}"
)
endif ()
endforeach ()
endforeach ()
unset (_@PACKAGE_PREFIX@_CONFIGURATIONS)
unset (_@PACKAGE_PREFIX@_CONFIG)
unset (_@PACKAGE_PREFIX@_PROPERTY_NAME)
unset (_@PACKAGE_PREFIX@_PROPERTY_VALUE)
endif ()
# alias for default import target to be compatible with older CMake package configurations
set (@PACKAGE_PREFIX@_LIBRARIES "${@PACKAGE_PREFIX@_TARGET}")
# set @PACKAGE_NAME@_* variables for backwards compatibility
if (NOT "^@PACKAGE_NAME@$" STREQUAL "^@PACKAGE_PREFIX@$")
foreach (_@PACKAGE_PREFIX@_VARIABLE IN ITEMS
VERSION_STRING
VERSION_MAJOR
VERSION_MINOR
VERSION_PATCH
INCLUDE_DIR
LIBRARIES
TARGET
)
set (@PACKAGE_NAME@_${_@PACKAGE_PREFIX@_VARIABLE} "${@PACKAGE_PREFIX@_${_@PACKAGE_PREFIX@_VARIABLE}}")
endforeach ()
unset (_@PACKAGE_PREFIX@_VARIABLE)
endif ()
# unset private variables
unset (@PACKAGE_NAME@_FIND_COMPONENT)
unset (_INSTALL_PREFIX)

53
cmake/execute_test.cmake Normal file
View file

@ -0,0 +1,53 @@
# ----------------------------------------------------------------------------
# sanitize string stored in variable for use in regular expression.
macro (sanitize_for_regex STRVAR)
string (REGEX REPLACE "([.+*?^$()])" "\\\\\\1" ${STRVAR} "${${STRVAR}}")
endmacro ()
# ----------------------------------------------------------------------------
# script arguments
if (NOT COMMAND)
message (FATAL_ERROR "Test command not specified!")
endif ()
if (NOT DEFINED EXPECTED_RC)
set (EXPECTED_RC 0)
endif ()
if (EXPECTED_OUTPUT)
sanitize_for_regex(EXPECTED_OUTPUT)
endif ()
if (UNEXPECTED_OUTPUT)
sanitize_for_regex(UNEXPECTED_OUTPUT)
endif ()
# ----------------------------------------------------------------------------
# set a few environment variables (useful for --tryfromenv)
set (ENV{FLAGS_undefok} "foo,bar")
set (ENV{FLAGS_weirdo} "")
set (ENV{FLAGS_version} "true")
set (ENV{FLAGS_help} "false")
# ----------------------------------------------------------------------------
# execute test command
execute_process(
COMMAND ${COMMAND}
RESULT_VARIABLE RC
OUTPUT_VARIABLE OUTPUT
ERROR_VARIABLE OUTPUT
)
if (OUTPUT)
message ("${OUTPUT}")
endif ()
# ----------------------------------------------------------------------------
# check test result
if (NOT RC EQUAL EXPECTED_RC)
string (REPLACE ";" " " COMMAND "${COMMAND}")
message (FATAL_ERROR "Command:\n\t${COMMAND}\nExit status is ${RC}, expected ${EXPECTED_RC}")
endif ()
if (EXPECTED_OUTPUT AND NOT OUTPUT MATCHES "${EXPECTED_OUTPUT}")
message (FATAL_ERROR "Test output does not match expected output: ${EXPECTED_OUTPUT}")
endif ()
if (UNEXPECTED_OUTPUT AND OUTPUT MATCHES "${UNEXPECTED_OUTPUT}")
message (FATAL_ERROR "Test output matches unexpected output: ${UNEXPECTED_OUTPUT}")
endif ()

49
cmake/package.cmake.in Normal file
View file

@ -0,0 +1,49 @@
# Per-generator CPack configuration file. See CPACK_PROJECT_CONFIG_FILE documented at
# http://www.cmake.org/cmake/help/v2.8.12/cpack.html#variable:CPACK_PROJECT_CONFIG_FILE
#
# All common CPACK_* variables are set in CMakeLists.txt already. This file only
# overrides some of these to provide package generator specific settings.
# whether package contains all development files or only runtime files
set (DEVEL @INSTALL_HEADERS@)
# ------------------------------------------------------------------------------
# Mac OS X package
if (CPACK_GENERATOR MATCHES "PackageMaker|DragNDrop")
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}")
if (DEVEL)
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-devel")
endif ()
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CPACK_PACKAGE_VERSION}")
# ------------------------------------------------------------------------------
# Debian package
elseif (CPACK_GENERATOR MATCHES "DEB")
set (CPACK_PACKAGE_FILE_NAME "lib${CPACK_PACKAGE_NAME}")
if (DEVEL)
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-dev")
else ()
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}0")
endif ()
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}_${CPACK_PACKAGE_VERSION}-1_${CPACK_PACKAGE_ARCHITECTURE}")
set (CPACK_DEBIAN_PACKAGE_DEPENDS)
set (CPACK_DEBIAN_PACKAGE_SECTION "devel")
set (CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set (CPACK_DEBIAN_PACKAGE_HOMEPAGE "${CPACK_RPM_PACKAGE_URL}")
set (CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_PACKAGE_VENDOR}")
set (CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${CPACK_PACKAGE_ARCHITECTURE}")
# ------------------------------------------------------------------------------
# RPM package
elseif (CPACK_GENERATOR MATCHES "RPM")
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}")
if (DEVEL)
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-devel")
endif ()
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CPACK_PACKAGE_VERSION}-1.${CPACK_PACKAGE_ARCHITECTURE}")
endif ()

14
cmake/package.pc.in Normal file
View file

@ -0,0 +1,14 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
bindir=${exec_prefix}/@RUNTIME_INSTALL_DIR@
libdir=${exec_prefix}/@LIBRARY_INSTALL_DIR@
includedir=${prefix}/@INCLUDE_INSTALL_DIR@
Name: @PACKAGE_NAME@
Version: @PACKAGE_VERSION@
Description: @PACKAGE_DESCRIPTION@
URL: @PACKAGE_URL@
Requires:
Libs: -L${libdir} -lgflags
Libs.private: -lpthread
Cflags: -I${includedir}

207
cmake/utils.cmake Normal file
View file

@ -0,0 +1,207 @@
## Utility CMake functions.
# ----------------------------------------------------------------------------
## Convert boolean value to 0 or 1
macro (bool_to_int VAR)
if (${VAR})
set (${VAR} 1)
else ()
set (${VAR} 0)
endif ()
endmacro ()
# ----------------------------------------------------------------------------
## Extract version numbers from version string
function (version_numbers version major minor patch)
if (version MATCHES "([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(rc[1-9][0-9]*|[a-z]+)?")
if (CMAKE_MATCH_1)
set (_major ${CMAKE_MATCH_1})
else ()
set (_major 0)
endif ()
if (CMAKE_MATCH_2)
set (_minor ${CMAKE_MATCH_2})
string (REGEX REPLACE "^\\." "" _minor "${_minor}")
else ()
set (_minor 0)
endif ()
if (CMAKE_MATCH_3)
set (_patch ${CMAKE_MATCH_3})
string (REGEX REPLACE "^\\." "" _patch "${_patch}")
else ()
set (_patch 0)
endif ()
else ()
set (_major 0)
set (_minor 0)
set (_patch 0)
endif ()
set ("${major}" "${_major}" PARENT_SCOPE)
set ("${minor}" "${_minor}" PARENT_SCOPE)
set ("${patch}" "${_patch}" PARENT_SCOPE)
endfunction ()
# ----------------------------------------------------------------------------
## Determine if cache entry exists
macro (gflags_is_cached retvar varname)
if (DEFINED ${varname})
get_property (${retvar} CACHE ${varname} PROPERTY TYPE SET)
else ()
set (${retvar} FALSE)
endif ()
endmacro ()
# ----------------------------------------------------------------------------
## Add gflags configuration variable
#
# The default value of the (cached) configuration value can be overridden either
# on the CMake command-line or the super-project by setting the GFLAGS_<varname>
# variable. When gflags is a subproject of another project (GFLAGS_IS_SUBPROJECT),
# the variable is not added to the CMake cache. Otherwise it is cached.
macro (gflags_define type varname docstring default)
# note that ARGC must be expanded here, as it is not a "real" variable
# (see the CMake documentation for the macro command)
if ("${ARGC}" GREATER 5)
message (FATAL_ERROR "gflags_variable: Too many macro arguments")
endif ()
if (NOT DEFINED GFLAGS_${varname})
if (DEFINED ${varname})
set (GFLAGS_${varname} "${${varname}}")
else ()
if (GFLAGS_IS_SUBPROJECT AND "${ARGC}" EQUAL 5)
set (GFLAGS_${varname} "${ARGV4}")
else ()
set (GFLAGS_${varname} "${default}")
endif ()
endif ()
endif ()
if (GFLAGS_IS_SUBPROJECT)
set (${varname} "${GFLAGS_${varname}}")
else ()
set (${varname} "${GFLAGS_${varname}}" CACHE ${type} "${docstring}")
endif ()
endmacro ()
# ----------------------------------------------------------------------------
## Set property of cached gflags configuration variable
macro (gflags_property varname property value)
gflags_is_cached (_cached ${varname})
if (_cached)
# note that property must be expanded here, as it is not a "real" variable
# (see the CMake documentation for the macro command)
if ("${property}" STREQUAL "ADVANCED")
if (${value})
mark_as_advanced (FORCE ${varname})
else ()
mark_as_advanced (CLEAR ${varname})
endif ()
else ()
set_property (CACHE ${varname} PROPERTY "${property}" "${value}")
endif ()
endif ()
unset (_cached)
endmacro ()
# ----------------------------------------------------------------------------
## Modify value of gflags configuration variable
macro (gflags_set varname value)
gflags_is_cached (_cached ${varname})
if (_cached)
set_property (CACHE ${varname} PROPERTY VALUE "${value}")
else ()
set (${varname} "${value}")
endif ()
unset (_cached)
endmacro ()
# ----------------------------------------------------------------------------
## Configure public header files
function (configure_headers out)
set (tmp)
foreach (src IN LISTS ARGN)
if (IS_ABSOLUTE "${src}")
list (APPEND tmp "${src}")
elseif (EXISTS "${PROJECT_SOURCE_DIR}/src/${src}.in")
configure_file ("${PROJECT_SOURCE_DIR}/src/${src}.in" "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}" @ONLY)
list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}")
else ()
configure_file ("${PROJECT_SOURCE_DIR}/src/${src}" "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}" COPYONLY)
list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}")
endif ()
endforeach ()
set (${out} "${tmp}" PARENT_SCOPE)
endfunction ()
# ----------------------------------------------------------------------------
## Configure source files with .in suffix
function (configure_sources out)
set (tmp)
foreach (src IN LISTS ARGN)
if (src MATCHES ".h$" AND EXISTS "${PROJECT_SOURCE_DIR}/src/${src}.in")
configure_file ("${PROJECT_SOURCE_DIR}/src/${src}.in" "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}" @ONLY)
list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}")
else ()
list (APPEND tmp "${PROJECT_SOURCE_DIR}/src/${src}")
endif ()
endforeach ()
set (${out} "${tmp}" PARENT_SCOPE)
endfunction ()
# ----------------------------------------------------------------------------
## Add usage test
#
# Using PASS_REGULAR_EXPRESSION and FAIL_REGULAR_EXPRESSION would
# do as well, but CMake/CTest does not allow us to specify an
# expected exit status. Moreover, the execute_test.cmake script
# sets environment variables needed by the --fromenv/--tryfromenv tests.
macro (add_gflags_test name expected_rc expected_output unexpected_output cmd)
set (args "--test_tmpdir=${PROJECT_BINARY_DIR}/Testing/Temporary"
"--srcdir=${PROJECT_SOURCE_DIR}/test")
add_test (
NAME ${name}
COMMAND "${CMAKE_COMMAND}" "-DCOMMAND:STRING=$<TARGET_FILE:${cmd}>;${args};${ARGN}"
"-DEXPECTED_RC:STRING=${expected_rc}"
"-DEXPECTED_OUTPUT:STRING=${expected_output}"
"-DUNEXPECTED_OUTPUT:STRING=${unexpected_output}"
-P "${PROJECT_SOURCE_DIR}/cmake/execute_test.cmake"
WORKING_DIRECTORY "${GFLAGS_FLAGFILES_DIR}"
)
endmacro ()
# ------------------------------------------------------------------------------
## Register installed package with CMake
#
# This function adds an entry to the CMake registry for packages with the
# path of the directory where the package configuration file of the installed
# package is located in order to help CMake find the package in a custom
# installation prefix. This differs from CMake's export(PACKAGE) command
# which registers the build directory instead.
function (register_gflags_package CONFIG_DIR)
if (NOT IS_ABSOLUTE "${CONFIG_DIR}")
set (CONFIG_DIR "${CMAKE_INSTALL_PREFIX}/${CONFIG_DIR}")
endif ()
string (MD5 REGISTRY_ENTRY "${CONFIG_DIR}")
if (WIN32)
install (CODE
"execute_process (
COMMAND reg add \"HKCU\\\\Software\\\\Kitware\\\\CMake\\\\Packages\\\\${PACKAGE_NAME}\" /v \"${REGISTRY_ENTRY}\" /d \"${CONFIG_DIR}\" /t REG_SZ /f
RESULT_VARIABLE RT
ERROR_VARIABLE ERR
OUTPUT_QUIET
)
if (RT EQUAL 0)
message (STATUS \"Register: Added HKEY_CURRENT_USER\\\\Software\\\\Kitware\\\\CMake\\\\Packages\\\\${PACKAGE_NAME}\\\\${REGISTRY_ENTRY}\")
else ()
string (STRIP \"\${ERR}\" ERR)
message (STATUS \"Register: Failed to add registry entry: \${ERR}\")
endif ()"
)
elseif (IS_DIRECTORY "$ENV{HOME}")
file (WRITE "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-registry-entry" "${CONFIG_DIR}")
install (
FILES "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-registry-entry"
DESTINATION "$ENV{HOME}/.cmake/packages/${PACKAGE_NAME}"
RENAME "${REGISTRY_ENTRY}"
)
endif ()
endfunction ()

21
cmake/version.cmake.in Normal file
View file

@ -0,0 +1,21 @@
## gflags CMake configuration version file
# -----------------------------------------------------------------------------
# library version
set (PACKAGE_VERSION "@PACKAGE_VERSION@")
# -----------------------------------------------------------------------------
# check compatibility
# Perform compatibility check here using the input CMake variables.
# See example in http://www.cmake.org/Wiki/CMake_2.6_Notes.
set (PACKAGE_VERSION_COMPATIBLE TRUE)
set (PACKAGE_VERSION_UNSUITABLE FALSE)
if ("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "@PACKAGE_VERSION_MAJOR@" AND
"${PACKAGE_FIND_VERSION_MINOR}" EQUAL "@PACKAGE_VERSION_MINOR@")
set (PACKAGE_VERSION_EXACT TRUE)
else ()
set (PACKAGE_VERSION_EXACT FALSE)
endif ()

99
compile
View file

@ -1,99 +0,0 @@
#! /bin/sh
# Wrapper for compilers which do not understand `-c -o'.
# Copyright 1999, 2000 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Usage:
# compile PROGRAM [ARGS]...
# `-o FOO.o' is removed from the args passed to the actual compile.
prog=$1
shift
ofile=
cfile=
args=
while test $# -gt 0; do
case "$1" in
-o)
# configure might choose to run compile as `compile cc -o foo foo.c'.
# So we do something ugly here.
ofile=$2
shift
case "$ofile" in
*.o | *.obj)
;;
*)
args="$args -o $ofile"
ofile=
;;
esac
;;
*.c)
cfile=$1
args="$args $1"
;;
*)
args="$args $1"
;;
esac
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no `-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# `.c' file was seen then we are probably linking. That is also
# ok.
exec "$prog" $args
fi
# Name of file we expect compiler to create.
cofile=`echo $cfile | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
# Create the lock directory.
# Note: use `[/.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo $cofile | sed -e 's|[/.-]|_|g'`.d
while true; do
if mkdir $lockdir > /dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir $lockdir; exit 1" 1 2 15
# Run the compile.
"$prog" $args
status=$?
if test -f "$cofile"; then
mv "$cofile" "$ofile"
fi
rmdir $lockdir
exit $status

1491
config.guess vendored

File diff suppressed because it is too large Load diff

1606
config.sub vendored

File diff suppressed because it is too large Load diff

22219
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -1,67 +0,0 @@
## This is a boilerplate file for Google opensource projects.
## To make it useful, replace <<TEXT>> with actual text for your project.
## Also, look at comments with "## double hashes" to see if any are worth
## uncommenting or modifying.
## Process this file with autoconf to produce configure.
## In general, the safest way to proceed is to run the following:
## % aclocal -I . -I `pwd`/../autoconf && autoheader && autoconf && automake
# make sure we're interpreted by some minimal autoconf
AC_PREREQ(2.57)
AC_INIT(gflags, 0.2, opensource@google.com)
# The argument here is just something that should be in the current directory
# (for sanity checking)
AC_CONFIG_SRCDIR(README)
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(src/config.h)
# Checks for programs.
AC_PROG_CC
AC_PROG_CPP
AC_PROG_CXX
# Uncomment this if you'll be exporting libraries (.so's)
AC_PROG_LIBTOOL
AC_SUBST(LIBTOOL_DEPS)
# Check whether some low-level functions/files are available
AC_HEADER_STDC
# These are tested for by AC_HEADER_STDC, but I check again to set the var
AC_CHECK_HEADER(stdint.h, ac_cv_have_stdint_h=1, ac_cv_have_stdint_h=0)
AC_CHECK_HEADER(sys/types.h, ac_cv_have_systypes_h=1, ac_cv_have_systypes_h=0)
AC_CHECK_HEADER(inttypes.h, ac_cv_have_inttypes_h=1, ac_cv_have_inttypes_h=0)
# These are the types I need. We look for them in either stdint.h,
# sys/types.h, or inttypes.h, all of which are part of the default-includes.
AC_CHECK_TYPE(uint16_t, ac_cv_have_uint16_t=1, ac_cv_have_uint16_t=0)
AC_CHECK_TYPE(u_int16_t, ac_cv_have_u_int16_t=1, ac_cv_have_u_int16_t=0)
AC_CHECK_TYPE(__uint16, ac_cv_have___uint16=1, ac_cv_have___uint16=0)
AX_C___ATTRIBUTE__
ACX_PTHREAD
# Find out what namespace 'normal' STL code lives in, and also what namespace
# the user wants our classes to be defined in
AC_CXX_STL_NAMESPACE
AC_DEFINE_GOOGLE_NAMESPACE(google)
# These are what's needed by gflags.h.in
AC_SUBST(ac_google_start_namespace)
AC_SUBST(ac_google_end_namespace)
AC_SUBST(ac_google_namespace)
AC_SUBST(ac_cv___attribute__)
AC_SUBST(ac_cv_have_stdint_h)
AC_SUBST(ac_cv_have_systypes_h)
AC_SUBST(ac_cv_have_inttypes_h)
AC_SUBST(ac_cv_have_uint16_t)
AC_SUBST(ac_cv_have_u_int16_t)
AC_SUBST(ac_cv_have___uint16)
## Check out ../autoconf/ for other macros you can call to do useful stuff
# Write generated configuration file, and also .h files
AC_CONFIG_FILES([Makefile src/google/gflags.h])
AC_OUTPUT

423
depcomp
View file

@ -1,423 +0,0 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
# Copyright 1999, 2000 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# `libtool' can also be set to `yes' or `no'.
if test -z "$depfile"; then
base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'`
dir=`echo "$object" | sed 's,/.*$,/,'`
if test "$dir" = "$object"; then
dir=
fi
# FIXME: should be _deps on DOS.
depfile="$dir.deps/$base"
fi
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
"$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say).
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the `deleted header file' problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
tr ' ' '
' < "$tmpdepfile" |
## Some versions of gcc put a space before the `:'. On the theory
## that the space means something, we add a space to the output as
## well.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like `#:fec' to the end of the
# dependency line.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr '
' ' ' >> $depfile
echo >> $depfile
# The second pass generates a dummy entry for each header file.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> $depfile
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. This file always lives in the current directory.
# Also, the AIX compiler puts `$object:' at the start of each line;
# $object doesn't have directory information.
stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'`
tmpdepfile="$stripped.u"
outname="$stripped.o"
if test "$libtool" = yes; then
"$@" -Wc,-M
else
"$@" -M
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
if test -f "$tmpdepfile"; then
# Each line is of the form `foo.o: dependent.h'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in `foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1="$dir.libs/$base.lo.d"
tmpdepfile2="$dir.libs/$base.d"
"$@" -Wc,-MD
else
tmpdepfile1="$dir$base.o.d"
tmpdepfile2="$dir$base.d"
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
if test -f "$tmpdepfile1"; then
tmpdepfile="$tmpdepfile1"
else
tmpdepfile="$tmpdepfile2"
fi
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a space and a tab in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the proprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'. We will use -o /dev/null later,
# however we can't do the remplacement now because
# `-o $object' might simply not be used
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
"$@" -o /dev/null $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' '
' < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# X makedepend
shift
cleared=no
for arg in "$@"; do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
-*)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix="`echo $object | sed 's/^.*\././'`"
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
sed '1,2d' "$tmpdepfile" | tr ' ' '
' | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the proprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E |
sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the proprocessed file to stdout, regardless of -o,
# because we must use -o when running libtool.
"$@" || exit $?
IFS=" "
for arg
do
case "$arg" in
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
echo " " >> "$depfile"
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0

View file

4
doc/README.md Normal file
View file

@ -0,0 +1,4 @@
To update the GitHub Pages at http://gflags.github.io/gflags/, use command:
```
git subtree push --prefix=doc/ origin gh-pages
```

115
doc/designstyle.css Normal file
View file

@ -0,0 +1,115 @@
body {
background-color: #ffffff;
color: black;
margin-right: 1in;
margin-left: 1in;
}
h1, h2, h3, h4, h5, h6 {
color: #3366ff;
font-family: sans-serif;
}
@media print {
/* Darker version for printing */
h1, h2, h3, h4, h5, h6 {
color: #000080;
font-family: helvetica, sans-serif;
}
}
h1 {
text-align: center;
font-size: 18pt;
}
h2 {
margin-left: -0.5in;
}
h3 {
margin-left: -0.25in;
}
h4 {
margin-left: -0.125in;
}
hr {
margin-left: -1in;
}
/* Definition lists: definition term bold */
dt {
font-weight: bold;
}
address {
text-align: right;
}
/* Use the <code> tag for bits of code and <var> for variables and objects. */
code,pre,samp,var {
color: #006000;
}
/* Use the <file> tag for file and directory paths and names. */
file {
color: #905050;
font-family: monospace;
}
/* Use the <kbd> tag for stuff the user should type. */
kbd {
color: #600000;
}
div.note p {
float: right;
width: 3in;
margin-right: 0%;
padding: 1px;
border: 2px solid #6060a0;
background-color: #fffff0;
}
UL.nobullets {
list-style-type: none;
list-style-image: none;
margin-left: -1em;
}
/*
body:after {
content: "Google Confidential";
}
*/
/* pretty printing styles. See prettify.js */
.str { color: #080; }
.kwd { color: #008; }
.com { color: #800; }
.typ { color: #606; }
.lit { color: #066; }
.pun { color: #660; }
.pln { color: #000; }
.tag { color: #008; }
.atn { color: #606; }
.atv { color: #080; }
pre.prettyprint { padding: 2px; border: 1px solid #888; }
.embsrc { background: #eee; }
@media print {
.str { color: #060; }
.kwd { color: #006; font-weight: bold; }
.com { color: #600; font-style: italic; }
.typ { color: #404; font-weight: bold; }
.lit { color: #044; }
.pun { color: #440; }
.pln { color: #000; }
.tag { color: #006; font-weight: bold; }
.atn { color: #404; }
.atv { color: #060; }
}
/* Table Column Headers */
.hdr {
color: #006;
font-weight: bold;
background-color: #dddddd; }
.hdr2 {
color: #006;
background-color: #eeeeee; }

View file

@ -2,11 +2,9 @@
<html>
<head>
<title>How To Use Google Commandline Flags</title>
<title>How To Use Gflags (formerly Google Commandline Flags)</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="http://www.google.com/favicon.ico" type="image/x-icon"
rel="shortcut icon">
<link href="designstyle.css" type="text/css" rel="stylesheet">
<style type="text/css">
<!--
@ -18,7 +16,7 @@
color: #000;
font-family: "Times Roman", times, serif;
}
ul.blacklist li {
ul.blacklist li {
color: #000;
font-family: "Times Roman", times, serif;
}
@ -28,7 +26,7 @@
<body>
<h1>How To Use Google Commandline Flags (gflags)</h1>
<h1>How To Use gflags (formerly Google Commandline Flags)</h1>
<small>(as of
<script type=text/javascript>
var lm = new Date(document.lastModified);
@ -37,6 +35,25 @@
</small>
<br>
<blockquote><dl>
<dt> Table of contents </dt>
<dd> <a href="#intro">Introduction</a> </dd>
<dd> <a href="#download">Download and Installation</a> </dd>
<dd> <a href="#cmake">Declare dependency on gflags with CMake</a></dd>
<dd> <a href="#bazel">Declare dependency on gflags with Bazel</a></dd>
<dd> <a href="#define">DEFINE: Defining Flags In Program</A> </dd>
<dd> <a href="#using">Accessing the Flag</A> </dd>
<dd> <a href="#declare">DECLARE: Using the Flag in a Different File</a> </dd>
<dd> <a href="#validate">RegisterFlagValidator: Sanity-checking Flag Values</a> </dd>
<dd> <a href="#together">Putting It Together: How to Set Up Flags</a> </dd>
<dd> <a href="#commandline">Setting Flags on the Command Line</a> </dd>
<dd> <a href="#default">Changing the Default Flag Value</a> </dd>
<dd> <a href="#special">Special Flags</a> </dd>
<dd> <a href="#api">The API</a> </dd>
<dd> <a href="#misc">Miscellaneous Notes</a> </dd>
<dd> <a href="#issues">Issues and Feature Requests</a> </dd>
<dd> <br/> </dd>
</dl></blockquote>
<h2> <A NAME=intro>Introduction, and Comparison to Other Commandline
Flags Libraries</A> </h2>
@ -57,13 +74,14 @@ string (in particular, a filename) as an argument. Users can use a
library to help parse the commandline and store the flags in some data
structure.</p>
<p>Google's commandline flags library differs from other libraries,
<p>Gflags, the commandline flags library used within Google,
differs from other libraries,
such as <code>getopt()</code>, in that flag definitions can be
scattered around the source code, and not just listed in one place
such as <code>main()</code>. In practice, this means that a single
source-code file will define and use flags that are meaningful to that
file. Any application that links in that file will get the flags, and
the google commandline flags library will automatically handle that
the gflags library will automatically handle that
flag appropriately.</p>
<p>There's significant gain in flexibility, and ease of code reuse,
@ -76,16 +94,97 @@ library. It's a C++ library, so examples are in C++. However, there
is a Python port with the same functionality, and this discussion
translates directly to Python.</p>
<h2> <A NAME=download>Download and Installation</A> </h2>
<p>The gflags library can be downloaded from <A href="https://github.com/gflags/gflags">GitHub</A>.
You can clone the project using the command:</p>
<pre>
git clone https://github.com/gflags/gflags.git
</pre>
<p>Build and installation instructions are provided in the
<A href="https://github.com/gflags/gflags/blob/master/INSTALL.md">INSTALL</A> file.
The installation of the gflags package includes configuration files for popular build systems
such as <A href="https://www.freedesktop.org/wiki/Software/pkg-config/">pkg-config</A>,
<A href="#cmake">CMake</A>, and <A href="#bazel">Bazel</A>.</p>
<h2> <A name=cmake>Declare dependency on gflags with CMake</A></h2>
<p>Using gflags within a project which uses <A href="http://www.cmake.org">CMake</A> for its build system is easy.
You can either require an external installation of the gflags package and find it using CMake's find_package
command, or include the gflags project as subtree or submodule within your project's source tree and add the directory
using CMake's add_subdirectory command.
<p>To use an external gflags installation, add the following CMake code to your <code>CMakeLists.txt</code> file.</p>
<p>Find gflags installation. The <code>gflags_DIR</code> variable must be set to the &lt;prefix&gt;/lib/cmake/gflags directory
containing the gflags-config.cmake file if &lt;prefix&gt; is a non-standard location. Otherwise, CMake should find
the gflags installation automatically.</p>
<pre>
find_package(gflags REQUIRED)
</pre>
<p>To request a particular imported gflags library target to link against, use the <code>COMPONENTS</code> option of
the find_package command. For example, to force the use of the single-threaded static library, use the command</p>
<pre>
find_package(gflags COMPONENTS nothreads_static)
</pre>
<p>Note that this will raise a fatal error when the installed gflags package does not contain the requested library.
It is therefore recommended to only specify the particular component to look for if a specific library must be used.
Otherwise, the gflags-config.cmake module will choose a suitable and available library for you. By default, the
multi-threaded gflags library with shared linkage is chosen if available.</p>
<p>When the source tree of the gflags project is included as subtree or submodule in the "gflags" directory of your project,
replace the above find_package command by <code>add_subdirectory(gflags)</code>. See the top of the <code>gflags/CMakeLists.txt</code>
file for a listing of available CMake variables that can be set before this command to configure the build of the
gflags library. The default build settings are the build of a single-threaded static library which does not require
any installation of the gflags subproject products.</p>
<p>Finally, add your executable build target which uses gflags to parse the command arguments with dependency on the
imported gflags library target:</p>
<pre>
add_executable(foo main.cc)
target_link_libraries(foo gflags::gflags)
</pre>
<h2> <A name=bazel>Declare dependency on gflags with Bazel</A></h2>
<p>To use gflags within a project which uses <A href="https://bazel.build/">Bazel</A> as build tool,
add the following lines to your <code>WORKSPACE</code> file
(see also Bazel documentation of <A href="https://www.bazel.io/versions/master/docs/be/workspace.html#git_repository">git_repository</A>):
<pre>
git_repository(
name = "com_github_gflags_gflags",
remote = "https://github.com/gflags/gflags.git",
tag = "v2.2.2"
)
</pre>
<p>You can then add <code>@com_github_gflags_gflags//:gflags</code> to the <code>deps</code> section of a
<code>cc_binary</code> or <code>cc_library</code> rule, and <code>#include "gflags/gflags.h"</code> to
include it in your source code. This uses the shared gflags library with multi-threading enabled.
In order to use the single-threaded shared gflags library, use the dependency
<code>@com_github_gflags_gflags//:gflags_nothreads</code> instead.</p>
<p>For example, see the following <code>BUILD</code> rule of the gflags/example project:</p>
<pre>
cc_binary(
name = "foo",
srcs = ["main.cc"],
deps = ["@com_github_gflags_gflags//:gflags"],
)
</pre>
<h2> <A name=define>DEFINE: Defining Flags In Program</A> </h2>
<p> Defining a flag is easy: just use the appropriate macro for the
type you want the flag to be, as defined at the bottom of
<code>base/commandlineflags.h</code>. Here's an example file,
<code>gflags/gflags.h</code>. Here's an example file,
<code>foo.cc</code>:</p>
<pre>
#include "base/commandlineflags.h"
#include &lt;gflags/gflags.h&gt;
DEFINE_bool(big_menu, true, "Include 'advanced' options in the menu listing");
DEFINE_string(languages, "english,french,german",
@ -107,7 +206,7 @@ types supported:</p>
flag in our example is a list of strings, but is defined of type
"string", not "list_of_string" or similar. This is by design. We'd
rather use only simple types for the flags, and allow for complex,
arbitrary parsing routines to parse them, then to try to put the logic
arbitrary parsing routines to parse them, than to try to put the logic
inside the flags library proper.</p>
<p>All DEFINE macros take the same three arguments: the name of the
@ -122,6 +221,15 @@ HREF="#declare">DECLARE</A> it in the others. Even better, DEFINE it
in <code>foo.cc</code> and DECLARE it in <code>foo.h</code>; then
everyone who <code>#includes foo.h</code> can use the flag.</p>
<p>
Defining flags in libraries rather than in main() is powerful, but
does have some costs. One is that a library might not have a good
default value for its flags, for example if the flag holds a
filename that might not exist in some environments. To mitigate such problems,
you can use <a href="#validate">flag validators</a> to ensure prompt
notification (in the form of a crash) of an invalid flag value.
</p>
<p>Note that while most functions in this library are defined in the
<code>google</code> namespace, <code>DEFINE_foo</code> (and
<code>DECLARE_foo</code>, <A HREF="#declare">below</A>), should always
@ -131,7 +239,7 @@ be in the global namespace.</p>
<h2> <A name=using>Accessing the Flag</A> </h2>
<p>All defined flags are available to the program as just a normal
variable, with the prefix <code>FLAGS_</code> appended. In the above
variable, with the prefix <code>FLAGS_</code> prepended. In the above
example, the macros define two variables, <code>FLAGS_big_menu</code>
(a bool), and <code>FLAGS_languages</code> (a C++ string).</p>
@ -145,7 +253,7 @@ variable:</p>
</pre>
<p>You can also get and set flag values via special functions in
<code>commandlineflags.h</code>. That's a rarer use case, though.</p>
<code>gflags.h</code>. That's a rarer use case, though.</p>
<h2> <A name=declare>DECLARE: Using the Flag in a Different File</A> </h2>
@ -159,7 +267,7 @@ use a flag that's defined in another file. For instance, if I were
writing <code>bar.cc</code> but wanted to access the big_menu, flag, I
would put this near the top of <code>bar.cc</code>:</p>
<pre>
DEFINE_bool(big_menu);
DECLARE_bool(big_menu);
</pre>
<p>This is functionally equivalent to saying <code>extern
@ -173,15 +281,58 @@ recommend the following guideline:</p>
<blockquote>
If you DEFINE a flag in <code>foo.cc</code>, either don't DECLARE it
at all, or only DECLARE it in <code>foo.h</code>.
at all, only DECLARE it in tightly related tests, or only DECLARE
it in <code>foo.h</code>.
</blockquote>
<p>You should go the do-not-DECLARE route when the flag is only needed
by <code>foo.cc</code>, and not in any other file. If the flag does
span multiple files, DECLARE it in the associated <code>.h</code>
file, and make others <code>#include</code> that <code>.h</code> file
if they want to access the flag. The <code>#include</code> will make
explicit the dependency between the two files.</p>
by <code>foo.cc</code>, and not in any other file. If you want to
modify the value of the flag in the related test file to see if it is
functioning as expected, DECLARE it in the <code>foo_test.cc</code>
file.
<p>If the flag does span multiple files, DECLARE it in the associated
<code>.h</code> file, and make others <code>#include</code> that
<code>.h</code> file if they want to access the flag. The
<code>#include</code> will make explicit the dependency between the
two files. This causes the flag to be a global variable.</p>
<h2> <A name=validate>RegisterFlagValidator: Sanity-checking Flag Values</A> </h2>
<p>After DEFINE-ing a flag, you may optionally register a validator
function with the flag. If you do this, after the flag is parsed from
the commandline, and whenever its value is changed via a call to
<code>SetCommandLineOption()</code>, the validator function is called
with the new value as an argument. The validator function should
return 'true' if the flag value is valid, and false otherwise.
If the function returns false for the new setting of the
flag, the flag will retain its current value. If it returns false for the
default value, ParseCommandLineFlags will die.
<p>Here is an example use of this functionality:</p>
<pre>
static bool ValidatePort(const char* flagname, int32 value) {
if (value > 0 && value < 32768) // value is ok
return true;
printf("Invalid value for --%s: %d\n", flagname, (int)value);
return false;
}
DEFINE_int32(port, 0, "What port to listen on");
DEFINE_validator(port, &ValidatePort);
</pre>
<p>By doing the registration at global initialization time (right
after the DEFINE_int32), we ensure that the registration happens before
the commandline is parsed at the beginning of <code>main()</code>.</p>
<p>The above used <code>DEFINE_validator</code> macro calls the
<code>RegisterFlagValidator()</code> function which returns true if the
registration is successful. It returns false if the registration fails
because a) the first argument does not refer to a commandline flag, or
b) a different validator has already been registered for this flag.
The return value is available as global static boolean variable named
<code>&lt;flag&gt;_validator_registered</code>.</p>
<h2> <A name=together>Putting It Together: How to Set Up Flags</A> </h2>
@ -194,7 +345,7 @@ the getopt library, but has much less overhead to use. In fact, it's
just a single function call:</p>
<pre>
google::ParseCommandLineFlags(&argc, &argv, true);
gflags::ParseCommandLineFlags(&argc, &argv, true);
</pre>
<p>Usually, this code is at the beginning of <code>main()</code>.
@ -250,14 +401,12 @@ specify the "languages" flag:</p>
<li> <code>app_containing_foo -languages "chinese,japanese,korean"</code>
</ul>
<p>For boolean flags, there are even more possibilities:</p>
<p>For boolean flags, the possibilities are slightly different:</p>
<ul>
<li> <code>app_containing_foo --big_menu</code>
<li> <code>app_containing_foo --nobig_menu</code>
<li> <code>app_containing_foo --big_menu=true</code>
<li> <code>app_containing_foo --big_menu=false</code>
<li> <code>app_containing_foo --big_menu true</code>
<li> <code>app_containing_foo --big_menu false</code>
</ul>
<p>(as well as the single-dash variant on all of these).</p>
@ -279,16 +428,40 @@ HREF="#special"><code>--undefok</code></A> to suppress the error.</p>
processing. So in <code>foo -f1 1 -- -f2 2</code>, <code>f1</code> is
considered a flag, but <code>-f2</code> is not.</p>
<p>If a flag is specified more than once, only the last specification
is used; the others are ignored.</p>
<p>Note that flags do not have single-letter synonyms, like they do in
the getopt library, nor do we allowing "combining" flags behind a
the getopt library, nor do we allow "combining" flags behind a
single dash, as in <code>ls -la</code>.</p>
<h2> <A name="special">Special Flags</code> </h2>
<h2> <A name=default>Changing the Default Flag Value</A> </h2>
<p>Sometimes a flag is defined in a library, and you want to change
its default value in one application but not others. It's simple to
do this: just assign a new value to the flag in <code>main()</code>,
before calling <code>ParseCommandLineFlags()</code>:</p>
<pre>
DECLARE_bool(lib_verbose); // mylib has a lib_verbose flag, default is false
int main(int argc, char** argv) {
FLAGS_lib_verbose = true; // in my app, I want a verbose lib by default
ParseCommandLineFlags(...);
}
</pre>
<p>For this application, users can still set the flag value on the
commandline, but if they do not, the flag's value will default to
true.</p>
<h2> <A name="special">Special Flags</a> </h2>
<p>There are a few flags defined by the commandlineflags module
itself, and are available to all applications. These fall into three
categories. First are the 'reporting' flags that, when found, cause
itself, and are available to all applications that use
commandlineflags. These fall into
three categories. First are the 'reporting' flags that, when found, cause
the application to print some information about itself and exit.</p>
<table><tr valign=top>
@ -296,12 +469,13 @@ the application to print some information about itself and exit.</p>
<td>shows all flags from all files, sorted by file and then by name;
shows the flagname, its default value, and its help string</td>
</tr><tr valign=top>
<td><code>--helpfull</code></td>
<td><code>--helpful</code></td>
<td>same as -help, but unambiguously asks for all flags
(in case -help changes in the future)</td>
</tr><tr valign=top>
<td><code>--helpshort</code></td>
<td>shows only flags for the file that includes <code>main()</code></td>
<td>shows only flags for the file with the same name as the executable
(usually the one containing <code>main()</code>)</td>
</tr><tr valign=top>
<td><code>--helpxml</code></td>
<td>like --help, but output is in xml for easier parsing</td>
@ -368,7 +542,7 @@ the application.</p>
<p>Note it is still an error to say <code>--tryfromenv=foo</code> if
<code>foo</code> is not DEFINED somewhere in the application.</p>
<h3> <code>--flagfile</code> </h3>
<h3 id="flagfiles"> <code>--flagfile</code> </h3>
<p><code>--flagfile=f</code> tells the commandlineflags module to read
the file <code>f</code>, and to run all the flag-assignments found in
@ -376,7 +550,7 @@ that file as if these flags had been specified on the commandline.</p>
<p>In its simplest form, <code>f</code> should just be a list of flag
assignments, one per line. Unlike on the commandline, the equals sign
separating a flagname from its argument is <i>required</i> for
separating a flagname from its argument is <i>required</i> for
flagfiles. An example flagfile, <code>/tmp/myflags</code>:</p>
<pre>
--nobig_menus
@ -419,7 +593,7 @@ and then processing continues with remaining flags from the command
line.</p>
<h2> <A name="api">The API</code> </h2>
<h2> <A name="api">The API</a> </h2>
<p>In addition to accessing <code>FLAGS_foo</code> directly, it is
possible to access the flags programmatically, through an API. It is
@ -431,12 +605,29 @@ access parts of <code>argv</code> outside main, including the program
name (<code>argv[0]</code>).</p>
<p>For more information about these routines, and other useful helper
methods such as <code>google::SetUsageMessage</code>, see
<code>gflags.h</code>.</p>
methods such as <code>gflags::SetUsageMessage()</code> and
<code>gflags::SetVersionString</code>, see <code>gflags.h</code>.</p>
<h2> <A name="misc">Miscellaneous Notes</code> </h2>
<p>If your application has code like this:</p>
<pre>
#define STRIP_FLAG_HELP 1 // this must go before the #include!
#include &lt;gflags/gflags.h&gt;
</pre>
<p>we will remove the help messages from the compiled source. This can
reduce the size of the resulting binary somewhat, and may also be
useful for security reasons.</p>
<h2> <A name="issues">Issues and Feature Requests</code> </h2>
<p>Please report any issues or ideas for additional features on <A href="https://github.com/gflags/gflags/issues">GitHub</A>.
We would also like to encourage <A href="https://github.com/gflags/gflags/pulls">pull requests</A> for bug fixes and implementations of new features.</p>
<hr>
<address>
Craig Silverstein<br>
Craig Silverstein, Andreas Schuh<br>
<script type=text/javascript>
var lm = new Date(document.lastModified);
document.write(lm.toDateString());

View file

@ -1,251 +0,0 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
:
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
chmodcmd=""
else
instcmd=$mkdirprog
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f "$src" ] || [ -d "$src" ]
then
:
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
:
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
:
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
:
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
:
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

6299
ltmain.sh

File diff suppressed because it is too large Load diff

336
missing
View file

@ -1,336 +0,0 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
run=:
# In the cases where this matters, `missing' is being run in the
# srcdir already.
if test -f configure.ac; then
configure_ac=configure.ac
else
configure_ac=configure.in
fi
case "$1" in
--run)
# Try to run requested program, and just exit if it succeeds.
run=
shift
"$@" && exit 0
;;
esac
# If it does not exist, or fails to run (possibly an outdated version),
# try to emulate it.
case "$1" in
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
--run try to run the given command, and emulate it if it fails
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
help2man touch the output file
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
tar try tar, gnutar, gtar, then tar without non-portable flags
yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing 0.4 - GNU automake"
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
aclocal*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`${configure_ac}'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acconfig.h' or \`${configure_ac}'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
test -z "$files" && files="config.h"
touch_files=
for f in $files; do
case "$f" in
*:*) touch_files="$touch_files "`echo "$f" |
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
*) touch_files="$touch_files $f.in";;
esac
done
touch $touch_files
;;
automake*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
while read f; do touch "$f"; done
;;
autom4te)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them.
You can get \`$1Help2man' as part of \`Autoconf' from any GNU
archive site."
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo "#! /bin/sh"
echo "# Created by GNU Automake missing as a replacement of"
echo "# $ $@"
echo "exit 0"
chmod +x $file
exit 1
fi
;;
bison|yacc)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if [ ! -f y.tab.h ]; then
echo >y.tab.h
fi
if [ ! -f y.tab.c ]; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
lex|flex)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if [ ! -f lex.yy.c ]; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
help2man)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a dependency of a manual page. You may need the
\`Help2man' package in order for those modifications to take
effect. You can get \`Help2man' from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
fi
if [ -f "$file" ]; then
touch $file
else
test -z "$file" || exec >$file
echo ".ab help2man is required to generate this page"
exit 1
fi
;;
makeinfo)
if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
# We have makeinfo, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
fi
touch $file
;;
tar)
shift
if test -n "$run"; then
echo 1>&2 "ERROR: \`tar' requires --run"
exit 1
fi
# We have already tried tar in the generic part.
# Look for gnutar/gtar before invocation to avoid ugly error
# messages.
if (gnutar --version > /dev/null 2>&1); then
gnutar "$@" && exit 0
fi
if (gtar --version > /dev/null 2>&1); then
gtar "$@" && exit 0
fi
firstarg="$1"
if shift; then
case "$firstarg" in
*o*)
firstarg=`echo "$firstarg" | sed s/o//`
tar "$firstarg" "$@" && exit 0
;;
esac
case "$firstarg" in
*h*)
firstarg=`echo "$firstarg" | sed s/h//`
tar "$firstarg" "$@" && exit 0
;;
esac
fi
echo 1>&2 "\
WARNING: I can't seem to be able to run \`tar' with the given arguments.
You may want to install GNU tar or Free paxutils, or check the
command line arguments."
exit 1
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequirements for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0

View file

@ -1,99 +0,0 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
errstatus=0
dirmode=""
usage="\
Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
# process command line arguments
while test $# -gt 0 ; do
case "${1}" in
-h | --help | --h* ) # -h for help
echo "${usage}" 1>&2; exit 0 ;;
-m ) # -m PERM arg
shift
test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; }
dirmode="${1}"
shift ;;
-- ) shift; break ;; # stop option processing
-* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option
* ) break ;; # first non-opt arg
esac
done
for file
do
if test -d "$file"; then
shift
else
break
fi
done
case $# in
0) exit 0 ;;
esac
case $dirmode in
'')
if mkdir -p -- . 2>/dev/null; then
echo "mkdir -p -- $*"
exec mkdir -p -- "$@"
fi ;;
*)
if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
echo "mkdir -m $dirmode -p -- $*"
exec mkdir -m "$dirmode" -p -- "$@"
fi ;;
esac
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp"
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
else
if test ! -z "$dirmode"; then
echo "chmod $dirmode $pathcomp"
lasterr=""
chmod "$dirmode" "$pathcomp" || lasterr=$?
if test ! -z "$lasterr"; then
errstatus=$lasterr
fi
fi
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# Local Variables:
# mode: shell-script
# sh-indentation: 3
# End:
# mkinstalldirs ends here

View file

@ -1,70 +0,0 @@
#!/bin/bash -e
# This takes one commandline argument, the name of the package. If no
# name is given, then we'll end up just using the name associated with
# an arbitrary .tar.gz file in the rootdir. That's fine: there's probably
# only one.
#
# Run this from the 'packages' directory, just under rootdir
## Set LIB to lib if exporting a library, empty-string else
LIB=
#LIB=lib
PACKAGE="$1"
# We can only build Debian packages, if the Debian build tools are installed
if [ \! -x /usr/bin/debuild ]; then
echo "Cannot find /usr/bin/debuild. Not building Debian packages." 1>&2
exit 0
fi
# Double-check we're in the packages directory, just under rootdir
if [ \! -r ../Makefile -a \! -r ../INSTALL ]; then
echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2
echo "Also, you must run \"make dist\" before running this script." 1>&2
exit 0
fi
# Find the top directory for this package
topdir="${PWD%/*}"
# Find the tar archive built by "make dist"
archive="$(basename "$(ls -1 ${topdir}/$PACKAGE*.tar.gz | tail -n 1)" .tar.gz)"
if [ -z "${archive}" ]; then
echo "Cannot find ../$PACKAGE*.tar.gz. Run \"make dist\" first." 1>&2
exit 0
fi
# Create a pristine directory for building the Debian package files
trap 'rm -rf '`pwd`/tmp'; exit $?' EXIT SIGHUP SIGINT SIGTERM
rm -rf tmp
mkdir -p tmp
cd tmp
# Debian has very specific requirements about the naming of build
# directories, and tar archives. It also wants to write all generated
# packages to the parent of the source directory. We accommodate these
# requirements by building directly from the tar file.
ln -s "${topdir}/${archive}.tar.gz" "${LIB}${archive}.orig.tar.gz"
tar zfx "${LIB}${archive}.orig.tar.gz"
[ -n "${LIB}" ] && mv "${archive}" "${LIB}${archive}"
cd "${LIB}${archive}"
# This is one of those 'specific requirements': where the deb control files live
ln -s "packages/deb" "debian"
# Now, we can call Debian's standard build tool
debuild -uc -us
cd ../.. # get back to the original top-level dir
# We'll put the result in a subdirectory that's named after the OS version
# we've made this .deb file for.
destdir="debian-$(cat /etc/debian_version 2>/dev/null || echo UNKNOWN)"
rm -rf "$destdir"
mkdir -p "$destdir"
mv $(find tmp -mindepth 1 -maxdepth 1 -type f) "$destdir"
echo
echo "The Debian package files are located in $PWD/$destdir"

View file

@ -1,7 +0,0 @@
The list of files here isn't complete. For a step-by-step guide on
how to set this package up correctly, check out
http://www.debian.org/doc/maint-guide/
Most of the files that are in this directory are boilerplate.
However, you may need to change the list of binary-arch dependencies
in 'rules'.

View file

@ -1,6 +0,0 @@
google-gflags (0.1-1) unstable; urgency=low
* Initial release.
-- Google Inc. <opensource@google.com> Wed, 13 Dec 2006 11:33:30 -0800

View file

@ -1 +0,0 @@
4

View file

@ -1,25 +0,0 @@
Source: google-gflags
Priority: optional
Maintainer: Google Inc. <opensource@google.com>
Build-Depends: debhelper (>= 4.0.0), binutils
Standards-Version: 3.6.1
Package: libgoogle-gflags-dev
Section: libdevel
Architecture: any
Depends: libgoogle-gflags0 (= ${Source-Version})
Description: a library that implements commandline flags
processing. As such it's a replacement for getopt(). It has increased
flexibility, including built-in support for C++ types like string, and
the ability to define flags in the source file in which they're used.
The devel package contains static and debug libraries and header files
for developing applications that use the google-gflags package.
Package: libgoogle-gflags0
Section: libs
Architecture: any
Depends: ${shlibs:Depends}
Description: a library that implements commandline flags
processing. As such it's a replacement for getopt(). It has increased
flexibility, including built-in support for C++ types like string, and
the ability to define flags in the source file in which they're used.

View file

@ -1,35 +0,0 @@
This package was debianized by Google Inc. <opensource@google.com> on
13 December 2006.
It was downloaded from http://code.google.com/
Upstream Author: opensource@google.com
Copyright (c) 2006, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,7 +0,0 @@
AUTHORS
COPYING
ChangeLog
INSTALL
NEWS
README
doc/gflags.html

View file

@ -1,117 +0,0 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
CFLAGS = -Wall -g
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
CFLAGS += -O0
else
CFLAGS += -O2
endif
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
INSTALL_PROGRAM += -s
endif
# shared library versions, option 1
#version=2.0.5
#major=2
# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so
version=`ls src/.libs/lib*.so.* | \
awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
major=`ls src/.libs/lib*.so.* | \
awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
config.status: configure
dh_testdir
# Add here commands to configure the package.
CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info
build: build-stamp
build-stamp: config.status
dh_testdir
# Add here commands to compile the package.
$(MAKE)
touch build-stamp
clean:
dh_testdir
dh_testroot
rm -f build-stamp
# Add here commands to clean up after the build process.
-$(MAKE) distclean
ifneq "$(wildcard /usr/share/misc/config.sub)" ""
cp -f /usr/share/misc/config.sub config.sub
endif
ifneq "$(wildcard /usr/share/misc/config.guess)" ""
cp -f /usr/share/misc/config.guess config.guess
endif
dh_clean
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/tmp
$(MAKE) install DESTDIR=$(CURDIR)/debian/tmp
# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
dh_installchangelogs ChangeLog
dh_installdocs
dh_installexamples
dh_install --sourcedir=debian/tmp
# dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_python
dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install

View file

@ -1,75 +0,0 @@
#!/bin/sh -e
# Run this from the 'packages' directory, just under rootdir
# We can only build rpm packages, if the rpm build tools are installed
if [ \! -x /usr/bin/rpmbuild ]
then
echo "Cannot find /usr/bin/rpmbuild. Not building an rpm." 1>&2
exit 0
fi
# Check the commandline flags
PACKAGE="$1"
VERSION="$2"
fullname="${PACKAGE}-${VERSION}"
archive=../$fullname.tar.gz
if [ -z "$1" -o -z "$2" ]
then
echo "Usage: $0 <package name> <package version>" 1>&2
exit 0
fi
# Double-check we're in the packages directory, just under rootdir
if [ \! -r ../Makefile -a \! -r ../INSTALL ]
then
echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2
echo "Also, you must run \"make dist\" before running this script." 1>&2
exit 0
fi
if [ \! -r "$archive" ]
then
echo "Cannot find $archive. Run \"make dist\" first." 1>&2
exit 0
fi
# Create the directory where the input lives, and where the output should live
RPM_SOURCE_DIR="/tmp/rpmsource-$fullname"
RPM_BUILD_DIR="/tmp/rpmbuild-$fullname"
trap 'rm -rf $RPM_SOURCE_DIR $RPM_BUILD_DIR; exit $?' EXIT SIGHUP SIGINT SIGTERM
rm -rf "$RPM_SOURCE_DIR" "$RPM_BUILD_DIR"
mkdir "$RPM_SOURCE_DIR"
mkdir "$RPM_BUILD_DIR"
cp "$archive" "$RPM_SOURCE_DIR"
rpmbuild -bb rpm/rpm.spec \
--define "NAME $PACKAGE" \
--define "VERSION $VERSION" \
--define "_sourcedir $RPM_SOURCE_DIR" \
--define "_builddir $RPM_BUILD_DIR" \
--define "_rpmdir $RPM_SOURCE_DIR"
# We put the output in a directory based on what system we've built for
destdir=rpm-unknown
if [ -r /etc/issue ]
then
grep "Red Hat.*release 7" /etc/issue >/dev/null 2>&1 && destdir=rh7
grep "Red Hat.*release 8" /etc/issue >/dev/null 2>&1 && destdir=rh8
grep "Red Hat.*release 9" /etc/issue >/dev/null 2>&1 && destdir=rh9
if grep Fedora /etc/issue >/dev/null; then
destdir=fc`grep Fedora /etc/issue | cut -d' ' -f 4`;
fi
fi
rm -rf "$destdir"
mkdir -p "$destdir"
# We want to get not only the main package but devel etc, hence the middle *
mv "$RPM_SOURCE_DIR"/*/"${PACKAGE}"-*"${VERSION}"*.rpm "$destdir"
echo
echo "The rpm package file(s) are located in $PWD/$destdir"

View file

@ -1,66 +0,0 @@
%define ver %VERSION
%define RELEASE 1
%define rel %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE}
%define prefix /usr
Name: %NAME
Summary: A commandline flags library that allows for distributed flags
Version: %ver
Release: %rel
Group: Development/Libraries
URL: http://code.google.com/p/google-gflags
License: BSD
Vendor: Google
Packager: Google Inc. <opensource@google.com>
Source: http://google-gflags.googlecode.com/files/%{NAME}-%{PACKAGE_VERSION}.tar.gz
Distribution: Redhat 7 and above.
Buildroot: %{_tmppath}/%{name}-root
Prefix: %prefix
%description
The %name package contains a library that implements commandline flags
processing. As such it's a replacement for getopt(). It has increased
flexibility, including built-in support for C++ types like string, and
the ability to define flags in the source file in which they're used.
%package devel
Summary: A commandline flags library that allows for distributed flags
Group: Development/Libraries
%description devel
The %name-devel package contains static and debug libraries and header
files for developing applications that use the %name package.
%changelog
* Tue Dec 13 2006 <opensource@google.com>
- First draft
%prep
%setup
%build
./configure
make prefix=%prefix
%install
rm -rf $RPM_BUILD_ROOT
make prefix=$RPM_BUILD_ROOT%{prefix} install
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%doc AUTHORS COPYING ChangeLog INSTALL NEWS README doc/gflags.html
%{prefix}/lib/libgflags.so.0
%{prefix}/lib/libgflags.so.0.0.0
%files devel
%defattr(-,root,root)
%{prefix}/include/google
%{prefix}/lib/libgflags.a
%{prefix}/lib/libgflags.la
%{prefix}/lib/libgflags.so

File diff suppressed because it is too large Load diff

View file

@ -1,548 +0,0 @@
#!/usr/bin/env python
#
# Copyright (c) 2007, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""gflags2man runs a Google flags base program and generates a man page.
Run the program, parse the output, and then format that into a man
page.
Usage:
gflags2man <program> [program] ...
"""
# TODO(csilvers): work with windows paths (\) as well as unix (/)
# This may seem a bit of an end run, but it: doesn't bloat flags, can
# support python/java/C++, supports older executables, and can be
# extended to other document formats.
# Inspired by help2man.
__author__ = 'Dan Christian'
import os
import re
import sys
import stat
import time
import subprocess
import gflags
_VERSION = '0.1'
def _GetDefaultDestDir():
home = os.environ.get('HOME', '')
homeman = os.path.join(home, 'man', 'man1')
if home and os.path.exists(homeman):
return homeman
else:
return os.environ.get('TMPDIR', '/tmp')
FLAGS = gflags.FLAGS
gflags.DEFINE_string('dest_dir', _GetDefaultDestDir(),
'Directory to write resulting manpage to.'
' Specify \'-\' for stdout')
gflags.DEFINE_string('help_flag', '--help',
'Option to pass to target program in to get help')
gflags.DEFINE_integer('v', 0, 'verbosity level to use for output')
_MIN_VALID_USAGE_MSG = 9 # if fewer lines than this, help is suspect
class Logging:
"""A super-simple logging class"""
def error(self, msg): print >>sys.stderr, "ERROR: ", msg
def warn(self, msg): print >>sys.stderr, "WARNING: ", msg
def info(self, msg): print msg
def debug(self, msg): self.vlog(1, msg)
def vlog(self, level, msg):
if FLAGS.v >= level: print msg
logging = Logging()
def GetRealPath(filename):
"""Given an executable filename, find in the PATH or find absolute path.
Args:
filename An executable filename (string)
Returns:
Absolute version of filename.
None if filename could not be found locally, absolutely, or in PATH
"""
if os.path.isabs(filename): # already absolute
return filename
if filename.startswith('./') or filename.startswith('../'): # relative
return os.path.abspath(filename)
path = os.getenv('PATH', '')
for directory in path.split(':'):
tryname = os.path.join(directory, filename)
if os.path.exists(tryname):
if not os.path.isabs(directory): # relative directory
return os.path.abspath(tryname)
return tryname
if os.path.exists(filename):
return os.path.abspath(filename)
return None # could not determine
class Flag(object):
"""The information about a single flag."""
def __init__(self, flag_desc, help):
"""Create the flag object.
Args:
flag_desc The command line forms this could take. (string)
help The help text (string)
"""
self.desc = flag_desc # the command line forms
self.help = help # the help text
self.default = '' # default value
self.tips = '' # parsing/syntax tips
class ProgramInfo(object):
"""All the information gleaned from running a program with --help."""
# Match a module block start, for python scripts --help
# "goopy.logging:"
module_py_re = re.compile(r'(\S.+):$')
# match the start of a flag listing
# " -v,--verbosity: Logging verbosity"
flag_py_re = re.compile(r'\s+(-\S+):\s+(.*)$')
# " (default: '0')"
flag_default_py_re = re.compile(r'\s+\(default:\s+\'(.*)\'\)$')
# " (an integer)"
flag_tips_py_re = re.compile(r'\s+\((.*)\)$')
# Match a module block start, for c++ programs --help
# "google/base/commandlineflags"
module_c_re = re.compile(r'\s+Flags from (\S.+):$')
# match the start of a flag listing
# " -v,--verbosity: Logging verbosity"
flag_c_re = re.compile(r'\s+(-\S+)\s+(.*)$')
# Match a module block start, for java programs --help
# "com.google.common.flags"
module_java_re = re.compile(r'\s+Flags for (\S.+):$')
# match the start of a flag listing
# " -v,--verbosity: Logging verbosity"
flag_java_re = re.compile(r'\s+(-\S+)\s+(.*)$')
def __init__(self, executable):
"""Create object with executable.
Args:
executable Program to execute (string)
"""
self.long_name = executable
self.name = os.path.basename(executable) # name
# Get name without extension (PAR files)
(self.short_name, self.ext) = os.path.splitext(self.name)
self.executable = GetRealPath(executable) # name of the program
self.output = [] # output from the program. List of lines.
self.desc = [] # top level description. List of lines
self.modules = {} # { section_name(string), [ flags ] }
self.module_list = [] # list of module names in their original order
self.date = time.localtime(time.time()) # default date info
def Run(self):
"""Run it and collect output.
Returns:
1 (true) If everything went well.
0 (false) If there were problems.
"""
if not self.executable:
logging.error('Could not locate "%s"' % self.long_name)
return 0
finfo = os.stat(self.executable)
self.date = time.localtime(finfo[stat.ST_MTIME])
logging.info('Running: %s %s </dev/null 2>&1'
% (self.executable, FLAGS.help_flag))
# --help output is often routed to stderr, so we re-direct that to
# stdout. Re-direct stdin to /dev/null to encourage programs that
# don't understand --help to exit.
try:
runstate = subprocess.Popen(
[self.executable, FLAGS.help_flag],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
stdin=open('/dev/null', 'r'))
except OSError, msg:
logging.error('Error executing "%s": %s' % (self.name, msg))
return 0
# read output progressively so the pipe doesn't fill up (fileutil).
self.output = runstate.stdout.readlines()
status = runstate.wait()
logging.debug('Program exited with %s' % status)
output = runstate.communicate()[0]
if output:
self.output = output.splitlines()
if len(self.output) < _MIN_VALID_USAGE_MSG:
logging.error(
'Error: "%s %s" returned %d and only %d lines: %s'
% (self.name, FLAGS.help_flag, status, len(self.output), output))
return 0
return 1
def Parse(self):
"""Parse program output."""
(start_line, lang) = self.ParseDesc()
if start_line < 0:
return
if 'python' == lang:
self.ParsePythonFlags(start_line)
elif 'c' == lang:
self.ParseCFlags(start_line)
elif 'java' == lang:
self.ParseJavaFlags(start_line)
def ParseDesc(self, start_line=0):
"""Parse the initial description.
This could be Python or C++.
Returns:
(start_line, lang_type)
start_line Line to start parsing flags on (int)
lang_type Either 'python' or 'c'
(-1, '') if the flags start could not be found
"""
exec_mod_start = self.executable + ':'
after_blank = 0
start_line = 0 # ignore the passed-in arg for now (?)
for start_line in range(start_line, len(self.output)): # collect top description
line = self.output[start_line].rstrip()
# Python flags start with 'flags:\n'
if ('flags:' == line
and len(self.output) > start_line+1
and '' == self.output[start_line+1].rstrip()):
start_line += 2
logging.debug('Flags start (python): %s' % line)
return (start_line, 'python')
# SWIG flags just have the module name followed by colon.
if exec_mod_start == line:
logging.debug('Flags start (swig): %s' % line)
return (start_line, 'python')
# C++ flags begin after a blank line and with a constant string
if after_blank and line.startswith(' Flags from '):
logging.debug('Flags start (c): %s' % line)
return (start_line, 'c')
# java flags begin with a constant string
if line == 'where flags are':
logging.debug('Flags start (java): %s' % line)
start_line += 2 # skip "Standard flags:"
return (start_line, 'java')
logging.debug('Desc: %s' % line)
self.desc.append(line)
after_blank = (line == '')
else:
logging.warn('Never found the start of the flags section for "%s"!'
% self.long_name)
return (-1, '')
def ParsePythonFlags(self, start_line=0):
"""Parse python/swig style flags."""
modname = None # name of current module
modlist = []
flag = None
for line_num in range(start_line, len(self.output)): # collect flags
line = self.output[line_num].rstrip()
if not line: # blank
continue
mobj = self.module_py_re.match(line)
if mobj: # start of a new module
modname = mobj.group(1)
logging.debug('Module: %s' % line)
if flag:
modlist.append(flag)
self.module_list.append(modname)
self.modules.setdefault(modname, [])
modlist = self.modules[modname]
flag = None
continue
mobj = self.flag_py_re.match(line)
if mobj: # start of a new flag
if flag:
modlist.append(flag)
logging.debug('Flag: %s' % line)
flag = Flag(mobj.group(1), mobj.group(2))
continue
if not flag: # continuation of a flag
logging.error('Flag info, but no current flag "%s"' % line)
mobj = self.flag_default_py_re.match(line)
if mobj: # (default: '...')
flag.default = mobj.group(1)
logging.debug('Fdef: %s' % line)
continue
mobj = self.flag_tips_py_re.match(line)
if mobj: # (tips)
flag.tips = mobj.group(1)
logging.debug('Ftip: %s' % line)
continue
if flag and flag.help:
flag.help += line # multiflags tack on an extra line
else:
logging.info('Extra: %s' % line)
if flag:
modlist.append(flag)
def ParseCFlags(self, start_line=0):
"""Parse C style flags."""
modname = None # name of current module
modlist = []
flag = None
for line_num in range(start_line, len(self.output)): # collect flags
line = self.output[line_num].rstrip()
if not line: # blank lines terminate flags
if flag: # save last flag
modlist.append(flag)
flag = None
continue
mobj = self.module_c_re.match(line)
if mobj: # start of a new module
modname = mobj.group(1)
logging.debug('Module: %s' % line)
if flag:
modlist.append(flag)
self.module_list.append(modname)
self.modules.setdefault(modname, [])
modlist = self.modules[modname]
flag = None
continue
mobj = self.flag_c_re.match(line)
if mobj: # start of a new flag
if flag: # save last flag
modlist.append(flag)
logging.debug('Flag: %s' % line)
flag = Flag(mobj.group(1), mobj.group(2))
continue
# append to flag help. type and default are part of the main text
if flag:
flag.help += ' ' + line.strip()
else:
logging.info('Extra: %s' % line)
if flag:
modlist.append(flag)
def ParseJavaFlags(self, start_line=0):
"""Parse Java style flags (com.google.common.flags)."""
# The java flags prints starts with a "Standard flags" "module"
# that doesn't follow the standard module syntax.
modname = 'Standard flags' # name of current module
self.module_list.append(modname)
self.modules.setdefault(modname, [])
modlist = self.modules[modname]
flag = None
for line_num in range(start_line, len(self.output)): # collect flags
line = self.output[line_num].rstrip()
logging.vlog(2, 'Line: "%s"' % line)
if not line: # blank lines terminate module
if flag: # save last flag
modlist.append(flag)
flag = None
continue
mobj = self.module_java_re.match(line)
if mobj: # start of a new module
modname = mobj.group(1)
logging.debug('Module: %s' % line)
if flag:
modlist.append(flag)
self.module_list.append(modname)
self.modules.setdefault(modname, [])
modlist = self.modules[modname]
flag = None
continue
mobj = self.flag_java_re.match(line)
if mobj: # start of a new flag
if flag: # save last flag
modlist.append(flag)
logging.debug('Flag: %s' % line)
flag = Flag(mobj.group(1), mobj.group(2))
continue
# append to flag help. type and default are part of the main text
if flag:
flag.help += ' ' + line.strip()
else:
logging.info('Extra: %s' % line)
if flag:
modlist.append(flag)
def Filter(self):
"""Filter parsed data to create derived fields."""
if not self.desc:
self.short_desc = ''
return
for i in range(len(self.desc)): # replace full path with name
if self.desc[i].find(self.executable) >= 0:
self.desc[i] = self.desc[i].replace(self.executable, self.name)
self.short_desc = self.desc[0]
word_list = self.short_desc.split(' ')
all_names = [ self.name, self.short_name, ]
# Since the short_desc is always listed right after the name,
# trim it from the short_desc
while word_list and (word_list[0] in all_names
or word_list[0].lower() in all_names):
del word_list[0]
self.short_desc = '' # signal need to reconstruct
if not self.short_desc and word_list:
self.short_desc = ' '.join(word_list)
class GenerateDoc(object):
"""Base class to output flags information."""
def __init__(self, proginfo, directory='.'):
"""Create base object.
Args:
proginfo A ProgramInfo object
directory Directory to write output into
"""
self.info = proginfo
self.dirname = directory
def Output(self):
"""Output all sections of the page."""
self.Open()
self.Header()
self.Body()
self.Footer()
def Open(self): raise NotImplementedError # define in subclass
def Header(self): raise NotImplementedError # define in subclass
def Body(self): raise NotImplementedError # define in subclass
def Footer(self): raise NotImplementedError # define in subclass
class GenerateMan(GenerateDoc):
"""Output a man page."""
def __init__(self, proginfo, directory='.'):
"""Create base object.
Args:
proginfo A ProgramInfo object
directory Directory to write output into
"""
GenerateDoc.__init__(self, proginfo, directory)
def Open(self):
if self.dirname == '-':
logging.info('Writing to stdout')
self.fp = sys.stdout
else:
self.file_path = '%s.1' % os.path.join(self.dirname, self.info.name)
logging.info('Writing: %s' % self.file_path)
self.fp = open(self.file_path, 'w')
def Header(self):
self.fp.write(
'.\\" DO NOT MODIFY THIS FILE! It was generated by gflags2man %s\n'
% _VERSION)
self.fp.write(
'.TH %s "1" "%s" "%s" "User Commands"\n'
% (self.info.name, time.strftime('%x', self.info.date), self.info.name))
self.fp.write(
'.SH NAME\n%s \\- %s\n' % (self.info.name, self.info.short_desc))
self.fp.write(
'.SH SYNOPSIS\n.B %s\n[\\fIFLAGS\\fR]...\n' % self.info.name)
def Body(self):
self.fp.write(
'.SH DESCRIPTION\n.\\" Add any additional description here\n.PP\n')
for ln in self.info.desc:
self.fp.write('%s\n' % ln)
self.fp.write(
'.SH OPTIONS\n')
# This shows flags in the original order
for modname in self.info.module_list:
if modname.find(self.info.executable) >= 0:
mod = modname.replace(self.info.executable, self.info.name)
else:
mod = modname
self.fp.write('\n.P\n.I %s\n' % mod)
for flag in self.info.modules[modname]:
help_string = flag.help
if flag.default or flag.tips:
help_string += '\n.br\n'
if flag.default:
help_string += ' (default: \'%s\')' % flag.default
if flag.tips:
help_string += ' (%s)' % flag.tips
self.fp.write(
'.TP\n%s\n%s\n' % (flag.desc, help_string))
def Footer(self):
self.fp.write(
'.SH COPYRIGHT\nCopyright \(co %s Google.\n'
% time.strftime('%Y', self.info.date))
self.fp.write('Gflags2man created this page from "%s %s" output.\n'
% (self.info.name, FLAGS.help_flag))
self.fp.write('\nGflags2man was written by Dan Christian. '
' Note that the date on this'
' page is the modification date of %s.\n' % self.info.name)
def main(argv):
argv = FLAGS(argv) # handles help as well
if len(argv) <= 1:
print >>sys.stderr, __doc__
print >>sys.stderr, "flags:"
print >>sys.stderr, str(FLAGS)
return 1
for arg in argv[1:]:
prog = ProgramInfo(arg)
if not prog.Run():
continue
prog.Parse()
prog.Filter()
doc = GenerateMan(prog, FLAGS.dest_dir)
doc.Output()
return 0
if __name__ == '__main__':
main(sys.argv)

View file

@ -1,800 +0,0 @@
#!/usr/bin/env python
# Copyright (c) 2007, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"Unittest for flags.py module"
__pychecker__ = "no-local" # for unittest
import sys
import os
import shutil
import unittest
# We use the name 'flags' internally in this test, for historical reasons.
# Don't do this yourself! :-) Just do 'import gflags; FLAGS=gflags.FLAGS; etc'
import gflags as flags
FLAGS=flags.FLAGS
class FlagsUnitTest(unittest.TestCase):
"Flags Unit Test"
def test_flags(self):
##############################################
# Test normal usage with no (expected) errors.
# Define flags
number_test_framework_flags = len(FLAGS.RegisteredFlags())
repeatHelp = "how many times to repeat (0-5)"
flags.DEFINE_integer("repeat", 4, repeatHelp,
lower_bound=0, short_name='r')
flags.DEFINE_string("name", "Bob", "namehelp")
flags.DEFINE_boolean("debug", 0, "debughelp")
flags.DEFINE_boolean("q", 1, "quiet mode")
flags.DEFINE_boolean("quack", 0, "superstring of 'q'")
flags.DEFINE_boolean("noexec", 1, "boolean flag with no as prefix")
flags.DEFINE_integer("x", 3, "how eXtreme to be")
flags.DEFINE_integer("l", 0x7fffffff00000000L, "how long to be")
assert FLAGS.repeat == 4, "integer default values not set:" + FLAGS.repeat
assert FLAGS.name == 'Bob', "default values not set:" + FLAGS.name
assert FLAGS.debug == 0, "boolean default values not set:" + FLAGS.debug
assert FLAGS.q == 1, "boolean default values not set:" + FLAGS.q
assert FLAGS.x == 3, "integer default values not set:" + FLAGS.x
assert FLAGS.l == 0x7fffffff00000000L, "integer default values not set:" + FLAGS.l
flag_values = FLAGS.FlagValuesDict()
assert flag_values['repeat'] == 4
assert flag_values['name'] == 'Bob'
assert flag_values['debug'] == 0
assert flag_values['r'] == 4 # short for of repeat
assert flag_values['q'] == 1
assert flag_values['quack'] == 0
assert flag_values['x'] == 3
assert flag_values['l'] == 0x7fffffff00000000L
# Verify string form of defaults
assert FLAGS['repeat'].default_as_str == "'4'"
assert FLAGS['name'].default_as_str == "'Bob'"
assert FLAGS['debug'].default_as_str == "'false'"
assert FLAGS['q'].default_as_str == "'true'"
assert FLAGS['quack'].default_as_str == "'false'"
assert FLAGS['noexec'].default_as_str == "'true'"
assert FLAGS['x'].default_as_str == "'3'"
assert FLAGS['l'].default_as_str == "'9223372032559808512'"
# Verify that the iterator for flags yields all the keys
keys = list(FLAGS)
keys.sort()
reg_flags = FLAGS.RegisteredFlags()
reg_flags.sort()
self.assertEqual(keys, reg_flags)
# Parse flags
# .. empty command line
argv = ('./program',)
argv = FLAGS(argv)
assert len(argv) == 1, "wrong number of arguments pulled"
assert argv[0]=='./program', "program name not preserved"
# .. non-empty command line
argv = ('./program', '--debug', '--name=Bob', '-q', '--x=8')
argv = FLAGS(argv)
assert len(argv) == 1, "wrong number of arguments pulled"
assert argv[0]=='./program', "program name not preserved"
assert FLAGS['debug'].present == 1
FLAGS['debug'].present = 0 # Reset
assert FLAGS['name'].present == 1
FLAGS['name'].present = 0 # Reset
assert FLAGS['q'].present == 1
FLAGS['q'].present = 0 # Reset
assert FLAGS['x'].present == 1
FLAGS['x'].present = 0 # Reset
# Flags list
assert len(FLAGS.RegisteredFlags()) == 9 + number_test_framework_flags
assert 'name' in FLAGS.RegisteredFlags()
assert 'debug' in FLAGS.RegisteredFlags()
assert 'repeat' in FLAGS.RegisteredFlags()
assert 'r' in FLAGS.RegisteredFlags()
assert 'q' in FLAGS.RegisteredFlags()
assert 'quack' in FLAGS.RegisteredFlags()
assert 'x' in FLAGS.RegisteredFlags()
assert 'l' in FLAGS.RegisteredFlags()
# has_key
assert FLAGS.has_key('name')
assert not FLAGS.has_key('name2')
assert 'name' in FLAGS
assert 'name2' not in FLAGS
# try deleting a flag
del FLAGS.r
assert len(FLAGS.RegisteredFlags()) == 8 + number_test_framework_flags
assert not 'r' in FLAGS.RegisteredFlags()
# .. command line with extra stuff
argv = ('./program', '--debug', '--name=Bob', 'extra')
argv = FLAGS(argv)
assert len(argv) == 2, "wrong number of arguments pulled"
assert argv[0]=='./program', "program name not preserved"
assert argv[1]=='extra', "extra argument not preserved"
assert FLAGS['debug'].present == 1
FLAGS['debug'].present = 0 # Reset
assert FLAGS['name'].present == 1
FLAGS['name'].present = 0 # Reset
# Test reset
argv = ('./program', '--debug')
argv = FLAGS(argv)
assert len(argv) == 1, "wrong number of arguments pulled"
assert argv[0] == './program', "program name not preserved"
assert FLAGS['debug'].present == 1
assert FLAGS['debug'].value == True
FLAGS.Reset()
assert FLAGS['debug'].present == 0
assert FLAGS['debug'].value == False
# Test integer argument passing
argv = ('./program', '--x', '0x12345')
argv = FLAGS(argv)
# 0x12345 == 74565
self.assertEquals(FLAGS.x, 74565)
self.assertEquals(type(FLAGS.x), int)
argv = ('./program', '--x', '0x123456789A')
argv = FLAGS(argv)
# 0x123456789A == 78187493530L
self.assertEquals(FLAGS.x, 78187493530L)
self.assertEquals(type(FLAGS.x), long)
# Treat 0-prefixed parameters as base-10, not base-8
argv = ('./program', '--x', '012345')
argv = FLAGS(argv)
self.assertEquals(FLAGS.x, 12345)
self.assertEquals(type(FLAGS.x), int)
argv = ('./program', '--x', '0123459')
argv = FLAGS(argv)
self.assertEquals(FLAGS.x, 123459)
self.assertEquals(type(FLAGS.x), int)
argv = ('./program', '--x', '0x123efg')
try:
argv = FLAGS(argv)
raise AssertionError("failed to detect invalid hex argument")
except flags.IllegalFlagValue:
pass
argv = ('./program', '--x', '0X123efg')
try:
argv = FLAGS(argv)
raise AssertionError("failed to detect invalid hex argument")
except flags.IllegalFlagValue:
pass
# Test boolean argument parsing
flags.DEFINE_boolean("test0", None, "test boolean parsing")
argv = ('./program', '--notest0')
argv = FLAGS(argv)
assert FLAGS.test0 == 0
flags.DEFINE_boolean("test1", None, "test boolean parsing")
argv = ('./program', '--test1')
argv = FLAGS(argv)
assert FLAGS.test1 == 1
FLAGS.test0 = None
argv = ('./program', '--test0=false')
argv = FLAGS(argv)
assert FLAGS.test0 == 0
FLAGS.test1 = None
argv = ('./program', '--test1=true')
argv = FLAGS(argv)
assert FLAGS.test1 == 1
FLAGS.test0 = None
argv = ('./program', '--test0=0')
argv = FLAGS(argv)
assert FLAGS.test0 == 0
FLAGS.test1 = None
argv = ('./program', '--test1=1')
argv = FLAGS(argv)
assert FLAGS.test1 == 1
# Test booleans that already have 'no' as a prefix
FLAGS.noexec = None
argv = ('./program', '--nonoexec', '--name', 'Bob')
argv = FLAGS(argv)
assert FLAGS.noexec == 0
FLAGS.noexec = None
argv = ('./program', '--name', 'Bob', '--noexec')
argv = FLAGS(argv)
assert FLAGS.noexec == 1
# Test unassigned booleans
flags.DEFINE_boolean("testnone", None, "test boolean parsing")
argv = ('./program',)
argv = FLAGS(argv)
assert FLAGS.testnone == None
# Test get with default
flags.DEFINE_boolean("testget1", None, "test parsing with defaults")
flags.DEFINE_boolean("testget2", None, "test parsing with defaults")
flags.DEFINE_boolean("testget3", None, "test parsing with defaults")
flags.DEFINE_integer("testget4", None, "test parsing with defaults")
argv = ('./program','--testget1','--notestget2')
argv = FLAGS(argv)
assert FLAGS.get('testget1', 'foo') == 1
assert FLAGS.get('testget2', 'foo') == 0
assert FLAGS.get('testget3', 'foo') == 'foo'
assert FLAGS.get('testget4', 'foo') == 'foo'
# test list code
lists = [['hello','moo','boo','1'],
[],]
flags.DEFINE_list('testlist', '', 'test lists parsing')
flags.DEFINE_spaceseplist('testspacelist', '', 'tests space lists parsing')
for name, sep in (('testlist', ','), ('testspacelist', ' '),
('testspacelist', '\n')):
for lst in lists:
argv = ('./program', '--%s=%s' % (name, sep.join(lst)))
argv = FLAGS(argv)
self.assertEquals(getattr(FLAGS, name), lst)
# Test help text
flagsHelp = str(FLAGS)
assert flagsHelp.find("repeat") != -1, "cannot find flag in help"
assert flagsHelp.find(repeatHelp) != -1, "cannot find help string in help"
# Test flag specified twice
argv = ('./program', '--repeat=4', '--repeat=2', '--debug', '--nodebug')
argv = FLAGS(argv)
self.assertEqual(FLAGS.get('repeat', None), 2)
self.assertEqual(FLAGS.get('debug', None), 0)
# Test MultiFlag with single default value
flags.DEFINE_multistring('s_str', 'sing1',
'string option that can occur multiple times',
short_name='s')
self.assertEqual(FLAGS.get('s_str', None), [ 'sing1', ])
# Test MultiFlag with list of default values
multi_string_defs = [ 'def1', 'def2', ]
flags.DEFINE_multistring('m_str', multi_string_defs,
'string option that can occur multiple times',
short_name='m')
self.assertEqual(FLAGS.get('m_str', None), multi_string_defs)
# Test flag specified multiple times with a MultiFlag
argv = ('./program', '--m_str=str1', '-m', 'str2')
argv = FLAGS(argv)
self.assertEqual(FLAGS.get('m_str', None), [ 'str1', 'str2', ])
# Test single-letter flags; should support both single and double dash
argv = ('./program', '-q', '-x8')
argv = FLAGS(argv)
self.assertEqual(FLAGS.get('q', None), 1)
self.assertEqual(FLAGS.get('x', None), 8)
argv = ('./program', '--q', '--x', '9', '--noqu')
argv = FLAGS(argv)
self.assertEqual(FLAGS.get('q', None), 1)
self.assertEqual(FLAGS.get('x', None), 9)
# --noqu should match '--noquack since it's a unique prefix
self.assertEqual(FLAGS.get('quack', None), 0)
argv = ('./program', '--noq', '--x=10', '--qu')
argv = FLAGS(argv)
self.assertEqual(FLAGS.get('q', None), 0)
self.assertEqual(FLAGS.get('x', None), 10)
self.assertEqual(FLAGS.get('quack', None), 1)
####################################
# Test flag serialization code:
oldtestlist = FLAGS.testlist
oldtestspacelist = FLAGS.testspacelist
argv = ('./program',
FLAGS['test0'].Serialize(),
FLAGS['test1'].Serialize(),
FLAGS['testnone'].Serialize(),
FLAGS['s_str'].Serialize())
argv = FLAGS(argv)
self.assertEqual(FLAGS['test0'].Serialize(), '--notest0')
self.assertEqual(FLAGS['test1'].Serialize(), '--test1')
self.assertEqual(FLAGS['testnone'].Serialize(), '')
self.assertEqual(FLAGS['s_str'].Serialize(), '--s_str=sing1')
testlist1 = ['aa', 'bb']
testspacelist1 = ['aa', 'bb', 'cc']
FLAGS.testlist = list(testlist1)
FLAGS.testspacelist = list(testspacelist1)
argv = ('./program',
FLAGS['testlist'].Serialize(),
FLAGS['testspacelist'].Serialize())
argv = FLAGS(argv)
self.assertEqual(FLAGS.testlist, testlist1)
self.assertEqual(FLAGS.testspacelist, testspacelist1)
testlist1 = ['aa some spaces', 'bb']
testspacelist1 = ['aa', 'bb,some,commas,', 'cc']
FLAGS.testlist = list(testlist1)
FLAGS.testspacelist = list(testspacelist1)
argv = ('./program',
FLAGS['testlist'].Serialize(),
FLAGS['testspacelist'].Serialize())
argv = FLAGS(argv)
self.assertEqual(FLAGS.testlist, testlist1)
self.assertEqual(FLAGS.testspacelist, testspacelist1)
FLAGS.testlist = oldtestlist
FLAGS.testspacelist = oldtestspacelist
####################################
# Test flag-update:
def ArgsString():
flagnames = FLAGS.RegisteredFlags()
flagnames.sort()
nonbool_flags = ['--%s %s' % (name, FLAGS.get(name, None))
for name in flagnames
if not isinstance(FLAGS[name], flags.BooleanFlag)]
truebool_flags = ['--%s' % (name)
for name in flagnames
if isinstance(FLAGS[name], flags.BooleanFlag) and
FLAGS.get(name, None)]
falsebool_flags = ['--no%s' % (name)
for name in flagnames
if isinstance(FLAGS[name], flags.BooleanFlag) and
not FLAGS.get(name, None)]
return ' '.join(nonbool_flags + truebool_flags + falsebool_flags)
argv = ('./program', '--repeat=3', '--name=giants', '--nodebug')
FLAGS(argv)
self.assertEqual(FLAGS.get('repeat', None), 3)
self.assertEqual(FLAGS.get('name', None), 'giants')
self.assertEqual(FLAGS.get('debug', None), 0)
self.assertEqual(ArgsString(),
"--l 9223372032559808512 "
"--m ['str1', 'str2'] --m_str ['str1', 'str2'] "
"--name giants "
"--repeat 3 "
"--s ['sing1'] --s_str ['sing1'] "
"--testget4 None --testlist [] "
"--testspacelist [] --x 10 "
"--noexec --quack "
"--test1 "
"--testget1 --no? --nodebug --nohelp --nohelpshort "
"--noq --notest0 --notestget2 "
"--notestget3 --notestnone")
argv = ('./program', '--debug', '--m_str=upd1', '-s', 'upd2')
FLAGS(argv)
self.assertEqual(FLAGS.get('repeat', None), 3)
self.assertEqual(FLAGS.get('name', None), 'giants')
self.assertEqual(FLAGS.get('debug', None), 1)
# items appended to existing non-default value lists for --m/--m_str
# new value overwrites default value (not appended to it) for --s/--s_str
self.assertEqual(ArgsString(),
"--l 9223372032559808512 "
"--m ['str1', 'str2', 'upd1'] "
"--m_str ['str1', 'str2', 'upd1'] "
"--name giants "
"--repeat 3 "
"--s ['upd2'] --s_str ['upd2'] "
"--testget4 None --testlist [] "
"--testspacelist [] --x 10 "
"--debug --noexec --quack "
"--test1 "
"--testget1 --no? --nohelp --nohelpshort "
"--noq --notest0 --notestget2 "
"--notestget3 --notestnone")
####################################
# Test all kind of error conditions.
# Duplicate flag detection
try:
flags.DEFINE_boolean("run", 0, "runhelp", short_name='q')
raise AssertionError("duplicate flag detection failed")
except flags.DuplicateFlag, e:
pass
try:
flags.DEFINE_boolean("zoom1", 0, "runhelp z1", short_name='z')
flags.DEFINE_boolean("zoom2", 0, "runhelp z2", short_name='z')
raise AssertionError("duplicate flag detection failed")
except flags.DuplicateFlag, e:
pass
# Make sure allow_override works
try:
flags.DEFINE_boolean("dup1", 0, "runhelp d11", short_name='u',
allow_override=0)
flag = FLAGS.FlagDict()['dup1']
self.assertEqual(flag.default, 0)
flags.DEFINE_boolean("dup1", 1, "runhelp d12", short_name='u',
allow_override=1)
flag = FLAGS.FlagDict()['dup1']
self.assertEqual(flag.default, 1)
except flags.DuplicateFlag, e:
raise AssertionError("allow_override did not permit a flag duplication")
# Make sure allow_override works
try:
flags.DEFINE_boolean("dup2", 0, "runhelp d21", short_name='u',
allow_override=1)
flag = FLAGS.FlagDict()['dup2']
self.assertEqual(flag.default, 0)
flags.DEFINE_boolean("dup2", 1, "runhelp d22", short_name='u',
allow_override=0)
flag = FLAGS.FlagDict()['dup2']
self.assertEqual(flag.default, 1)
except flags.DuplicateFlag, e:
raise AssertionError("allow_override did not permit a flag duplication")
# Make sure allow_override doesn't work with None default
try:
flags.DEFINE_boolean("dup3", 0, "runhelp d31", short_name='u',
allow_override=0)
flag = FLAGS.FlagDict()['dup3']
self.assertEqual(flag.default, 0)
flags.DEFINE_boolean("dup3", None, "runhelp d32", short_name='u',
allow_override=1)
raise AssertionError('Cannot override a flag with a default of None')
except flags.DuplicateFlag, e:
pass
# Make sure that when we override, the help string gets updated correctly
flags.DEFINE_boolean("dup3", 0, "runhelp d31", short_name='u',
allow_override=1)
flags.DEFINE_boolean("dup3", 1, "runhelp d32", short_name='u',
allow_override=1)
self.assert_(str(FLAGS).find('runhelp d31') == -1)
self.assert_(str(FLAGS).find('runhelp d32') != -1)
# Integer out of bounds
try:
argv = ('./program', '--repeat=-4')
FLAGS(argv)
raise AssertionError('integer bounds exception not thrown:'
+ str(FLAGS.repeat))
except flags.IllegalFlagValue:
pass
# Non-integer
try:
argv = ('./program', '--repeat=2.5')
FLAGS(argv)
raise AssertionError("malformed integer value exception not thrown")
except flags.IllegalFlagValue:
pass
# Missing required arugment
try:
argv = ('./program', '--name')
FLAGS(argv)
raise AssertionError("Flag argument required exception not thrown")
except flags.FlagsError:
pass
# Argument erroneously supplied for boolean
try:
argv = ('./program', '--debug=goofup')
FLAGS(argv)
raise AssertionError("No argument allowed exception not thrown")
except flags.FlagsError:
pass
# Unknown argument --nosuchflag
try:
argv = ('./program', '--nosuchflag', '--name=Bob', 'extra')
FLAGS(argv)
raise AssertionError("Unknown argument exception not thrown")
except flags.FlagsError:
pass
# Non-numeric argument for integer flag --repeat
try:
argv = ('./program', '--repeat', 'Bob', 'extra')
FLAGS(argv)
raise AssertionError("Illegal flag value exception not thrown")
except flags.IllegalFlagValue:
pass
################################################
# Code to test the flagfile=<> loading behavior
################################################
def _SetupTestFiles(self):
""" Creates and sets up some dummy flagfile files with bogus flags"""
# Figure out where to create temporary files
tmp_path = '/tmp/flags_unittest'
if os.path.exists(tmp_path):
shutil.rmtree(tmp_path)
os.makedirs(tmp_path)
try:
tmp_flag_file_1 = open((tmp_path + '/UnitTestFile1.tst'), 'w')
tmp_flag_file_2 = open((tmp_path + '/UnitTestFile2.tst'), 'w')
tmp_flag_file_3 = open((tmp_path + '/UnitTestFile3.tst'), 'w')
except IOError, e_msg:
print e_msg
print 'FAIL\n File Creation problem in Unit Test'
sys.exit(1)
# put some dummy flags in our test files
tmp_flag_file_1.write('#A Fake Comment\n')
tmp_flag_file_1.write('--UnitTestMessage1=tempFile1!\n')
tmp_flag_file_1.write('\n')
tmp_flag_file_1.write('--UnitTestNumber=54321\n')
tmp_flag_file_1.write('--noUnitTestBoolFlag\n')
file_list = [tmp_flag_file_1.name]
# this one includes test file 1
tmp_flag_file_2.write('//A Different Fake Comment\n')
tmp_flag_file_2.write('--flagfile=%s\n' % tmp_flag_file_1.name)
tmp_flag_file_2.write('--UnitTestMessage2=setFromTempFile2\n')
tmp_flag_file_2.write('\t\t\n')
tmp_flag_file_2.write('--UnitTestNumber=6789a\n')
file_list.append(tmp_flag_file_2.name)
# this file points to itself
tmp_flag_file_3.write('--flagfile=%s\n' % tmp_flag_file_3.name)
tmp_flag_file_3.write('--UnitTestMessage1=setFromTempFile3\n')
tmp_flag_file_3.write('#YAFC\n')
tmp_flag_file_3.write('--UnitTestBoolFlag\n')
file_list.append(tmp_flag_file_3.name)
tmp_flag_file_1.close()
tmp_flag_file_2.close()
tmp_flag_file_3.close()
return file_list # these are just the file names
# end SetupFiles def
def _RemoveTestFiles(self, tmp_file_list):
"""Closes the files we just created. tempfile deletes them for us """
for file_name in tmp_file_list:
try:
os.remove(file_name)
except OSError, e_msg:
print '%s\n, Problem deleting test file' % e_msg
#end RemoveTestFiles def
def __DeclareSomeFlags(self):
flags.DEFINE_string('UnitTestMessage1', 'Foo!', 'You Add Here.')
flags.DEFINE_string('UnitTestMessage2', 'Bar!', 'Hello, Sailor!')
flags.DEFINE_boolean('UnitTestBoolFlag', 0, 'Some Boolean thing')
flags.DEFINE_integer('UnitTestNumber', 12345, 'Some integer',
lower_bound=0)
def _UndeclareSomeFlags(self):
FLAGS.__delattr__('UnitTestMessage1')
FLAGS.__delattr__('UnitTestMessage2')
FLAGS.__delattr__('UnitTestBoolFlag')
FLAGS.__delattr__('UnitTestNumber')
#### Flagfile Unit Tests ####
def testMethod_flagfiles_1(self):
""" Test trivial case with no flagfile based options. """
self.__DeclareSomeFlags()
fake_cmd_line = 'fooScript --UnitTestBoolFlag'
fake_argv = fake_cmd_line.split(' ')
FLAGS(fake_argv)
self.assertEqual( FLAGS.UnitTestBoolFlag, 1)
self.assertEqual( fake_argv, FLAGS.ReadFlagsFromFiles(fake_argv))
self._UndeclareSomeFlags()
# end testMethodOne
def testMethod_flagfiles_2(self):
"""Tests parsing one file + arguments off simulated argv"""
self.__DeclareSomeFlags()
tmp_files = self._SetupTestFiles()
# specify our temp file on the fake cmd line
fake_cmd_line = 'fooScript --q --flagfile=%s' % tmp_files[0]
fake_argv = fake_cmd_line.split(' ')
# We should see the original cmd line with the file's contents spliced in.
# Note that these will be in REVERSE order from order encountered in file
# This is done so arguements we encounter sooner will have priority.
expected_results = ['fooScript',
'--UnitTestMessage1=tempFile1!',
'--UnitTestNumber=54321',
'--noUnitTestBoolFlag',
'--q']
test_results = FLAGS.ReadFlagsFromFiles(fake_argv)
self.assertEqual(expected_results, test_results)
self._RemoveTestFiles(tmp_files)
self._UndeclareSomeFlags()
# end testTwo def
def testMethod_flagfiles_3(self):
"""Tests parsing nested files + arguments of simulated argv"""
self.__DeclareSomeFlags()
tmp_files = self._SetupTestFiles()
# specify our temp file on the fake cmd line
fake_cmd_line = ('fooScript --UnitTestNumber=77 --flagfile=%s'
% tmp_files[1])
fake_argv = fake_cmd_line.split(' ')
expected_results = ['fooScript',
'--UnitTestMessage1=tempFile1!',
'--UnitTestNumber=54321',
'--noUnitTestBoolFlag',
'--UnitTestMessage2=setFromTempFile2',
'--UnitTestNumber=6789a',
'--UnitTestNumber=77']
test_results = FLAGS.ReadFlagsFromFiles(fake_argv)
self.assertEqual(expected_results, test_results)
self._RemoveTestFiles(tmp_files)
self._UndeclareSomeFlags()
# end testThree def
def testMethod_flagfiles_4(self):
"""Tests parsing self referetial files + arguments of simulated argv.
This test should print a warning to stderr of some sort.
"""
self.__DeclareSomeFlags()
tmp_files = self._SetupTestFiles()
# specify our temp file on the fake cmd line
fake_cmd_line = ('fooScript --flagfile=%s --noUnitTestBoolFlag'
% tmp_files[2])
fake_argv = fake_cmd_line.split(' ')
expected_results = ['fooScript',
'--UnitTestMessage1=setFromTempFile3',
'--UnitTestBoolFlag',
'--noUnitTestBoolFlag' ]
test_results = FLAGS.ReadFlagsFromFiles(fake_argv)
self.assertEqual(expected_results, test_results)
self._RemoveTestFiles(tmp_files)
self._UndeclareSomeFlags()
def test_flagfiles_user_path_expansion(self):
"""Test that user directory referenced paths (ie. ~/foo) are correctly
expanded. This test depends on whatever account's running the unit test
to have read/write access to their own home directory, otherwise it'll
FAIL.
"""
self.__DeclareSomeFlags()
fake_flagfile_item_style_1 = '--flagfile=~/foo.file'
fake_flagfile_item_style_2 = '-flagfile=~/foo.file'
expected_results = os.path.expanduser('~/foo.file')
test_results = FLAGS.ExtractFilename(fake_flagfile_item_style_1)
self.assertEqual(expected_results, test_results)
test_results = FLAGS.ExtractFilename(fake_flagfile_item_style_2)
self.assertEqual(expected_results, test_results)
self._UndeclareSomeFlags()
# end testFour def
def test_no_touchy_non_flags(self):
"""
Test that the flags parser does not mutilate arguments which are
not supposed to be flags
"""
self.__DeclareSomeFlags()
fake_argv = ['fooScript', '--UnitTestBoolFlag',
'command', '--command_arg1', '--UnitTestBoom', '--UnitTestB']
argv = FLAGS(fake_argv)
self.assertEqual(argv, fake_argv[:1] + fake_argv[2:])
self._UndeclareSomeFlags()
def test_SetDefault(self):
"""
Test changing flag defaults.
"""
self.__DeclareSomeFlags()
# Test that SetDefault changes both the default and the value,
# and that the value is changed when one is given as an option.
FLAGS['UnitTestMessage1'].SetDefault('New value')
self.assertEqual(FLAGS.UnitTestMessage1, 'New value')
self.assertEqual(FLAGS['UnitTestMessage1'].default_as_str,"'New value'")
FLAGS([ 'dummyscript', '--UnitTestMessage1=Newer value' ])
self.assertEqual(FLAGS.UnitTestMessage1, 'Newer value')
# Test that setting the default to None works correctly.
FLAGS['UnitTestNumber'].SetDefault(None)
self.assertEqual(FLAGS.UnitTestNumber, None)
self.assertEqual(FLAGS['UnitTestNumber'].default_as_str, None)
FLAGS([ 'dummyscript', '--UnitTestNumber=56' ])
self.assertEqual(FLAGS.UnitTestNumber, 56)
# Test that setting invalid defaults raises exceptions
self.assertRaises(flags.IllegalFlagValue,
FLAGS['UnitTestNumber'].SetDefault, 'oops')
self.assertRaises(flags.IllegalFlagValue,
FLAGS['UnitTestNumber'].SetDefault, -1)
self.assertRaises(flags.IllegalFlagValue,
FLAGS['UnitTestBoolFlag'].SetDefault, 'oops')
self._UndeclareSomeFlags()
def testMethod_ShortestUniquePrefixes(self):
"""
Test FlagValues.ShortestUniquePrefixes
"""
flags.DEFINE_string('a', '', '')
flags.DEFINE_string('abc', '', '')
flags.DEFINE_string('common_a_string', '', '')
flags.DEFINE_boolean('common_b_boolean', 0, '')
flags.DEFINE_boolean('common_c_boolean', 0, '')
flags.DEFINE_boolean('common', 0, '')
flags.DEFINE_integer('commonly', 0, '')
flags.DEFINE_boolean('zz', 0, '')
flags.DEFINE_integer('nozz', 0, '')
shorter_flags = FLAGS.ShortestUniquePrefixes(FLAGS.FlagDict())
expected_results = {'nocommon_b_boolean': 'nocommon_b',
'common_c_boolean': 'common_c',
'common_b_boolean': 'common_b',
'a': 'a',
'abc': 'ab',
'zz': 'z',
'nozz': 'nozz',
'common_a_string': 'common_a',
'commonly': 'commonl',
'nocommon_c_boolean': 'nocommon_c',
'nocommon': 'nocommon',
'common': 'common'}
for name, shorter in expected_results.iteritems():
self.assertEquals(shorter_flags[name], shorter)
FLAGS.__delattr__('a')
FLAGS.__delattr__('abc')
FLAGS.__delattr__('common_a_string')
FLAGS.__delattr__('common_b_boolean')
FLAGS.__delattr__('common_c_boolean')
FLAGS.__delattr__('common')
FLAGS.__delattr__('commonly')
FLAGS.__delattr__('zz')
FLAGS.__delattr__('nozz')
if __name__ == '__main__':
unittest.main()

View file

@ -1,42 +0,0 @@
#!/usr/bin/python2.2
# Copyright (c) 2007, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from distutils.core import setup
setup(name='gflags',
version='0.2',
description='Google Commandline Flags Module',
license='BSD',
author='Google Inc.',
author_email='opensource@google.com',
url='http://code.google.com/p/google-gflags',
py_modules=["gflags"],
data_files=["/usr/local/bin", "gflags2man.py"])

59
src/config.h Normal file
View file

@ -0,0 +1,59 @@
// Note: This header file is only used internally. It is not part of public interface!
#ifndef GFLAGS_CONFIG_H_
#define GFLAGS_CONFIG_H_
// ---------------------------------------------------------------------------
// System checks
// CMake build configuration is written to defines.h file, unused by Bazel build
#if !defined(GFLAGS_BAZEL_BUILD)
# include "defines.h"
#endif
// gcc requires this to get PRId64, etc.
#if defined(HAVE_INTTYPES_H) && !defined(__STDC_FORMAT_MACROS)
# define __STDC_FORMAT_MACROS 1
#endif
// ---------------------------------------------------------------------------
// Path separator
#ifndef PATH_SEPARATOR
# ifdef OS_WINDOWS
# define PATH_SEPARATOR '\\'
# else
# define PATH_SEPARATOR '/'
# endif
#endif
// ---------------------------------------------------------------------------
// Windows
// Always export symbols when compiling a shared library as this file is only
// included by internal modules when building the gflags library itself.
// The gflags_declare.h header file will set it to import these symbols otherwise.
#ifndef GFLAGS_DLL_DECL
# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
# define GFLAGS_DLL_DECL __declspec(dllexport)
# elif defined(__GNUC__) && __GNUC__ >= 4
# define GFLAGS_DLL_DECL __attribute__((visibility("default")))
# else
# define GFLAGS_DLL_DECL
# endif
#endif
// Flags defined by the gflags library itself must be exported
#ifndef GFLAGS_DLL_DEFINE_FLAG
# define GFLAGS_DLL_DEFINE_FLAG GFLAGS_DLL_DECL
#endif
#ifdef OS_WINDOWS
// The unittests import the symbols of the shared gflags library
# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
# define GFLAGS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
# endif
# include "windows_port.h"
#endif
#endif // GFLAGS_CONFIG_H_

48
src/defines.h.in Normal file
View file

@ -0,0 +1,48 @@
/* Generated from defines.h.in during build configuration using CMake. */
// Note: This header file is only used internally. It is not part of public interface!
// Any cmakedefine is defined using the -D flag instead when Bazel is used.
// For Bazel, this file is thus not used to avoid a private file in $(GENDIR).
#ifndef GFLAGS_DEFINES_H_
#define GFLAGS_DEFINES_H_
// Define if you build this library for a MS Windows OS.
#cmakedefine OS_WINDOWS
// Define if you have the <stdint.h> header file.
#cmakedefine HAVE_STDINT_H
// Define if you have the <sys/types.h> header file.
#cmakedefine HAVE_SYS_TYPES_H
// Define if you have the <inttypes.h> header file.
#cmakedefine HAVE_INTTYPES_H
// Define if you have the <sys/stat.h> header file.
#cmakedefine HAVE_SYS_STAT_H
// Define if you have the <unistd.h> header file.
#cmakedefine HAVE_UNISTD_H
// Define if you have the <fnmatch.h> header file.
#cmakedefine HAVE_FNMATCH_H
// Define if you have the <shlwapi.h> header file (Windows 2000/XP).
#cmakedefine HAVE_SHLWAPI_H
// Define if you have the strtoll function.
#cmakedefine HAVE_STRTOLL
// Define if you have the strtoq function.
#cmakedefine HAVE_STRTOQ
// Define if you have the <pthread.h> header file.
#cmakedefine HAVE_PTHREAD
// Define if your pthread library defines the type pthread_rwlock_t
#cmakedefine HAVE_RWLOCK
#endif // GFLAGS_DEFINES_H_

File diff suppressed because it is too large Load diff

626
src/gflags.h.in Normal file
View file

@ -0,0 +1,626 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// Revamped and reorganized by Craig Silverstein
//
// This is the file that should be included by any file which declares
// or defines a command line flag or wants to parse command line flags
// or print a program usage message (which will include information about
// flags). Executive summary, in the form of an example foo.cc file:
//
// #include "foo.h" // foo.h has a line "DECLARE_int32(start);"
// #include "validators.h" // hypothetical file defining ValidateIsFile()
//
// DEFINE_int32(end, 1000, "The last record to read");
//
// DEFINE_string(filename, "my_file.txt", "The file to read");
// // Crash if the specified file does not exist.
// static bool dummy = RegisterFlagValidator(&FLAGS_filename,
// &ValidateIsFile);
//
// DECLARE_bool(verbose); // some other file has a DEFINE_bool(verbose, ...)
//
// void MyFunc() {
// if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end);
// }
//
// Then, at the command-line:
// ./foo --noverbose --start=5 --end=100
//
// For more details, see
// doc/gflags.html
//
// --- A note about thread-safety:
//
// We describe many functions in this routine as being thread-hostile,
// thread-compatible, or thread-safe. Here are the meanings we use:
//
// thread-safe: it is safe for multiple threads to call this routine
// (or, when referring to a class, methods of this class)
// concurrently.
// thread-hostile: it is not safe for multiple threads to call this
// routine (or methods of this class) concurrently. In gflags,
// most thread-hostile routines are intended to be called early in,
// or even before, main() -- that is, before threads are spawned.
// thread-compatible: it is safe for multiple threads to read from
// this variable (when applied to variables), or to call const
// methods of this class (when applied to classes), as long as no
// other thread is writing to the variable or calling non-const
// methods of this class.
#ifndef GFLAGS_GFLAGS_H_
#define GFLAGS_GFLAGS_H_
#include <string>
#include <vector>
#include "gflags/gflags_declare.h" // IWYU pragma: export
// We always want to export variables defined in user code
#ifndef GFLAGS_DLL_DEFINE_FLAG
# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
# define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport)
# else
# define GFLAGS_DLL_DEFINE_FLAG
# endif
#endif
namespace GFLAGS_NAMESPACE {
// --------------------------------------------------------------------
// To actually define a flag in a file, use DEFINE_bool,
// DEFINE_string, etc. at the bottom of this file. You may also find
// it useful to register a validator with the flag. This ensures that
// when the flag is parsed from the commandline, or is later set via
// SetCommandLineOption, we call the validation function. It is _not_
// called when you assign the value to the flag directly using the = operator.
//
// The validation function should return true if the flag value is valid, and
// false otherwise. If the function returns false for the new setting of the
// flag, the flag will retain its current value. If it returns false for the
// default value, ParseCommandLineFlags() will die.
//
// This function is safe to call at global construct time (as in the
// example below).
//
// Example use:
// static bool ValidatePort(const char* flagname, int32 value) {
// if (value > 0 && value < 32768) // value is ok
// return true;
// printf("Invalid value for --%s: %d\n", flagname, (int)value);
// return false;
// }
// DEFINE_int32(port, 0, "What port to listen on");
// static bool dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort);
// Returns true if successfully registered, false if not (because the
// first argument doesn't point to a command-line flag, or because a
// validator is already registered for this flag).
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const bool* flag, bool (*validate_fn)(const char*, bool));
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int32* flag, bool (*validate_fn)(const char*, int32));
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint32* flag, bool (*validate_fn)(const char*, uint32));
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const int64* flag, bool (*validate_fn)(const char*, int64));
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const uint64* flag, bool (*validate_fn)(const char*, uint64));
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const double* flag, bool (*validate_fn)(const char*, double));
extern GFLAGS_DLL_DECL bool RegisterFlagValidator(const std::string* flag, bool (*validate_fn)(const char*, const std::string&));
// Convenience macro for the registration of a flag validator
#define DEFINE_validator(name, validator) \
static const bool name##_validator_registered = \
GFLAGS_NAMESPACE::RegisterFlagValidator(&FLAGS_##name, validator)
// --------------------------------------------------------------------
// These methods are the best way to get access to info about the
// list of commandline flags. Note that these routines are pretty slow.
// GetAllFlags: mostly-complete info about the list, sorted by file.
// ShowUsageWithFlags: pretty-prints the list to stdout (what --help does)
// ShowUsageWithFlagsRestrict: limit to filenames with restrict as a substr
//
// In addition to accessing flags, you can also access argv[0] (the program
// name) and argv (the entire commandline), which we sock away a copy of.
// These variables are static, so you should only set them once.
//
// No need to export this data only structure from DLL, avoiding VS warning 4251.
struct CommandLineFlagInfo {
std::string name; // the name of the flag
std::string type; // the type of the flag: int32, etc
std::string description; // the "help text" associated with the flag
std::string current_value; // the current value, as a string
std::string default_value; // the default value, as a string
std::string filename; // 'cleaned' version of filename holding the flag
bool has_validator_fn; // true if RegisterFlagValidator called on this flag
bool is_default; // true if the flag has the default value and
// has not been set explicitly from the cmdline
// or via SetCommandLineOption
const void* flag_ptr; // pointer to the flag's current value (i.e. FLAGS_foo)
};
// Using this inside of a validator is a recipe for a deadlock.
// TODO(user) Fix locking when validators are running, to make it safe to
// call validators during ParseAllFlags.
// Also make sure then to uncomment the corresponding unit test in
// gflags_unittest.sh
extern GFLAGS_DLL_DECL void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
// These two are actually defined in gflags_reporting.cc.
extern GFLAGS_DLL_DECL void ShowUsageWithFlags(const char *argv0); // what --help does
extern GFLAGS_DLL_DECL void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict);
// Create a descriptive string for a flag.
// Goes to some trouble to make pretty line breaks.
extern GFLAGS_DLL_DECL std::string DescribeOneFlag(const CommandLineFlagInfo& flag);
// Thread-hostile; meant to be called before any threads are spawned.
extern GFLAGS_DLL_DECL void SetArgv(int argc, const char** argv);
// The following functions are thread-safe as long as SetArgv() is
// only called before any threads start.
extern GFLAGS_DLL_DECL const std::vector<std::string>& GetArgvs();
extern GFLAGS_DLL_DECL const char* GetArgv(); // all of argv as a string
extern GFLAGS_DLL_DECL const char* GetArgv0(); // only argv0
extern GFLAGS_DLL_DECL uint32 GetArgvSum(); // simple checksum of argv
extern GFLAGS_DLL_DECL const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
extern GFLAGS_DLL_DECL const char* ProgramInvocationShortName(); // basename(argv0)
// ProgramUsage() is thread-safe as long as SetUsageMessage() is only
// called before any threads start.
extern GFLAGS_DLL_DECL const char* ProgramUsage(); // string set by SetUsageMessage()
// VersionString() is thread-safe as long as SetVersionString() is only
// called before any threads start.
extern GFLAGS_DLL_DECL const char* VersionString(); // string set by SetVersionString()
// --------------------------------------------------------------------
// Normally you access commandline flags by just saying "if (FLAGS_foo)"
// or whatever, and set them by calling "FLAGS_foo = bar" (or, more
// commonly, via the DEFINE_foo macro). But if you need a bit more
// control, we have programmatic ways to get/set the flags as well.
// These programmatic ways to access flags are thread-safe, but direct
// access is only thread-compatible.
// Return true iff the flagname was found.
// OUTPUT is set to the flag's value, or unchanged if we return false.
extern GFLAGS_DLL_DECL bool GetCommandLineOption(const char* name, std::string* OUTPUT);
// Return true iff the flagname was found. OUTPUT is set to the flag's
// CommandLineFlagInfo or unchanged if we return false.
extern GFLAGS_DLL_DECL bool GetCommandLineFlagInfo(const char* name, CommandLineFlagInfo* OUTPUT);
// Return the CommandLineFlagInfo of the flagname. exit() if name not found.
// Example usage, to check if a flag's value is currently the default value:
// if (GetCommandLineFlagInfoOrDie("foo").is_default) ...
extern GFLAGS_DLL_DECL CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name);
enum FlagSettingMode {
// update the flag's value (can call this multiple times).
SET_FLAGS_VALUE,
// update the flag's value, but *only if* it has not yet been updated
// with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef".
SET_FLAG_IF_DEFAULT,
// set the flag's default value to this. If the flag has not yet updated
// yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef")
// change the flag's current value to the new default value as well.
SET_FLAGS_DEFAULT
};
// Set a particular flag ("command line option"). Returns a string
// describing the new value that the option has been set to. The
// return value API is not well-specified, so basically just depend on
// it to be empty if the setting failed for some reason -- the name is
// not a valid flag name, or the value is not a valid value -- and
// non-empty else.
// SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case)
extern GFLAGS_DLL_DECL std::string SetCommandLineOption (const char* name, const char* value);
extern GFLAGS_DLL_DECL std::string SetCommandLineOptionWithMode(const char* name, const char* value, FlagSettingMode set_mode);
// --------------------------------------------------------------------
// Saves the states (value, default value, whether the user has set
// the flag, registered validators, etc) of all flags, and restores
// them when the FlagSaver is destroyed. This is very useful in
// tests, say, when you want to let your tests change the flags, but
// make sure that they get reverted to the original states when your
// test is complete.
//
// Example usage:
// void TestFoo() {
// FlagSaver s1;
// FLAG_foo = false;
// FLAG_bar = "some value";
//
// // test happens here. You can return at any time
// // without worrying about restoring the FLAG values.
// }
//
// Note: This class is marked with GFLAGS_ATTRIBUTE_UNUSED because all
// the work is done in the constructor and destructor, so in the standard
// usage example above, the compiler would complain that it's an
// unused variable.
//
// This class is thread-safe. However, its destructor writes to
// exactly the set of flags that have changed value during its
// lifetime, so concurrent _direct_ access to those flags
// (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe.
class GFLAGS_DLL_DECL FlagSaver {
public:
FlagSaver();
~FlagSaver();
private:
class FlagSaverImpl* impl_; // we use pimpl here to keep API steady
FlagSaver(const FlagSaver&); // no copying!
void operator=(const FlagSaver&);
}@GFLAGS_ATTRIBUTE_UNUSED@;
// --------------------------------------------------------------------
// Some deprecated or hopefully-soon-to-be-deprecated functions.
// This is often used for logging. TODO(csilvers): figure out a better way
extern GFLAGS_DLL_DECL std::string CommandlineFlagsIntoString();
// Usually where this is used, a FlagSaver should be used instead.
extern GFLAGS_DLL_DECL
bool ReadFlagsFromString(const std::string& flagfilecontents,
const char* prog_name,
bool errors_are_fatal); // uses SET_FLAGS_VALUE
// These let you manually implement --flagfile functionality.
// DEPRECATED.
extern GFLAGS_DLL_DECL bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
extern GFLAGS_DLL_DECL bool ReadFromFlagsFile(const std::string& filename, const char* prog_name, bool errors_are_fatal); // uses SET_FLAGS_VALUE
// --------------------------------------------------------------------
// Useful routines for initializing flags from the environment.
// In each case, if 'varname' does not exist in the environment
// return defval. If 'varname' does exist but is not valid
// (e.g., not a number for an int32 flag), abort with an error.
// Otherwise, return the value. NOTE: for booleans, for true use
// 't' or 'T' or 'true' or '1', for false 'f' or 'F' or 'false' or '0'.
extern GFLAGS_DLL_DECL bool BoolFromEnv(const char *varname, bool defval);
extern GFLAGS_DLL_DECL int32 Int32FromEnv(const char *varname, int32 defval);
extern GFLAGS_DLL_DECL uint32 Uint32FromEnv(const char *varname, uint32 defval);
extern GFLAGS_DLL_DECL int64 Int64FromEnv(const char *varname, int64 defval);
extern GFLAGS_DLL_DECL uint64 Uint64FromEnv(const char *varname, uint64 defval);
extern GFLAGS_DLL_DECL double DoubleFromEnv(const char *varname, double defval);
extern GFLAGS_DLL_DECL const char *StringFromEnv(const char *varname, const char *defval);
// --------------------------------------------------------------------
// The next two functions parse gflags from main():
// Set the "usage" message for this program. For example:
// string usage("This program does nothing. Sample usage:\n");
// usage += argv[0] + " <uselessarg1> <uselessarg2>";
// SetUsageMessage(usage);
// Do not include commandline flags in the usage: we do that for you!
// Thread-hostile; meant to be called before any threads are spawned.
extern GFLAGS_DLL_DECL void SetUsageMessage(const std::string& usage);
// Sets the version string, which is emitted with --version.
// For instance: SetVersionString("1.3");
// Thread-hostile; meant to be called before any threads are spawned.
extern GFLAGS_DLL_DECL void SetVersionString(const std::string& version);
// Looks for flags in argv and parses them. Rearranges argv to put
// flags first, or removes them entirely if remove_flags is true.
// If a flag is defined more than once in the command line or flag
// file, the last definition is used. Returns the index (into argv)
// of the first non-flag argument.
// See top-of-file for more details on this function.
#ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead.
extern GFLAGS_DLL_DECL uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags);
#endif
// Calls to ParseCommandLineNonHelpFlags and then to
// HandleCommandLineHelpFlags can be used instead of a call to
// ParseCommandLineFlags during initialization, in order to allow for
// changing default values for some FLAGS (via
// e.g. SetCommandLineOptionWithMode calls) between the time of
// command line parsing and the time of dumping help information for
// the flags as a result of command line parsing. If a flag is
// defined more than once in the command line or flag file, the last
// definition is used. Returns the index (into argv) of the first
// non-flag argument. (If remove_flags is true, will always return 1.)
extern GFLAGS_DLL_DECL uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv, bool remove_flags);
// This is actually defined in gflags_reporting.cc.
// This function is misnamed (it also handles --version, etc.), but
// it's too late to change that now. :-(
extern GFLAGS_DLL_DECL void HandleCommandLineHelpFlags(); // in gflags_reporting.cc
// Allow command line reparsing. Disables the error normally
// generated when an unknown flag is found, since it may be found in a
// later parse. Thread-hostile; meant to be called before any threads
// are spawned.
extern GFLAGS_DLL_DECL void AllowCommandLineReparsing();
// Reparse the flags that have not yet been recognized. Only flags
// registered since the last parse will be recognized. Any flag value
// must be provided as part of the argument using "=", not as a
// separate command line argument that follows the flag argument.
// Intended for handling flags from dynamically loaded libraries,
// since their flags are not registered until they are loaded.
extern GFLAGS_DLL_DECL void ReparseCommandLineNonHelpFlags();
// Clean up memory allocated by flags. This is only needed to reduce
// the quantity of "potentially leaked" reports emitted by memory
// debugging tools such as valgrind. It is not required for normal
// operation, or for the google perftools heap-checker. It must only
// be called when the process is about to exit, and all threads that
// might access flags are quiescent. Referencing flags after this is
// called will have unexpected consequences. This is not safe to run
// when multiple threads might be running: the function is
// thread-hostile.
extern GFLAGS_DLL_DECL void ShutDownCommandLineFlags();
// --------------------------------------------------------------------
// Now come the command line flag declaration/definition macros that
// will actually be used. They're kind of hairy. A major reason
// for this is initialization: we want people to be able to access
// variables in global constructors and have that not crash, even if
// their global constructor runs before the global constructor here.
// (Obviously, we can't guarantee the flags will have the correct
// default value in that case, but at least accessing them is safe.)
// The only way to do that is have flags point to a static buffer.
// So we make one, using a union to ensure proper alignment, and
// then use placement-new to actually set up the flag with the
// correct default value. In the same vein, we have to worry about
// flag access in global destructors, so FlagRegisterer has to be
// careful never to destroy the flag-values it constructs.
//
// Note that when we define a flag variable FLAGS_<name>, we also
// preemptively define a junk variable, FLAGS_no<name>. This is to
// cause a link-time error if someone tries to define 2 flags with
// names like "logging" and "nologging". We do this because a bool
// flag FLAG can be set from the command line to true with a "-FLAG"
// argument, and to false with a "-noFLAG" argument, and so this can
// potentially avert confusion.
//
// We also put flags into their own namespace. It is purposefully
// named in an opaque way that people should have trouble typing
// directly. The idea is that DEFINE puts the flag in the weird
// namespace, and DECLARE imports the flag from there into the current
// namespace. The net result is to force people to use DECLARE to get
// access to a flag, rather than saying "extern GFLAGS_DLL_DECL bool FLAGS_whatever;"
// or some such instead. We want this so we can put extra
// functionality (like sanity-checking) in DECLARE if we want, and
// make sure it is picked up everywhere.
//
// We also put the type of the variable in the namespace, so that
// people can't DECLARE_int32 something that they DEFINE_bool'd
// elsewhere.
class GFLAGS_DLL_DECL FlagRegisterer {
public:
// We instantiate this template ctor for all supported types,
// so it is possible to place implementation of the FlagRegisterer ctor in
// .cc file.
// Calling this constructor with unsupported type will produce linker error.
template <typename FlagType>
FlagRegisterer(const char* name,
const char* help, const char* filename,
FlagType* current_storage, FlagType* defvalue_storage);
};
// Force compiler to not generate code for the given template specialization.
#if defined(_MSC_VER) && _MSC_VER < 1800 // Visual Studio 2013 version 12.0
#define GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(type)
#else
#define GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(type) \
extern template GFLAGS_DLL_DECL FlagRegisterer::FlagRegisterer( \
const char* name, const char* help, const char* filename, \
type* current_storage, type* defvalue_storage)
#endif
// Do this for all supported flag types.
GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(bool);
GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(int32);
GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(uint32);
GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(int64);
GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(uint64);
GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(double);
GFLAGS_DECLARE_FLAG_REGISTERER_CTOR(std::string);
#undef GFLAGS_DECLARE_FLAG_REGISTERER_CTOR
// If your application #defines STRIP_FLAG_HELP to a non-zero value
// before #including this file, we remove the help message from the
// binary file. This can reduce the size of the resulting binary
// somewhat, and may also be useful for security reasons.
extern GFLAGS_DLL_DECL const char kStrippedFlagHelp[];
} // namespace GFLAGS_NAMESPACE
#ifndef SWIG // In swig, ignore the main flag declarations
#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0
// Need this construct to avoid the 'defined but not used' warning.
#define MAYBE_STRIPPED_HELP(txt) \
(false ? (txt) : GFLAGS_NAMESPACE::kStrippedFlagHelp)
#else
#define MAYBE_STRIPPED_HELP(txt) txt
#endif
// Each command-line flag has two variables associated with it: one
// with the current value, and one with the default value. However,
// we have a third variable, which is where value is assigned; it's a
// constant. This guarantees that FLAG_##value is initialized at
// static initialization time (e.g. before program-start) rather than
// than global construction time (which is after program-start but
// before main), at least when 'value' is a compile-time constant. We
// use a small trick for the "default value" variable, and call it
// FLAGS_no<name>. This serves the second purpose of assuring a
// compile error if someone tries to define a flag named no<name>
// which is illegal (--foo and --nofoo both affect the "foo" flag).
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
namespace fL##shorttype { \
static const type FLAGS_nono##name = value; \
/* We always want to export defined variables, dll or no */ \
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \
static type FLAGS_no##name = FLAGS_nono##name; \
static GFLAGS_NAMESPACE::FlagRegisterer o_##name( \
#name, MAYBE_STRIPPED_HELP(help), __FILE__, \
&FLAGS_##name, &FLAGS_no##name); \
} \
using fL##shorttype::FLAGS_##name
// For DEFINE_bool, we want to do the extra check that the passed-in
// value is actually a bool, and not a string or something that can be
// coerced to a bool. These declarations (no definition needed!) will
// help us do that, and never evaluate From, which is important.
// We'll use 'sizeof(IsBool(val))' to distinguish. This code requires
// that the compiler have different sizes for bool & double. Since
// this is not guaranteed by the standard, we check it with a
// COMPILE_ASSERT.
namespace fLB {
struct CompileAssert {};
typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[
(sizeof(double) != sizeof(bool)) ? 1 : -1];
template<typename From> double GFLAGS_DLL_DECL IsBoolFlag(const From& from);
GFLAGS_DLL_DECL bool IsBoolFlag(bool from);
} // namespace fLB
// Here are the actual DEFINE_*-macros. The respective DECLARE_*-macros
// are in a separate include, gflags_declare.h, for reducing
// the physical transitive size for DECLARE use.
#define DEFINE_bool(name, val, txt) \
namespace fLB { \
typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \
(sizeof(::fLB::IsBoolFlag(val)) != sizeof(double))? 1: -1]; \
} \
DEFINE_VARIABLE(bool, B, name, val, txt)
#define DEFINE_int32(name, val, txt) \
DEFINE_VARIABLE(GFLAGS_NAMESPACE::int32, I, \
name, val, txt)
#define DEFINE_uint32(name,val, txt) \
DEFINE_VARIABLE(GFLAGS_NAMESPACE::uint32, U, \
name, val, txt)
#define DEFINE_int64(name, val, txt) \
DEFINE_VARIABLE(GFLAGS_NAMESPACE::int64, I64, \
name, val, txt)
#define DEFINE_uint64(name,val, txt) \
DEFINE_VARIABLE(GFLAGS_NAMESPACE::uint64, U64, \
name, val, txt)
#define DEFINE_double(name, val, txt) \
DEFINE_VARIABLE(double, D, name, val, txt)
// Strings are trickier, because they're not a POD, so we can't
// construct them at static-initialization time (instead they get
// constructed at global-constructor time, which is much later). To
// try to avoid crashes in that case, we use a char buffer to store
// the string, which we can static-initialize, and then placement-new
// into it later. It's not perfect, but the best we can do.
namespace fLS {
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
const char *value) {
return new(stringspot) clstring(value);
}
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
const clstring &value) {
return new(stringspot) clstring(value);
}
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
int value);
// Auxiliary class used to explicitly call destructor of string objects
// allocated using placement new during static program deinitialization.
// The destructor MUST be an inline function such that the explicit
// destruction occurs in the same compilation unit as the placement new.
class StringFlagDestructor {
void *current_storage_;
void *defvalue_storage_;
public:
StringFlagDestructor(void *current, void *defvalue)
: current_storage_(current), defvalue_storage_(defvalue) {}
~StringFlagDestructor() {
reinterpret_cast<clstring*>(current_storage_ )->~clstring();
reinterpret_cast<clstring*>(defvalue_storage_)->~clstring();
}
};
} // namespace fLS
// We need to define a var named FLAGS_no##name so people don't define
// --string and --nostring. And we need a temporary place to put val
// so we don't have to evaluate it twice. Two great needs that go
// great together!
// The weird 'using' + 'extern' inside the fLS namespace is to work around
// an unknown compiler bug/issue with the gcc 4.2.1 on SUSE 10. See
// http://code.google.com/p/google-gflags/issues/detail?id=20
#define DEFINE_string(name, val, txt) \
namespace fLS { \
using ::fLS::clstring; \
using ::fLS::StringFlagDestructor; \
static union { void* align; char s[sizeof(clstring)]; } s_##name[2]; \
clstring* const FLAGS_no##name = ::fLS:: \
dont_pass0toDEFINE_string(s_##name[0].s, \
val); \
static GFLAGS_NAMESPACE::FlagRegisterer o_##name( \
#name, MAYBE_STRIPPED_HELP(txt), __FILE__, \
FLAGS_no##name, new (s_##name[1].s) clstring(*FLAGS_no##name)); \
static StringFlagDestructor d_##name(s_##name[0].s, s_##name[1].s); \
extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name; \
using fLS::FLAGS_##name; \
clstring& FLAGS_##name = *FLAGS_no##name; \
} \
using fLS::FLAGS_##name
#endif // SWIG
@INCLUDE_GFLAGS_NS_H@
#endif // GFLAGS_GFLAGS_H_

766
src/gflags_completions.cc Normal file
View file

@ -0,0 +1,766 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
// Bash-style command line flag completion for C++ binaries
//
// This module implements bash-style completions. It achieves this
// goal in the following broad chunks:
//
// 1) Take a to-be-completed word, and examine it for search hints
// 2) Identify all potentially matching flags
// 2a) If there are no matching flags, do nothing.
// 2b) If all matching flags share a common prefix longer than the
// completion word, output just that matching prefix
// 3) Categorize those flags to produce a rough ordering of relevance.
// 4) Potentially trim the set of flags returned to a smaller number
// that bash is happier with
// 5) Output the matching flags in groups ordered by relevance.
// 5a) Force bash to place most-relevent groups at the top of the list
// 5b) Trim most flag's descriptions to fit on a single terminal line
#include <cstdio>
#include <cstdlib>
#include <cstring> // for strlen
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "config.h"
#include "gflags/gflags.h"
#include "gflags/gflags_completions.h"
#include "util.h"
using std::set;
using std::string;
using std::vector;
DEFINE_string(tab_completion_word, "",
"If non-empty, HandleCommandLineCompletions() will hijack the "
"process and attempt to do bash-style command line flag "
"completion on this value.");
DEFINE_int32(tab_completion_columns, 80,
"Number of columns to use in output for tab completion");
namespace GFLAGS_NAMESPACE {
namespace {
// Function prototypes and Type forward declarations. Code may be
// more easily understood if it is roughly ordered according to
// control flow, rather than by C's "declare before use" ordering
struct CompletionOptions;
struct NotableFlags;
// The entry point if flag completion is to be used.
static void PrintFlagCompletionInfo(void);
// 1) Examine search word
static void CanonicalizeCursorWordAndSearchOptions(
const string &cursor_word,
string *canonical_search_token,
CompletionOptions *options);
static bool RemoveTrailingChar(string *str, char c);
// 2) Find all matches
static void FindMatchingFlags(
const vector<CommandLineFlagInfo> &all_flags,
const CompletionOptions &options,
const string &match_token,
set<const CommandLineFlagInfo *> *all_matches,
string *longest_common_prefix);
static bool DoesSingleFlagMatch(
const CommandLineFlagInfo &flag,
const CompletionOptions &options,
const string &match_token);
// 3) Categorize matches
static void CategorizeAllMatchingFlags(
const set<const CommandLineFlagInfo *> &all_matches,
const string &search_token,
const string &module,
const string &package_dir,
NotableFlags *notable_flags);
static void TryFindModuleAndPackageDir(
const vector<CommandLineFlagInfo> &all_flags,
string *module,
string *package_dir);
// 4) Decide which flags to use
static void FinalizeCompletionOutput(
const set<const CommandLineFlagInfo *> &matching_flags,
CompletionOptions *options,
NotableFlags *notable_flags,
vector<string> *completions);
static void RetrieveUnusedFlags(
const set<const CommandLineFlagInfo *> &matching_flags,
const NotableFlags &notable_flags,
set<const CommandLineFlagInfo *> *unused_flags);
// 5) Output matches
static void OutputSingleGroupWithLimit(
const set<const CommandLineFlagInfo *> &group,
const string &line_indentation,
const string &header,
const string &footer,
bool long_output_format,
int *remaining_line_limit,
size_t *completion_elements_added,
vector<string> *completions);
// (helpers for #5)
static string GetShortFlagLine(
const string &line_indentation,
const CommandLineFlagInfo &info);
static string GetLongFlagLine(
const string &line_indentation,
const CommandLineFlagInfo &info);
//
// Useful types
// Try to deduce the intentions behind this completion attempt. Return the
// canonical search term in 'canonical_search_token'. Binary search options
// are returned in the various booleans, which should all have intuitive
// semantics, possibly except:
// - return_all_matching_flags: Generally, we'll trim the number of
// returned candidates to some small number, showing those that are
// most likely to be useful first. If this is set, however, the user
// really does want us to return every single flag as an option.
// - force_no_update: Any time we output lines, all of which share a
// common prefix, bash will 'helpfuly' not even bother to show the
// output, instead changing the current word to be that common prefix.
// If it's clear this shouldn't happen, we'll set this boolean
struct CompletionOptions {
bool flag_name_substring_search;
bool flag_location_substring_search;
bool flag_description_substring_search;
bool return_all_matching_flags;
bool force_no_update;
CompletionOptions(): flag_name_substring_search(false),
flag_location_substring_search(false),
flag_description_substring_search(false),
return_all_matching_flags(false),
force_no_update(false) { }
};
// Notable flags are flags that are special or preferred for some
// reason. For example, flags that are defined in the binary's module
// are expected to be much more relevant than flags defined in some
// other random location. These sets are specified roughly in precedence
// order. Once a flag is placed in one of these 'higher' sets, it won't
// be placed in any of the 'lower' sets.
struct NotableFlags {
typedef set<const CommandLineFlagInfo *> FlagSet;
FlagSet perfect_match_flag;
FlagSet module_flags; // Found in module file
FlagSet package_flags; // Found in same directory as module file
FlagSet most_common_flags; // One of the XXX most commonly supplied flags
FlagSet subpackage_flags; // Found in subdirectories of package
};
//
// Tab completion implementation - entry point
static void PrintFlagCompletionInfo(void) {
string cursor_word = FLAGS_tab_completion_word;
string canonical_token;
CompletionOptions options = CompletionOptions();
CanonicalizeCursorWordAndSearchOptions(
cursor_word,
&canonical_token,
&options);
DVLOG(1) << "Identified canonical_token: '" << canonical_token << "'";
vector<CommandLineFlagInfo> all_flags;
set<const CommandLineFlagInfo *> matching_flags;
GetAllFlags(&all_flags);
DVLOG(2) << "Found " << all_flags.size() << " flags overall";
string longest_common_prefix;
FindMatchingFlags(
all_flags,
options,
canonical_token,
&matching_flags,
&longest_common_prefix);
DVLOG(1) << "Identified " << matching_flags.size() << " matching flags";
DVLOG(1) << "Identified " << longest_common_prefix
<< " as longest common prefix.";
if (longest_common_prefix.size() > canonical_token.size()) {
// There's actually a shared common prefix to all matching flags,
// so may as well output that and quit quickly.
DVLOG(1) << "The common prefix '" << longest_common_prefix
<< "' was longer than the token '" << canonical_token
<< "'. Returning just this prefix for completion.";
fprintf(stdout, "--%s", longest_common_prefix.c_str());
return;
}
if (matching_flags.empty()) {
VLOG(1) << "There were no matching flags, returning nothing.";
return;
}
string module;
string package_dir;
TryFindModuleAndPackageDir(all_flags, &module, &package_dir);
DVLOG(1) << "Identified module: '" << module << "'";
DVLOG(1) << "Identified package_dir: '" << package_dir << "'";
NotableFlags notable_flags;
CategorizeAllMatchingFlags(
matching_flags,
canonical_token,
module,
package_dir,
&notable_flags);
DVLOG(2) << "Categorized matching flags:";
DVLOG(2) << " perfect_match: " << notable_flags.perfect_match_flag.size();
DVLOG(2) << " module: " << notable_flags.module_flags.size();
DVLOG(2) << " package: " << notable_flags.package_flags.size();
DVLOG(2) << " most common: " << notable_flags.most_common_flags.size();
DVLOG(2) << " subpackage: " << notable_flags.subpackage_flags.size();
vector<string> completions;
FinalizeCompletionOutput(
matching_flags,
&options,
&notable_flags,
&completions);
if (options.force_no_update)
completions.push_back("~");
DVLOG(1) << "Finalized with " << completions.size()
<< " chosen completions";
for (vector<string>::const_iterator it = completions.begin();
it != completions.end();
++it) {
DVLOG(9) << " Completion entry: '" << *it << "'";
fprintf(stdout, "%s\n", it->c_str());
}
}
// 1) Examine search word (and helper method)
static void CanonicalizeCursorWordAndSearchOptions(
const string &cursor_word,
string *canonical_search_token,
CompletionOptions *options) {
*canonical_search_token = cursor_word;
if (canonical_search_token->empty()) return;
// Get rid of leading quotes and dashes in the search term
if ((*canonical_search_token)[0] == '"')
*canonical_search_token = canonical_search_token->substr(1);
while ((*canonical_search_token)[0] == '-')
*canonical_search_token = canonical_search_token->substr(1);
options->flag_name_substring_search = false;
options->flag_location_substring_search = false;
options->flag_description_substring_search = false;
options->return_all_matching_flags = false;
options->force_no_update = false;
// Look for all search options we can deduce now. Do this by walking
// backwards through the term, looking for up to three '?' and up to
// one '+' as suffixed characters. Consume them if found, and remove
// them from the canonical search token.
int found_question_marks = 0;
int found_plusses = 0;
while (true) {
if (found_question_marks < 3 &&
RemoveTrailingChar(canonical_search_token, '?')) {
++found_question_marks;
continue;
}
if (found_plusses < 1 &&
RemoveTrailingChar(canonical_search_token, '+')) {
++found_plusses;
continue;
}
break;
}
if (found_question_marks > 2) options->flag_description_substring_search = true;
if (found_question_marks > 1) options->flag_location_substring_search = true;
if (found_question_marks > 0) options->flag_name_substring_search = true;
options->return_all_matching_flags = (found_plusses > 0);
}
// Returns true if a char was removed
static bool RemoveTrailingChar(string *str, char c) {
if (str->empty()) return false;
if ((*str)[str->size() - 1] == c) {
*str = str->substr(0, str->size() - 1);
return true;
}
return false;
}
// 2) Find all matches (and helper methods)
static void FindMatchingFlags(
const vector<CommandLineFlagInfo> &all_flags,
const CompletionOptions &options,
const string &match_token,
set<const CommandLineFlagInfo *> *all_matches,
string *longest_common_prefix) {
all_matches->clear();
bool first_match = true;
for (vector<CommandLineFlagInfo>::const_iterator it = all_flags.begin();
it != all_flags.end();
++it) {
if (DoesSingleFlagMatch(*it, options, match_token)) {
all_matches->insert(&*it);
if (first_match) {
first_match = false;
*longest_common_prefix = it->name;
} else {
if (longest_common_prefix->empty() || it->name.empty()) {
longest_common_prefix->clear();
continue;
}
string::size_type pos = 0;
while (pos < longest_common_prefix->size() &&
pos < it->name.size() &&
(*longest_common_prefix)[pos] == it->name[pos])
++pos;
longest_common_prefix->erase(pos);
}
}
}
}
// Given the set of all flags, the parsed match options, and the
// canonical search token, produce the set of all candidate matching
// flags for subsequent analysis or filtering.
static bool DoesSingleFlagMatch(
const CommandLineFlagInfo &flag,
const CompletionOptions &options,
const string &match_token) {
// Is there a prefix match?
string::size_type pos = flag.name.find(match_token);
if (pos == 0) return true;
// Is there a substring match if we want it?
if (options.flag_name_substring_search &&
pos != string::npos)
return true;
// Is there a location match if we want it?
if (options.flag_location_substring_search &&
flag.filename.find(match_token) != string::npos)
return true;
// TODO(user): All searches should probably be case-insensitive
// (especially this one...)
if (options.flag_description_substring_search &&
flag.description.find(match_token) != string::npos)
return true;
return false;
}
// 3) Categorize matches (and helper method)
// Given a set of matching flags, categorize them by
// likely relevance to this specific binary
static void CategorizeAllMatchingFlags(
const set<const CommandLineFlagInfo *> &all_matches,
const string &search_token,
const string &module, // empty if we couldn't find any
const string &package_dir, // empty if we couldn't find any
NotableFlags *notable_flags) {
notable_flags->perfect_match_flag.clear();
notable_flags->module_flags.clear();
notable_flags->package_flags.clear();
notable_flags->most_common_flags.clear();
notable_flags->subpackage_flags.clear();
for (set<const CommandLineFlagInfo *>::const_iterator it =
all_matches.begin();
it != all_matches.end();
++it) {
DVLOG(2) << "Examining match '" << (*it)->name << "'";
DVLOG(7) << " filename: '" << (*it)->filename << "'";
string::size_type pos = string::npos;
if (!package_dir.empty())
pos = (*it)->filename.find(package_dir);
string::size_type slash = string::npos;
if (pos != string::npos) // candidate for package or subpackage match
slash = (*it)->filename.find(
PATH_SEPARATOR,
pos + package_dir.size() + 1);
if ((*it)->name == search_token) {
// Exact match on some flag's name
notable_flags->perfect_match_flag.insert(*it);
DVLOG(3) << "Result: perfect match";
} else if (!module.empty() && (*it)->filename == module) {
// Exact match on module filename
notable_flags->module_flags.insert(*it);
DVLOG(3) << "Result: module match";
} else if (!package_dir.empty() &&
pos != string::npos && slash == string::npos) {
// In the package, since there was no slash after the package portion
notable_flags->package_flags.insert(*it);
DVLOG(3) << "Result: package match";
} else if (!package_dir.empty() &&
pos != string::npos && slash != string::npos) {
// In a subdirectory of the package
notable_flags->subpackage_flags.insert(*it);
DVLOG(3) << "Result: subpackage match";
}
DVLOG(3) << "Result: not special match";
}
}
static void PushNameWithSuffix(vector<string>* suffixes, const char* suffix) {
suffixes->push_back(
StringPrintf("/%s%s", ProgramInvocationShortName(), suffix));
}
static void TryFindModuleAndPackageDir(
const vector<CommandLineFlagInfo> &all_flags,
string *module,
string *package_dir) {
module->clear();
package_dir->clear();
vector<string> suffixes;
// TODO(user): There's some inherant ambiguity here - multiple directories
// could share the same trailing folder and file structure (and even worse,
// same file names), causing us to be unsure as to which of the two is the
// actual package for this binary. In this case, we'll arbitrarily choose.
PushNameWithSuffix(&suffixes, ".");
PushNameWithSuffix(&suffixes, "-main.");
PushNameWithSuffix(&suffixes, "_main.");
// These four are new but probably merited?
PushNameWithSuffix(&suffixes, "-test.");
PushNameWithSuffix(&suffixes, "_test.");
PushNameWithSuffix(&suffixes, "-unittest.");
PushNameWithSuffix(&suffixes, "_unittest.");
for (vector<CommandLineFlagInfo>::const_iterator it = all_flags.begin();
it != all_flags.end();
++it) {
for (vector<string>::const_iterator suffix = suffixes.begin();
suffix != suffixes.end();
++suffix) {
// TODO(user): Make sure the match is near the end of the string
if (it->filename.find(*suffix) != string::npos) {
*module = it->filename;
string::size_type sep = it->filename.rfind(PATH_SEPARATOR);
*package_dir = it->filename.substr(0, (sep == string::npos) ? 0 : sep);
return;
}
}
}
}
// Can't specialize template type on a locally defined type. Silly C++...
struct DisplayInfoGroup {
const char* header;
const char* footer;
set<const CommandLineFlagInfo *> *group;
int SizeInLines() const {
int size_in_lines = static_cast<int>(group->size()) + 1;
if (strlen(header) > 0) {
size_in_lines++;
}
if (strlen(footer) > 0) {
size_in_lines++;
}
return size_in_lines;
}
};
// 4) Finalize and trim output flag set
static void FinalizeCompletionOutput(
const set<const CommandLineFlagInfo *> &matching_flags,
CompletionOptions *options,
NotableFlags *notable_flags,
vector<string> *completions) {
// We want to output lines in groups. Each group needs to be indented
// the same to keep its lines together. Unless otherwise required,
// only 99 lines should be output to prevent bash from harassing the
// user.
// First, figure out which output groups we'll actually use. For each
// nonempty group, there will be ~3 lines of header & footer, plus all
// output lines themselves.
int max_desired_lines = // "999999 flags should be enough for anyone. -dave"
(options->return_all_matching_flags ? 999999 : 98);
int lines_so_far = 0;
vector<DisplayInfoGroup> output_groups;
bool perfect_match_found = false;
if (!notable_flags->perfect_match_flag.empty()) {
perfect_match_found = true;
DisplayInfoGroup group =
{ "",
"==========",
&notable_flags->perfect_match_flag };
lines_so_far += group.SizeInLines();
output_groups.push_back(group);
}
if (lines_so_far < max_desired_lines &&
!notable_flags->module_flags.empty()) {
DisplayInfoGroup group = {
"-* Matching module flags *-",
"===========================",
&notable_flags->module_flags };
lines_so_far += group.SizeInLines();
output_groups.push_back(group);
}
if (lines_so_far < max_desired_lines &&
!notable_flags->package_flags.empty()) {
DisplayInfoGroup group = {
"-* Matching package flags *-",
"============================",
&notable_flags->package_flags };
lines_so_far += group.SizeInLines();
output_groups.push_back(group);
}
if (lines_so_far < max_desired_lines &&
!notable_flags->most_common_flags.empty()) {
DisplayInfoGroup group = {
"-* Commonly used flags *-",
"=========================",
&notable_flags->most_common_flags };
lines_so_far += group.SizeInLines();
output_groups.push_back(group);
}
if (lines_so_far < max_desired_lines &&
!notable_flags->subpackage_flags.empty()) {
DisplayInfoGroup group = {
"-* Matching sub-package flags *-",
"================================",
&notable_flags->subpackage_flags };
lines_so_far += group.SizeInLines();
output_groups.push_back(group);
}
set<const CommandLineFlagInfo *> obscure_flags; // flags not notable
if (lines_so_far < max_desired_lines) {
RetrieveUnusedFlags(matching_flags, *notable_flags, &obscure_flags);
if (!obscure_flags.empty()) {
DisplayInfoGroup group = {
"-* Other flags *-",
"",
&obscure_flags };
lines_so_far += group.SizeInLines();
output_groups.push_back(group);
}
}
// Second, go through each of the chosen output groups and output
// as many of those flags as we can, while remaining below our limit
int remaining_lines = max_desired_lines;
size_t completions_output = 0;
int indent = static_cast<int>(output_groups.size()) - 1;
for (vector<DisplayInfoGroup>::const_iterator it =
output_groups.begin();
it != output_groups.end();
++it, --indent) {
OutputSingleGroupWithLimit(
*it->group, // group
string(indent, ' '), // line indentation
string(it->header), // header
string(it->footer), // footer
perfect_match_found, // long format
&remaining_lines, // line limit - reduces this by number printed
&completions_output, // completions (not lines) added
completions); // produced completions
perfect_match_found = false;
}
if (completions_output != matching_flags.size()) {
options->force_no_update = false;
completions->push_back("~ (Remaining flags hidden) ~");
} else {
options->force_no_update = true;
}
}
static void RetrieveUnusedFlags(
const set<const CommandLineFlagInfo *> &matching_flags,
const NotableFlags &notable_flags,
set<const CommandLineFlagInfo *> *unused_flags) {
// Remove from 'matching_flags' set all members of the sets of
// flags we've already printed (specifically, those in notable_flags)
for (set<const CommandLineFlagInfo *>::const_iterator it =
matching_flags.begin();
it != matching_flags.end();
++it) {
if (notable_flags.perfect_match_flag.count(*it) ||
notable_flags.module_flags.count(*it) ||
notable_flags.package_flags.count(*it) ||
notable_flags.most_common_flags.count(*it) ||
notable_flags.subpackage_flags.count(*it))
continue;
unused_flags->insert(*it);
}
}
// 5) Output matches (and helper methods)
static void OutputSingleGroupWithLimit(
const set<const CommandLineFlagInfo *> &group,
const string &line_indentation,
const string &header,
const string &footer,
bool long_output_format,
int *remaining_line_limit,
size_t *completion_elements_output,
vector<string> *completions) {
if (group.empty()) return;
if (!header.empty()) {
if (*remaining_line_limit < 2) return;
*remaining_line_limit -= 2;
completions->push_back(line_indentation + header);
completions->push_back(line_indentation + string(header.size(), '-'));
}
for (set<const CommandLineFlagInfo *>::const_iterator it = group.begin();
it != group.end() && *remaining_line_limit > 0;
++it) {
--*remaining_line_limit;
++*completion_elements_output;
completions->push_back(
(long_output_format
? GetLongFlagLine(line_indentation, **it)
: GetShortFlagLine(line_indentation, **it)));
}
if (!footer.empty()) {
if (*remaining_line_limit < 1) return;
--*remaining_line_limit;
completions->push_back(line_indentation + footer);
}
}
static string GetShortFlagLine(
const string &line_indentation,
const CommandLineFlagInfo &info) {
string prefix;
bool is_string = (info.type == "string");
SStringPrintf(&prefix, "%s--%s [%s%s%s] ",
line_indentation.c_str(),
info.name.c_str(),
(is_string ? "'" : ""),
info.default_value.c_str(),
(is_string ? "'" : ""));
int remainder =
FLAGS_tab_completion_columns - static_cast<int>(prefix.size());
string suffix;
if (remainder > 0)
suffix =
(static_cast<int>(info.description.size()) > remainder ?
(info.description.substr(0, remainder - 3) + "...").c_str() :
info.description.c_str());
return prefix + suffix;
}
static string GetLongFlagLine(
const string &line_indentation,
const CommandLineFlagInfo &info) {
string output = DescribeOneFlag(info);
// Replace '-' with '--', and remove trailing newline before appending
// the module definition location.
string old_flagname = "-" + info.name;
output.replace(
output.find(old_flagname),
old_flagname.size(),
"-" + old_flagname);
// Stick a newline and indentation in front of the type and default
// portions of DescribeOneFlag()s description
static const char kNewlineWithIndent[] = "\n ";
output.replace(output.find(" type:"), 1, string(kNewlineWithIndent));
output.replace(output.find(" default:"), 1, string(kNewlineWithIndent));
output = StringPrintf("%s Details for '--%s':\n"
"%s defined: %s",
line_indentation.c_str(),
info.name.c_str(),
output.c_str(),
info.filename.c_str());
// Eliminate any doubled newlines that crept in. Specifically, if
// DescribeOneFlag() decided to break the line just before "type"
// or "default", we don't want to introduce an extra blank line
static const string line_of_spaces(FLAGS_tab_completion_columns, ' ');
static const char kDoubledNewlines[] = "\n \n";
for (string::size_type newlines = output.find(kDoubledNewlines);
newlines != string::npos;
newlines = output.find(kDoubledNewlines))
// Replace each 'doubled newline' with a single newline
output.replace(newlines, sizeof(kDoubledNewlines) - 1, string("\n"));
for (string::size_type newline = output.find('\n');
newline != string::npos;
newline = output.find('\n')) {
int newline_pos = static_cast<int>(newline) % FLAGS_tab_completion_columns;
int missing_spaces = FLAGS_tab_completion_columns - newline_pos;
output.replace(newline, 1, line_of_spaces, 1, missing_spaces);
}
return output;
}
} // anonymous
void HandleCommandLineCompletions(void) {
if (FLAGS_tab_completion_word.empty()) return;
PrintFlagCompletionInfo();
gflags_exitfunc(0);
}
} // namespace GFLAGS_NAMESPACE

121
src/gflags_completions.h.in Normal file
View file

@ -0,0 +1,121 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
//
// Implement helpful bash-style command line flag completions
//
// ** Functional API:
// HandleCommandLineCompletions() should be called early during
// program startup, but after command line flag code has been
// initialized, such as the beginning of HandleCommandLineHelpFlags().
// It checks the value of the flag --tab_completion_word. If this
// flag is empty, nothing happens here. If it contains a string,
// however, then HandleCommandLineCompletions() will hijack the
// process, attempting to identify the intention behind this
// completion. Regardless of the outcome of this deduction, the
// process will be terminated, similar to --helpshort flag
// handling.
//
// ** Overview of Bash completions:
// Bash can be told to programmatically determine completions for the
// current 'cursor word'. It does this by (in this case) invoking a
// command with some additional arguments identifying the command
// being executed, the word being completed, and the previous word
// (if any). Bash then expects a sequence of output lines to be
// printed to stdout. If these lines all contain a common prefix
// longer than the cursor word, bash will replace the cursor word
// with that common prefix, and display nothing. If there isn't such
// a common prefix, bash will display the lines in pages using 'more'.
//
// ** Strategy taken for command line completions:
// If we can deduce either the exact flag intended, or a common flag
// prefix, we'll output exactly that. Otherwise, if information
// must be displayed to the user, we'll take the opportunity to add
// some helpful information beyond just the flag name (specifically,
// we'll include the default flag value and as much of the flag's
// description as can fit on a single terminal line width, as specified
// by the flag --tab_completion_columns). Furthermore, we'll try to
// make bash order the output such that the most useful or relevant
// flags are the most likely to be shown at the top.
//
// ** Additional features:
// To assist in finding that one really useful flag, substring matching
// was implemented. Before pressing a <TAB> to get completion for the
// current word, you can append one or more '?' to the flag to do
// substring matching. Here's the semantics:
// --foo<TAB> Show me all flags with names prefixed by 'foo'
// --foo?<TAB> Show me all flags with 'foo' somewhere in the name
// --foo??<TAB> Same as prior case, but also search in module
// definition path for 'foo'
// --foo???<TAB> Same as prior case, but also search in flag
// descriptions for 'foo'
// Finally, we'll trim the output to a relatively small number of
// flags to keep bash quiet about the verbosity of output. If one
// really wanted to see all possible matches, appending a '+' to the
// search word will force the exhaustive list of matches to be printed.
//
// ** How to have bash accept completions from a binary:
// Bash requires that it be informed about each command that programmatic
// completion should be enabled for. Example addition to a .bashrc
// file would be (your path to gflags_completions.sh file may differ):
/*
$ complete -o bashdefault -o default -o nospace -C \
'/home/build/eng/bash/bash_completions.sh --tab_completion_columns $COLUMNS' \
time env binary_name another_binary [...]
*/
// This would allow the following to work:
// $ /path/to/binary_name --vmodule<TAB>
// Or:
// $ ./bin/path/another_binary --gfs_u<TAB>
// (etc)
//
// Sadly, it appears that bash gives no easy way to force this behavior for
// all commands. That's where the "time" in the above example comes in.
// If you haven't specifically added a command to the list of completion
// supported commands, you can still get completions by prefixing the
// entire command with "env".
// $ env /some/brand/new/binary --vmod<TAB>
// Assuming that "binary" is a newly compiled binary, this should still
// produce the expected completion output.
#ifndef GFLAGS_COMPLETIONS_H_
#define GFLAGS_COMPLETIONS_H_
namespace @GFLAGS_NAMESPACE@ {
extern void HandleCommandLineCompletions(void);
}
#endif // GFLAGS_COMPLETIONS_H_

117
src/gflags_completions.sh Executable file
View file

@ -0,0 +1,117 @@
#!/bin/bash
# Copyright (c) 2008, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ---
# Author: Dave Nicponski
#
# This script is invoked by bash in response to a matching compspec. When
# this happens, bash calls this script using the command shown in the -C
# block of the complete entry, but also appends 3 arguments. They are:
# - The command being used for completion
# - The word being completed
# - The word preceding the completion word.
#
# Here's an example of how you might use this script:
# $ complete -o bashdefault -o default -o nospace -C \
# '/usr/local/bin/gflags_completions.sh --tab_completion_columns $COLUMNS' \
# time env binary_name another_binary [...]
# completion_word_index gets the index of the (N-1)th argument for
# this command line. completion_word gets the actual argument from
# this command line at the (N-1)th position
completion_word_index="$(($# - 1))"
completion_word="${!completion_word_index}"
# TODO(user): Replace this once gflags_completions.cc has
# a bool parameter indicating unambiguously to hijack the process for
# completion purposes.
if [ -z "$completion_word" ]; then
# Until an empty value for the completion word stops being misunderstood
# by binaries, don't actually execute the binary or the process
# won't be hijacked!
exit 0
fi
# binary_index gets the index of the command being completed (which bash
# places in the (N-2)nd position. binary gets the actual command from
# this command line at that (N-2)nd position
binary_index="$(($# - 2))"
binary="${!binary_index}"
# For completions to be universal, we may have setup the compspec to
# trigger on 'harmless pass-through' commands, like 'time' or 'env'.
# If the command being completed is one of those two, we'll need to
# identify the actual command being executed. To do this, we need
# the actual command line that the <TAB> was pressed on. Bash helpfully
# places this in the $COMP_LINE variable.
if [ "$binary" == "time" ] || [ "$binary" == "env" ]; then
# we'll assume that the first 'argument' is actually the
# binary
# TODO(user): This is not perfect - the 'env' command, for instance,
# is allowed to have options between the 'env' and 'the command to
# be executed'. For example, consider:
# $ env FOO="bar" bin/do_something --help<TAB>
# In this case, we'll mistake the FOO="bar" portion as the binary.
# Perhaps we should continuing consuming leading words until we
# either run out of words, or find a word that is a valid file
# marked as executable. I can't think of any reason this wouldn't
# work.
# Break up the 'original command line' (not this script's command line,
# rather the one the <TAB> was pressed on) and find the second word.
parts=( ${COMP_LINE} )
binary=${parts[1]}
fi
# Build the command line to use for completion. Basically it involves
# passing through all the arguments given to this script (except the 3
# that bash added), and appending a '--tab_completion_word "WORD"' to
# the arguments.
params=""
for ((i=1; i<=$(($# - 3)); ++i)); do
params="$params \"${!i}\"";
done
params="$params --tab_completion_word \"$completion_word\""
# TODO(user): Perhaps stash the output in a temporary file somewhere
# in /tmp, and only cat it to stdout if the command returned a success
# code, to prevent false positives
# If we think we have a reasonable command to execute, then execute it
# and hope for the best.
candidate=$(type -p "$binary")
if [ ! -z "$candidate" ]; then
eval "$candidate 2>/dev/null $params"
elif [ -f "$binary" ] && [ -x "$binary" ]; then
eval "$binary 2>/dev/null $params"
fi

156
src/gflags_declare.h.in Normal file
View file

@ -0,0 +1,156 @@
// Copyright (c) 1999, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
//
// Revamped and reorganized by Craig Silverstein
//
// This is the file that should be included by any file which declares
// command line flag.
#ifndef GFLAGS_DECLARE_H_
#define GFLAGS_DECLARE_H_
// ---------------------------------------------------------------------------
// Namespace of gflags library symbols.
#define GFLAGS_NAMESPACE @GFLAGS_NAMESPACE@
// ---------------------------------------------------------------------------
// Windows DLL import/export.
// Whether gflags library is a DLL.
//
// Set to 1 by default when the shared gflags library was built on Windows.
// Must be overwritten when this header file is used with the optionally also
// built static library instead; set by CMake's INTERFACE_COMPILE_DEFINITIONS.
#ifndef GFLAGS_IS_A_DLL
# define GFLAGS_IS_A_DLL @GFLAGS_IS_A_DLL@
#endif
// We always want to import the symbols of the gflags library.
#ifndef GFLAGS_DLL_DECL
# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
# define GFLAGS_DLL_DECL __declspec(dllimport)
# elif defined(__GNUC__) && __GNUC__ >= 4
# define GFLAGS_DLL_DECL __attribute__((visibility("default")))
# else
# define GFLAGS_DLL_DECL
# endif
#endif
// We always want to import variables declared in user code.
#ifndef GFLAGS_DLL_DECLARE_FLAG
# if GFLAGS_IS_A_DLL && defined(_MSC_VER)
# define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport)
# elif defined(__GNUC__) && __GNUC__ >= 4
# define GFLAGS_DLL_DECLARE_FLAG __attribute__((visibility("default")))
# else
# define GFLAGS_DLL_DECLARE_FLAG
# endif
#endif
// ---------------------------------------------------------------------------
// Flag types
#include <string>
#if @HAVE_STDINT_H@
# include <stdint.h> // the normal place uint32_t is defined
#elif @HAVE_SYS_TYPES_H@
# include <sys/types.h> // the normal place u_int32_t is defined
#elif @HAVE_INTTYPES_H@
# include <inttypes.h> // a third place for uint32_t or u_int32_t
#endif
namespace GFLAGS_NAMESPACE {
#if @GFLAGS_INTTYPES_FORMAT_C99@ // C99
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
#elif @GFLAGS_INTTYPES_FORMAT_BSD@ // BSD
typedef int32_t int32;
typedef u_int32_t uint32;
typedef int64_t int64;
typedef u_int64_t uint64;
#elif @GFLAGS_INTTYPES_FORMAT_VC7@ // Windows
typedef __int32 int32;
typedef unsigned __int32 uint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
#else
# error Do not know how to define a 32-bit integer quantity on your system
#endif
} // namespace GFLAGS_NAMESPACE
namespace fLS {
// The meaning of "string" might be different between now and when the
// macros below get invoked (e.g., if someone is experimenting with
// other string implementations that get defined after this file is
// included). Save the current meaning now and use it in the macros.
typedef std::string clstring;
} // namespace fLS
#define DECLARE_VARIABLE(type, shorttype, name) \
/* We always want to import declared variables, dll or no */ \
namespace fL##shorttype { extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; } \
using fL##shorttype::FLAGS_##name
#define DECLARE_bool(name) \
DECLARE_VARIABLE(bool, B, name)
#define DECLARE_int32(name) \
DECLARE_VARIABLE(::GFLAGS_NAMESPACE::int32, I, name)
#define DECLARE_uint32(name) \
DECLARE_VARIABLE(::GFLAGS_NAMESPACE::uint32, U, name)
#define DECLARE_int64(name) \
DECLARE_VARIABLE(::GFLAGS_NAMESPACE::int64, I64, name)
#define DECLARE_uint64(name) \
DECLARE_VARIABLE(::GFLAGS_NAMESPACE::uint64, U64, name)
#define DECLARE_double(name) \
DECLARE_VARIABLE(double, D, name)
#define DECLARE_string(name) \
/* We always want to import declared variables, dll or no */ \
namespace fLS { \
extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; \
} \
using fLS::FLAGS_##name
#endif // GFLAGS_DECLARE_H_

102
src/gflags_ns.h.in Normal file
View file

@ -0,0 +1,102 @@
// Copyright (c) 2014, Andreas Schuh
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -----------------------------------------------------------------------------
// Imports the gflags library symbols into an alternative/deprecated namespace.
#ifndef GFLAGS_GFLAGS_H_
# error The internal header gflags_@ns@.h may only be included by gflags.h
#endif
#ifndef GFLAGS_NS_@NS@_H_
#define GFLAGS_NS_@NS@_H_
namespace @ns@ {
using GFLAGS_NAMESPACE::int32;
using GFLAGS_NAMESPACE::uint32;
using GFLAGS_NAMESPACE::int64;
using GFLAGS_NAMESPACE::uint64;
using GFLAGS_NAMESPACE::RegisterFlagValidator;
using GFLAGS_NAMESPACE::CommandLineFlagInfo;
using GFLAGS_NAMESPACE::GetAllFlags;
using GFLAGS_NAMESPACE::ShowUsageWithFlags;
using GFLAGS_NAMESPACE::ShowUsageWithFlagsRestrict;
using GFLAGS_NAMESPACE::DescribeOneFlag;
using GFLAGS_NAMESPACE::SetArgv;
using GFLAGS_NAMESPACE::GetArgvs;
using GFLAGS_NAMESPACE::GetArgv;
using GFLAGS_NAMESPACE::GetArgv0;
using GFLAGS_NAMESPACE::GetArgvSum;
using GFLAGS_NAMESPACE::ProgramInvocationName;
using GFLAGS_NAMESPACE::ProgramInvocationShortName;
using GFLAGS_NAMESPACE::ProgramUsage;
using GFLAGS_NAMESPACE::VersionString;
using GFLAGS_NAMESPACE::GetCommandLineOption;
using GFLAGS_NAMESPACE::GetCommandLineFlagInfo;
using GFLAGS_NAMESPACE::GetCommandLineFlagInfoOrDie;
using GFLAGS_NAMESPACE::FlagSettingMode;
using GFLAGS_NAMESPACE::SET_FLAGS_VALUE;
using GFLAGS_NAMESPACE::SET_FLAG_IF_DEFAULT;
using GFLAGS_NAMESPACE::SET_FLAGS_DEFAULT;
using GFLAGS_NAMESPACE::SetCommandLineOption;
using GFLAGS_NAMESPACE::SetCommandLineOptionWithMode;
using GFLAGS_NAMESPACE::FlagSaver;
using GFLAGS_NAMESPACE::CommandlineFlagsIntoString;
using GFLAGS_NAMESPACE::ReadFlagsFromString;
using GFLAGS_NAMESPACE::AppendFlagsIntoFile;
using GFLAGS_NAMESPACE::ReadFromFlagsFile;
using GFLAGS_NAMESPACE::BoolFromEnv;
using GFLAGS_NAMESPACE::Int32FromEnv;
using GFLAGS_NAMESPACE::Uint32FromEnv;
using GFLAGS_NAMESPACE::Int64FromEnv;
using GFLAGS_NAMESPACE::Uint64FromEnv;
using GFLAGS_NAMESPACE::DoubleFromEnv;
using GFLAGS_NAMESPACE::StringFromEnv;
using GFLAGS_NAMESPACE::SetUsageMessage;
using GFLAGS_NAMESPACE::SetVersionString;
using GFLAGS_NAMESPACE::ParseCommandLineNonHelpFlags;
using GFLAGS_NAMESPACE::HandleCommandLineHelpFlags;
using GFLAGS_NAMESPACE::AllowCommandLineReparsing;
using GFLAGS_NAMESPACE::ReparseCommandLineNonHelpFlags;
using GFLAGS_NAMESPACE::ShutDownCommandLineFlags;
using GFLAGS_NAMESPACE::FlagRegisterer;
#ifndef SWIG
using GFLAGS_NAMESPACE::ParseCommandLineFlags;
#endif
} // namespace @ns@
#endif // GFLAGS_NS_@NS@_H_

View file

@ -1,4 +1,4 @@
// Copyright (c) 2006, Google Inc.
// Copyright (c) 1999, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -28,7 +28,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// Author: Ray Sidney
//
// Revamped and reorganized by Craig Silverstein
//
// This file contains code for handling the 'reporting' flags. These
@ -37,10 +37,10 @@
// reporting flags, but we also have flags like --helpxml, etc.
//
// There's only one function that's meant to be called externally:
// HandleCommandLineHelpFlags(). (Well, actually,
// ShowUsageWithFlags() and ShowUsageWithFlagsRestrict() can be called
// HandleCommandLineHelpFlags(). (Well, actually, ShowUsageWithFlags(),
// ShowUsageWithFlagsRestrict(), and DescribeOneFlag() can be called
// externally too, but there's little need for it.) These are all
// declared in the main commandlineflags.h header file.
// declared in the main gflags.h header file.
//
// HandleCommandLineHelpFlags() will check what 'reporting' flags have
// been defined, if any -- the "help" part of the function name is a
@ -48,47 +48,42 @@
// called after all flag-values have been assigned, that is, after
// parsing the command-line.
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cassert>
#include <string>
#include <vector>
#include "google/gflags.h"
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR '/'
#endif
#include "config.h"
#include "gflags/gflags.h"
#include "gflags/gflags_completions.h"
#include "util.h"
// The 'reporting' flags. They all call gflags_exitfunc().
DEFINE_bool (help, false, "show help on all flags [tip: all flags can have two dashes]");
DEFINE_bool (helpful, false, "show help on all flags -- same as -help");
DEFINE_bool (helpshort, false, "show help on only the main module for this program");
DEFINE_string(helpon, "", "show help on the modules named by this flag value");
DEFINE_string(helpmatch, "", "show help on modules whose name contains the specified substr");
DEFINE_bool (helppackage, false, "show help on all modules in the main package");
DEFINE_bool (helpxml, false, "produce an xml version of help");
DEFINE_bool (version, false, "show version and build info and exit");
namespace GFLAGS_NAMESPACE {
using std::string;
using std::vector;
// The 'reporting' flags. They all call exit().
DEFINE_bool(help, false,
"show help on all flags [tip: all flags can have two dashes]");
DEFINE_bool(helpfull, false,
"show help on all flags -- same as -help");
DEFINE_bool(helpshort, false,
"show help on only the main module for this program");
DEFINE_string(helpon, "",
"show help on the modules named by this flag value");
DEFINE_string(helpmatch, "",
"show help on modules whose name contains the specified substr");
DEFINE_bool(helppackage, false,
"show help on all modules in the main package");
DEFINE_bool(helpxml, false,
"produce an xml version of help");
DEFINE_bool(version, false,
"show version and build info and exit");
_START_GOOGLE_NAMESPACE_
// --------------------------------------------------------------------
// DescribeOneFlag()
// DescribeOneFlagInXML()
// Routines that pretty-print info about a flag. These use
// a CommandLineFlagInfo, which is the way the commandlineflags
// a CommandLineFlagInfo, which is the way the gflags
// API exposes static info about a flag.
// --------------------------------------------------------------------
@ -96,7 +91,7 @@ static const int kLineLength = 80;
static void AddString(const string& s,
string* final_string, int* chars_in_line) {
const int slen = s.length();
const int slen = static_cast<int>(s.length());
if (*chars_in_line + 1 + slen >= kLineLength) { // < 80 chars/line
*final_string += "\n ";
*chars_in_line = 6;
@ -108,17 +103,31 @@ static void AddString(const string& s,
*chars_in_line += slen;
}
static string PrintStringFlagsWithQuotes(const CommandLineFlagInfo& flag,
const string& text, bool current) {
const char* c_string = (current ? flag.current_value.c_str() :
flag.default_value.c_str());
if (strcmp(flag.type.c_str(), "string") == 0) { // add quotes for strings
return StringPrintf("%s: \"%s\"", text.c_str(), c_string);
} else {
return StringPrintf("%s: %s", text.c_str(), c_string);
}
}
// Create a descriptive string for a flag.
// Goes to some trouble to make pretty line breaks.
static string DescribeOneFlag(const CommandLineFlagInfo& flag) {
string main_part = (string(" -") + flag.name +
" (" + flag.description + ')');
string DescribeOneFlag(const CommandLineFlagInfo& flag) {
string main_part;
SStringPrintf(&main_part, " -%s (%s)",
flag.name.c_str(),
flag.description.c_str());
const char* c_string = main_part.c_str();
int chars_left = main_part.length();
string final_string = "";
int chars_left = static_cast<int>(main_part.length());
string final_string;
int chars_in_line = 0; // how many chars in current line so far?
while (1) {
assert(chars_left == strlen(c_string)); // Unless there's a \0 in there?
assert(static_cast<size_t>(chars_left)
== strlen(c_string)); // Unless there's a \0 in there?
const char* newline = strchr(c_string, '\n');
if (newline == NULL && chars_in_line+chars_left < kLineLength) {
// The whole remainder of the string fits on this line
@ -127,7 +136,7 @@ static string DescribeOneFlag(const CommandLineFlagInfo& flag) {
break;
}
if (newline != NULL && newline - c_string < kLineLength - chars_in_line) {
int n = newline - c_string;
int n = static_cast<int>(newline - c_string);
final_string.append(c_string, n);
chars_left -= n + 1;
c_string += n + 1;
@ -152,46 +161,55 @@ static string DescribeOneFlag(const CommandLineFlagInfo& flag) {
}
if (*c_string == '\0')
break;
final_string += "\n ";
StringAppendF(&final_string, "\n ");
chars_in_line = 6;
}
// Append data type
AddString(string("type: ") + flag.type, &final_string, &chars_in_line);
// Append default value
if (strcmp(flag.type.c_str(), "string") == 0) { // add quotes for strings
AddString(string("default: \"") + flag.default_value + string("\""),
&final_string, &chars_in_line);
} else {
AddString(string("default: ") + flag.default_value,
// The listed default value will be the actual default from the flag
// definition in the originating source file, unless the value has
// subsequently been modified using SetCommandLineOptionWithMode() with mode
// SET_FLAGS_DEFAULT, or by setting FLAGS_foo = bar before ParseCommandLineFlags().
AddString(PrintStringFlagsWithQuotes(flag, "default", false), &final_string,
&chars_in_line);
if (!flag.is_default) {
AddString(PrintStringFlagsWithQuotes(flag, "currently", true),
&final_string, &chars_in_line);
}
final_string += '\n';
StringAppendF(&final_string, "\n");
return final_string;
}
// Simple routine to xml-escape a string: escape & and < only.
static string XMLText(const string& txt) {
string ans = txt;
for (string::size_type pos = 0; (pos=ans.find("&", pos)) != string::npos; )
for (string::size_type pos = 0; (pos = ans.find("&", pos)) != string::npos; )
ans.replace(pos++, 1, "&amp;");
for (string::size_type pos = 0; (pos=ans.find("<", pos)) != string::npos; )
for (string::size_type pos = 0; (pos = ans.find("<", pos)) != string::npos; )
ans.replace(pos++, 1, "&lt;");
return ans;
}
static void AddXMLTag(string* r, const char* tag, const string& txt) {
StringAppendF(r, "<%s>%s</%s>", tag, XMLText(txt).c_str(), tag);
}
static string DescribeOneFlagInXML(const CommandLineFlagInfo& flag) {
// The file and flagname could have been attributes, but default
// and meaning need to avoid attribute normalization. This way it
// can be parsed by simple programs, in addition to xml parsers.
return (string("<flag>") +
"<file>" + XMLText(flag.filename) + "</file>" +
"<name>" + XMLText(flag.name) + "</name>" +
"<meaning>" + XMLText(flag.description) + "</meaning>" +
"<default>" + XMLText(flag.default_value) + "</default>" +
"<type>" + XMLText(flag.type) + "</type>" +
string("</flag>"));
string r("<flag>");
AddXMLTag(&r, "file", flag.filename);
AddXMLTag(&r, "name", flag.name);
AddXMLTag(&r, "meaning", flag.description);
AddXMLTag(&r, "default", flag.default_value);
AddXMLTag(&r, "current", flag.current_value);
AddXMLTag(&r, "type", flag.type);
r += "</flag>";
return r;
}
// --------------------------------------------------------------------
@ -217,41 +235,73 @@ static string Dirname(const string& filename) {
return filename.substr(0, (sep == string::npos) ? 0 : sep);
}
void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict) {
#ifndef DO_NOT_SHOW_COMMANDLINE_HELP
// Test whether a filename contains at least one of the substrings.
static bool FileMatchesSubstring(const string& filename,
const vector<string>& substrings) {
for (vector<string>::const_iterator target = substrings.begin();
target != substrings.end();
++target) {
if (strstr(filename.c_str(), target->c_str()) != NULL)
return true;
// If the substring starts with a '/', that means that we want
// the string to be at the beginning of a directory component.
// That should match the first directory component as well, so
// we allow '/foo' to match a filename of 'foo'.
if (!target->empty() && (*target)[0] == PATH_SEPARATOR &&
strncmp(filename.c_str(), target->c_str() + 1,
strlen(target->c_str() + 1)) == 0)
return true;
}
return false;
}
// Show help for every filename which matches any of the target substrings.
// If substrings is empty, shows help for every file. If a flag's help message
// has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1'
// before including gflags/gflags.h), then this flag will not be displayed
// by '--help' and its variants.
static void ShowUsageWithFlagsMatching(const char *argv0,
const vector<string> &substrings) {
fprintf(stdout, "%s: %s\n", Basename(argv0), ProgramUsage());
vector<CommandLineFlagInfo> flags;
GetAllFlags(&flags); // flags are sorted by filename, then flagname
const bool have_restrict = (restrict != NULL) && (*restrict != '\0');
string last_filename = ""; // so we know when we're at a new file
string last_filename; // so we know when we're at a new file
bool first_directory = true; // controls blank lines between dirs
bool found_match = false; // stays false iff no dir matches restrict
for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin();
flag != flags.end();
++flag) {
if (have_restrict && strstr(flag->filename.c_str(), restrict) == NULL) {
continue; // this flag doesn't pass the restrict
}
found_match = true; // this flag passed the restrict!
if (flag->filename != last_filename) { // new file
if (Dirname(flag->filename) != Dirname(last_filename)) { // new dir!
if (!first_directory)
fprintf(stdout, "\n\n"); // put blank lines between directories
first_directory = false;
if (substrings.empty() ||
FileMatchesSubstring(flag->filename, substrings)) {
found_match = true; // this flag passed the match!
// If the flag has been stripped, pretend that it doesn't exist.
if (flag->description == kStrippedFlagHelp) continue;
if (flag->filename != last_filename) { // new file
if (Dirname(flag->filename) != Dirname(last_filename)) { // new dir!
if (!first_directory)
fprintf(stdout, "\n\n"); // put blank lines between directories
first_directory = false;
}
fprintf(stdout, "\n Flags from %s:\n", flag->filename.c_str());
last_filename = flag->filename;
}
fprintf(stdout, "\n Flags from %s:\n", flag->filename.c_str());
last_filename = flag->filename;
// Now print this flag
fprintf(stdout, "%s", DescribeOneFlag(*flag).c_str());
}
// Now print this flag
fprintf(stdout, "%s", DescribeOneFlag(*flag).c_str());
}
if (!found_match && restrict == NULL) {
fprintf(stdout, "\n No modules matched program name `%s': use -help\n",
Basename(argv0));
if (!found_match && !substrings.empty()) {
fprintf(stdout, "\n No modules matched: use -help\n");
}
#endif // DO_NOT_SHOW_COMMANDLINE_HELP
}
void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict_) {
vector<string> substrings;
if (restrict_ != NULL && *restrict_ != '\0') {
substrings.push_back(restrict_);
}
ShowUsageWithFlagsMatching(argv0, substrings);
}
void ShowUsageWithFlags(const char *argv0) {
@ -276,7 +326,8 @@ static void ShowXMLOfFlags(const char *prog_name) {
for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin();
flag != flags.end();
++flag) {
fprintf(stdout, "%s\n", DescribeOneFlagInXML(*flag).c_str());
if (flag->description != kStrippedFlagHelp)
fprintf(stdout, "%s\n", DescribeOneFlagInXML(*flag).c_str());
}
// The end of the document
fprintf(stdout, "</AllFlags>\n");
@ -288,15 +339,28 @@ static void ShowXMLOfFlags(const char *prog_name) {
// --------------------------------------------------------------------
static void ShowVersion() {
fprintf(stdout, "%s\n", ProgramInvocationShortName());
// TODO: add other stuff, like a timestamp, who built it, what
// target they built, etc.
const char* version_string = VersionString();
if (version_string && *version_string) {
fprintf(stdout, "%s version %s\n",
ProgramInvocationShortName(), version_string);
} else {
fprintf(stdout, "%s\n", ProgramInvocationShortName());
}
# if !defined(NDEBUG)
fprintf(stdout, "Debug build (NDEBUG not #defined)\n");
# endif
}
static void AppendPrognameStrings(vector<string>* substrings,
const char* progname) {
string r;
r += PATH_SEPARATOR;
r += progname;
substrings->push_back(r + ".");
substrings->push_back(r + "-main.");
substrings->push_back(r + "_main.");
}
// --------------------------------------------------------------------
// HandleCommandLineHelpFlags()
// Checks all the 'reporting' commandline flags to see if any
@ -307,28 +371,31 @@ static void ShowVersion() {
void HandleCommandLineHelpFlags() {
const char* progname = ProgramInvocationShortName();
extern void (*commandlineflags_exitfunc)(int); // in gflags.cc
HandleCommandLineCompletions();
vector<string> substrings;
AppendPrognameStrings(&substrings, progname);
if (FLAGS_helpshort) {
// show only flags related to this binary:
// E.g. for fileutil.cc, want flags containing ... "/fileutil." cc
string restrict = string("/") + progname + ".";
ShowUsageWithFlagsRestrict(progname, restrict.c_str());
commandlineflags_exitfunc(1); // almost certainly exit()
ShowUsageWithFlagsMatching(progname, substrings);
gflags_exitfunc(1);
} else if (FLAGS_help || FLAGS_helpfull) {
} else if (FLAGS_help || FLAGS_helpful) {
// show all options
ShowUsageWithFlagsRestrict(progname, ""); // empty restrict
commandlineflags_exitfunc(1);
gflags_exitfunc(1);
} else if (!FLAGS_helpon.empty()) {
string restrict = "/" + FLAGS_helpon + ".";
ShowUsageWithFlagsRestrict(progname, restrict.c_str());
commandlineflags_exitfunc(1);
string restrict_ = PATH_SEPARATOR + FLAGS_helpon + ".";
ShowUsageWithFlagsRestrict(progname, restrict_.c_str());
gflags_exitfunc(1);
} else if (!FLAGS_helpmatch.empty()) {
ShowUsageWithFlagsRestrict(progname, FLAGS_helpmatch.c_str());
commandlineflags_exitfunc(1);
gflags_exitfunc(1);
} else if (FLAGS_helppackage) {
// Shows help for all files in the same directory as main(). We
@ -338,38 +405,38 @@ void HandleCommandLineHelpFlags() {
// filename like "/progname.cc", and take the dirname of that.
vector<CommandLineFlagInfo> flags;
GetAllFlags(&flags);
const string restrict = string("/") + progname + ".";
string last_package = "";
string last_package;
for (vector<CommandLineFlagInfo>::const_iterator flag = flags.begin();
flag != flags.end();
++flag) {
if (!strstr(flag->filename.c_str(), restrict.c_str()))
if (!FileMatchesSubstring(flag->filename, substrings))
continue;
const string package = Dirname(flag->filename) + "/";
const string package = Dirname(flag->filename) + PATH_SEPARATOR;
if (package != last_package) {
ShowUsageWithFlagsRestrict(progname, package.c_str());
if (last_package != "") { // means this isn't our first pkg
fprintf(stderr, "WARNING: Multiple packages contain a file=%s\n",
progname);
VLOG(7) << "Found package: " << package;
if (!last_package.empty()) { // means this isn't our first pkg
LOG(WARNING) << "Multiple packages contain a file=" << progname;
}
last_package = package;
}
}
if (last_package == "") { // never found a package to print
fprintf(stderr, "WARNING: Unable to find a package for file=%s\n",
progname);
if (last_package.empty()) { // never found a package to print
LOG(WARNING) << "Unable to find a package for file=" << progname;
}
commandlineflags_exitfunc(1);
gflags_exitfunc(1);
} else if (FLAGS_helpxml) {
ShowXMLOfFlags(progname);
commandlineflags_exitfunc(1);
gflags_exitfunc(1);
} else if (FLAGS_version) {
ShowVersion();
// Unlike help, we may be asking for version in a script, so return 0
commandlineflags_exitfunc(0);
gflags_exitfunc(0);
}
}
_END_GOOGLE_NAMESPACE_
} // namespace GFLAGS_NAMESPACE

View file

@ -1,959 +0,0 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// Author: Marius Eriksen
//
// For now, this unit test does not cover all features of
// commandlineflags.cc
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h> // for unlink()
#include <sys/stat.h> // for mkdir()
#include <math.h> // for isinf() and isnan()
#include <vector>
#include <string>
#include "google/gflags.h"
using std::vector;
using std::string;
DECLARE_string(tryfromenv); // in commandlineflags.cc
DEFINE_string(test_tmpdir, "/tmp/gflags_unittest", "Dir we use for temp files");
DEFINE_bool(test_bool, false, "tests bool-ness");
DEFINE_int32(test_int32, -1, "");
DEFINE_int64(test_int64, -2, "");
DEFINE_uint64(test_uint64, 2, "");
DEFINE_double(test_double, -1.0, "");
DEFINE_string(test_string, "initial", "");
//
// The below ugliness gets some additional code coverage in the -helpxml
// and -helpmatch test cases having to do with string lengths and formatting
//
DEFINE_bool(test_bool_with_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_quite_long_name,
false,
"extremely_extremely_extremely_extremely_extremely_extremely_extremely_extremely_long_meaning");
DEFINE_string(test_str1, "initial", "");
DEFINE_string(test_str2, "initial", "");
DEFINE_string(test_str3, "initial", "");
// This is used to test setting tryfromenv manually
DEFINE_string(test_tryfromenv, "initial", "");
// These are never used in this unittest, but can be used by
// commandlineflags_unittest.sh when it needs to specify flags
// that are legal for commandlineflags_unittest but don't need to
// be a particular value.
DEFINE_bool(unused_bool, true, "unused bool-ness");
DEFINE_int32(unused_int32, -1001, "");
DEFINE_int64(unused_int64, -2001, "");
DEFINE_uint64(unused_uint64, 2000, "");
DEFINE_double(unused_double, -1000.0, "");
DEFINE_string(unused_string, "unused", "");
_START_GOOGLE_NAMESPACE_
// The following is some bare-bones testing infrastructure
#define EXPECT_TRUE(cond) \
do { \
if (!(cond)) { \
fprintf(stderr, "Check failed: %s\n", #cond); \
exit(1); \
} \
} while (0)
#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
#define EXPECT_OP(op, val1, val2) \
do { \
if (!((val1) op (val2))) { \
fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
exit(1); \
} \
} while (0)
#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
#define EXPECT_GT(val1, val2) EXPECT_OP(>, val1, val2)
#define EXPECT_LT(val1, val2) EXPECT_OP(<, val1, val2)
#define EXPECT_PRED1(pred, arg) \
do { \
if (!((pred)(arg))) { \
fprintf(stderr, "Check failed: %s(%s)\n", #pred, #arg); \
exit(1); \
} \
} while (0)
#define EXPECT_DOUBLE_EQ(val1, val2) \
do { \
if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
exit(1); \
} \
} while (0)
#define EXPECT_STREQ(val1, val2) \
do { \
if (strcmp((val1), (val2)) != 0) { \
fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
exit(1); \
} \
} while (0)
static bool g_called_exit;
static void CalledExit(int) { g_called_exit = true; }
#define EXPECT_DEATH(fn, msg) \
do { \
g_called_exit = false; \
extern void (*commandlineflags_exitfunc)(int); /* in gflags.cc */ \
commandlineflags_exitfunc = &CalledExit; \
fn; \
commandlineflags_exitfunc = &exit; /* set back to its default */ \
if (!g_called_exit) { \
fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
exit(1); \
} \
} while (0)
vector<void (*)()> g_testlist; // the tests to run
#define TEST(a, b) \
struct Test_##a##_##b { \
Test_##a##_##b() { g_testlist.push_back(&Run); } \
static void Run() { FlagSaver fs; RunTest(); } \
static void RunTest(); \
}; \
static Test_##a##_##b g_test_##a##_##b; \
void Test_##a##_##b::RunTest()
static int RUN_ALL_TESTS() {
vector<void (*)()>::const_iterator it;
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
(*it)();
}
fprintf(stderr, "Passed %d tests\n\nPASS\n", (int)g_testlist.size());
return 0;
}
// Death tests for "help" options.
//
// The help system automatically calls exit(1) when you specify any of
// the help-related flags ("-helpmatch", "-helpxml") so we can't test
// those mainline.
// Tests that "-helpmatch" causes the process to die.
TEST(ReadFlagsFromStringDeathTest, HelpMatch) {
EXPECT_DEATH(ReadFlagsFromString("-helpmatch=base", GetArgv0(), true),
"");
}
// Tests that "-helpxml" causes the process to die.
TEST(ReadFlagsFromStringDeathTest, HelpXml) {
EXPECT_DEATH(ReadFlagsFromString("-helpxml", GetArgv0(), true),
"");
}
// A subroutine needed for testing reading flags from a string.
void TestFlagString(const string& flags,
const string& expected_string,
bool expected_bool,
int32 expected_int32,
double expected_double) {
EXPECT_TRUE(ReadFlagsFromString(flags,
GetArgv0(),
// errors are fatal
true));
EXPECT_EQ(expected_string, FLAGS_test_string);
EXPECT_EQ(expected_bool, FLAGS_test_bool);
EXPECT_EQ(expected_int32, FLAGS_test_int32);
EXPECT_DOUBLE_EQ(expected_double, FLAGS_test_double);
}
// Tests reading flags from a string.
TEST(FlagFileTest, ReadFlagsFromString) {
TestFlagString(
// Flag string
"-test_string=continued\n"
"# some comments are in order\n"
"# some\n"
" # comments\n"
"#are\n"
" #trickier\n"
"# than others\n"
"-test_bool=true\n"
" -test_int32=1\n"
"-test_double=0.0\n",
// Expected values
"continued",
true,
1,
0.0);
TestFlagString(
// Flag string
"# let's make sure it can update values\n"
"-test_string=initial\n"
"-test_bool=false\n"
"-test_int32=123\n"
"-test_double=123.0\n",
// Expected values
"initial",
false,
123,
123.0);
}
// Tests the filename part of the flagfile
TEST(FlagFileTest, FilenamesOurfileLast) {
FLAGS_test_string = "initial";
FLAGS_test_bool = false;
FLAGS_test_int32 = -1;
FLAGS_test_double = -1.0;
TestFlagString(
// Flag string
"-test_string=continued\n"
"# some comments are in order\n"
"# some\n"
" # comments\n"
"#are\n"
" #trickier\n"
"# than others\n"
"not_our_filename\n"
"-test_bool=true\n"
" -test_int32=1\n"
"gflags_unittest\n"
"-test_double=1000.0\n",
// Expected values
"continued",
false,
-1,
1000.0);
}
TEST(FlagFileTest, FilenamesOurfileFirst) {
FLAGS_test_string = "initial";
FLAGS_test_bool = false;
FLAGS_test_int32 = -1;
FLAGS_test_double = -1.0;
TestFlagString(
// Flag string
"-test_string=continued\n"
"# some comments are in order\n"
"# some\n"
" # comments\n"
"#are\n"
" #trickier\n"
"# than others\n"
"gflags_unittest\n"
"-test_bool=true\n"
" -test_int32=1\n"
"not_our_filename\n"
"-test_double=1000.0\n",
// Expected values
"continued",
true,
1,
-1.0);
}
TEST(FlagFileTest, FilenamesOurfileGlob) {
FLAGS_test_string = "initial";
FLAGS_test_bool = false;
FLAGS_test_int32 = -1;
FLAGS_test_double = -1.0;
TestFlagString(
// Flag string
"-test_string=continued\n"
"# some comments are in order\n"
"# some\n"
" # comments\n"
"#are\n"
" #trickier\n"
"# than others\n"
"*flags*\n"
"-test_bool=true\n"
" -test_int32=1\n"
"flags\n"
"-test_double=1000.0\n",
// Expected values
"continued",
true,
1,
-1.0);
}
TEST(FlagFileTest, FilenamesOurfileInBigList) {
FLAGS_test_string = "initial";
FLAGS_test_bool = false;
FLAGS_test_int32 = -1;
FLAGS_test_double = -1.0;
TestFlagString(
// Flag string
"-test_string=continued\n"
"# some comments are in order\n"
"# some\n"
" # comments\n"
"#are\n"
" #trickier\n"
"# than others\n"
"*first* *flags* *third*\n"
"-test_bool=true\n"
" -test_int32=1\n"
"flags\n"
"-test_double=1000.0\n",
// Expected values
"continued",
true,
1,
-1.0);
}
// Tests that a failed flag-from-string read keeps flags at default values
TEST(FlagFileTest, FailReadFlagsFromString) {
FLAGS_test_int32 = 119;
string flags("# let's make sure it can update values\n"
"-test_string=non_initial\n"
"-test_bool=false\n"
"-test_int32=123\n"
"-test_double=illegal\n");
EXPECT_FALSE(ReadFlagsFromString(flags,
GetArgv0(),
// errors are fatal
false));
EXPECT_EQ(119, FLAGS_test_int32);
EXPECT_EQ("initial", FLAGS_test_string);
}
// Tests that flags can be set to ordinary values.
TEST(SetFlagValueTest, OrdinaryValues) {
EXPECT_EQ("initial", FLAGS_test_str1);
SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str1); // set; was default
SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str1); // already set once
FLAGS_test_str1 = "initial";
SetCommandLineOptionWithMode("test_str1", "third", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("initial", FLAGS_test_str1); // still already set before
SetCommandLineOptionWithMode("test_str1", "third", SET_FLAGS_VALUE);
EXPECT_EQ("third", FLAGS_test_str1); // changed value
SetCommandLineOptionWithMode("test_str1", "fourth", SET_FLAGS_DEFAULT);
EXPECT_EQ("third", FLAGS_test_str1);
// value not changed (already set before)
EXPECT_EQ("initial", FLAGS_test_str2);
SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str2); // changed (was default)
FLAGS_test_str2 = "extra";
EXPECT_EQ("extra", FLAGS_test_str2);
FLAGS_test_str2 = "second";
SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT);
EXPECT_EQ("third", FLAGS_test_str2); // still changed (was equal to default)
SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("fourth", FLAGS_test_str2); // changed (was default)
EXPECT_EQ("initial", FLAGS_test_str3);
SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str3); // changed
FLAGS_test_str3 = "third";
SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_DEFAULT);
EXPECT_EQ("third", FLAGS_test_str3); // not changed (was set)
SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("third", FLAGS_test_str3); // not changed (was set)
SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAGS_VALUE);
EXPECT_EQ("fourth", FLAGS_test_str3); // changed value
}
// Tests that flags can be set to exceptional values.
TEST(SetFlagValueTest, ExceptionalValues) {
EXPECT_EQ("test_double set to inf\n",
SetCommandLineOption("test_double", "inf"));
EXPECT_PRED1(isinf, FLAGS_test_double);
EXPECT_EQ("test_double set to inf\n",
SetCommandLineOption("test_double", "INF"));
EXPECT_PRED1(isinf, FLAGS_test_double);
// set some bad values
EXPECT_EQ("",
SetCommandLineOption("test_double", "0.1xxx"));
EXPECT_EQ("",
SetCommandLineOption("test_double", " "));
EXPECT_EQ("",
SetCommandLineOption("test_double", ""));
EXPECT_EQ("test_double set to -inf\n",
SetCommandLineOption("test_double", "-inf"));
EXPECT_PRED1(isinf, FLAGS_test_double);
EXPECT_GT(0, FLAGS_test_double);
EXPECT_EQ("test_double set to nan\n",
SetCommandLineOption("test_double", "NaN"));
EXPECT_PRED1(isnan, FLAGS_test_double);
}
// Tests that integer flags can be specified in many ways
TEST(SetFlagValueTest, DifferentRadices) {
EXPECT_EQ("test_int32 set to 12\n",
SetCommandLineOption("test_int32", "12"));
EXPECT_EQ("test_int32 set to 16\n",
SetCommandLineOption("test_int32", "0x10"));
EXPECT_EQ("test_int32 set to 34\n",
SetCommandLineOption("test_int32", "0X22"));
// Leading 0 is *not* octal; it's still decimal
EXPECT_EQ("test_int32 set to 10\n",
SetCommandLineOption("test_int32", "010"));
}
// Tests what happens when you try to set a flag to an illegal value
TEST(SetFlagValueTest, IllegalValues) {
FLAGS_test_bool = true;
FLAGS_test_int32 = 119;
FLAGS_test_int64 = 1191;
FLAGS_test_uint64 = 11911;
EXPECT_EQ("",
SetCommandLineOption("test_bool", "12"));
EXPECT_EQ("",
SetCommandLineOption("test_int32", "7000000000000"));
// TODO(csilvers): uncomment this when we disallow negative numbers for uint64
#if 0
EXPECT_EQ("",
SetCommandLineOption("test_uint64", "-1"));
#endif
EXPECT_EQ("",
SetCommandLineOption("test_int64", "not a number!"));
// Test the empty string with each type of input
EXPECT_EQ("", SetCommandLineOption("test_bool", ""));
EXPECT_EQ("", SetCommandLineOption("test_int32", ""));
EXPECT_EQ("", SetCommandLineOption("test_int64", ""));
EXPECT_EQ("", SetCommandLineOption("test_uint64", ""));
EXPECT_EQ("", SetCommandLineOption("test_double", ""));
EXPECT_EQ("test_string set to \n", SetCommandLineOption("test_string", ""));
EXPECT_EQ(true, FLAGS_test_bool);
EXPECT_EQ(119, FLAGS_test_int32);
EXPECT_EQ(1191, FLAGS_test_int64);
EXPECT_EQ(11911, FLAGS_test_uint64);
}
// Tests that the FooFromEnv does the right thing
TEST(FromEnvTest, LegalValues) {
setenv("BOOL_VAL1", "true", 1);
setenv("BOOL_VAL2", "false", 1);
setenv("BOOL_VAL3", "1", 1);
setenv("BOOL_VAL4", "F", 1);
EXPECT_EQ(true, BoolFromEnv("BOOL_VAL1", false));
EXPECT_EQ(false, BoolFromEnv("BOOL_VAL2", true));
EXPECT_EQ(true, BoolFromEnv("BOOL_VAL3", false));
EXPECT_EQ(false, BoolFromEnv("BOOL_VAL4", true));
EXPECT_EQ(true, BoolFromEnv("BOOL_VAL_UNKNOWN", true));
EXPECT_EQ(false, BoolFromEnv("BOOL_VAL_UNKNOWN", false));
setenv("INT_VAL1", "1", 1);
setenv("INT_VAL2", "-1", 1);
EXPECT_EQ(1, Int32FromEnv("INT_VAL1", 10));
EXPECT_EQ(-1, Int32FromEnv("INT_VAL2", 10));
EXPECT_EQ(10, Int32FromEnv("INT_VAL_UNKNOWN", 10));
setenv("INT_VAL3", "1099511627776", 1);
EXPECT_EQ(1, Int64FromEnv("INT_VAL1", 20));
EXPECT_EQ(-1, Int64FromEnv("INT_VAL2", 20));
EXPECT_EQ(1099511627776LL, Int64FromEnv("INT_VAL3", 20));
EXPECT_EQ(20, Int64FromEnv("INT_VAL_UNKNOWN", 20));
EXPECT_EQ(1, Uint64FromEnv("INT_VAL1", 30));
EXPECT_EQ(1099511627776ULL, Uint64FromEnv("INT_VAL3", 30));
EXPECT_EQ(30, Uint64FromEnv("INT_VAL_UNKNOWN", 30));
// I pick values here that can be easily represented exactly in floating-point
setenv("DOUBLE_VAL1", "0.0", 1);
setenv("DOUBLE_VAL2", "1.0", 1);
setenv("DOUBLE_VAL3", "-1.0", 1);
EXPECT_EQ(0.0, DoubleFromEnv("DOUBLE_VAL1", 40.0));
EXPECT_EQ(1.0, DoubleFromEnv("DOUBLE_VAL2", 40.0));
EXPECT_EQ(-1.0, DoubleFromEnv("DOUBLE_VAL3", 40.0));
EXPECT_EQ(40.0, DoubleFromEnv("DOUBLE_VAL_UNKNOWN", 40.0));
setenv("STRING_VAL1", "", 1);
setenv("STRING_VAL2", "my happy string!", 1);
EXPECT_STREQ("", StringFromEnv("STRING_VAL1", "unknown"));
EXPECT_STREQ("my happy string!", StringFromEnv("STRING_VAL2", "unknown"));
EXPECT_STREQ("unknown", StringFromEnv("STRING_VAL_UNKNOWN", "unknown"));
}
// Tests that the FooFromEnv dies on parse-error
TEST(FromEnvTest, IllegalValues) {
setenv("BOOL_BAD1", "so true!",1 );
setenv("BOOL_BAD2", "", 1);
EXPECT_DEATH(BoolFromEnv("BOOL_BAD1", false), "error parsing env variable");
EXPECT_DEATH(BoolFromEnv("BOOL_BAD2", true), "error parsing env variable");
setenv("INT_BAD1", "one", 1);
setenv("INT_BAD2", "100000000000000000", 1);
setenv("INT_BAD3", "0xx10", 1);
setenv("INT_BAD4", "", 1);
EXPECT_DEATH(Int32FromEnv("INT_BAD1", 10), "error parsing env variable");
EXPECT_DEATH(Int32FromEnv("INT_BAD2", 10), "error parsing env variable");
EXPECT_DEATH(Int32FromEnv("INT_BAD3", 10), "error parsing env variable");
EXPECT_DEATH(Int32FromEnv("INT_BAD4", 10), "error parsing env variable");
setenv("BIGINT_BAD1", "18446744073709551616000", 1);
EXPECT_DEATH(Int64FromEnv("INT_BAD1", 20), "error parsing env variable");
EXPECT_DEATH(Int64FromEnv("INT_BAD3", 20), "error parsing env variable");
EXPECT_DEATH(Int64FromEnv("INT_BAD4", 20), "error parsing env variable");
EXPECT_DEATH(Int64FromEnv("BIGINT_BAD1", 200), "error parsing env variable");
setenv("BIGINT_BAD2", "-1", 1);
EXPECT_DEATH(Uint64FromEnv("INT_BAD1", 30), "error parsing env variable");
EXPECT_DEATH(Uint64FromEnv("INT_BAD3", 30), "error parsing env variable");
EXPECT_DEATH(Uint64FromEnv("INT_BAD4", 30), "error parsing env variable");
EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD1", 30), "error parsing env variable");
// TODO(csilvers): uncomment this when we disallow negative numbers for uint64
#if 0
EXPECT_DEATH(Uint64FromEnv("BIGINT_BAD2", 30), "error parsing env variable");
#endif
setenv("DOUBLE_BAD1", "0.0.0", 1);
setenv("DOUBLE_BAD2", "", 1);
EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD1", 40.0), "error parsing env variable");
EXPECT_DEATH(DoubleFromEnv("DOUBLE_BAD2", 40.0), "error parsing env variable");
}
// Tests that FlagSaver can save the states of string flags.
TEST(FlagSaverTest, CanSaveStringFlagStates) {
// 1. Initializes the flags.
// State of flag test_str1:
// default value - "initial"
// current value - "initial"
// not set - true
SetCommandLineOptionWithMode("test_str2", "second", SET_FLAGS_VALUE);
// State of flag test_str2:
// default value - "initial"
// current value - "second"
// not set - false
SetCommandLineOptionWithMode("test_str3", "second", SET_FLAGS_DEFAULT);
// State of flag test_str3:
// default value - "second"
// current value - "second"
// not set - true
// 2. Saves the flag states.
{
FlagSaver fs;
// 3. Modifies the flag states.
SetCommandLineOptionWithMode("test_str1", "second", SET_FLAGS_VALUE);
EXPECT_EQ("second", FLAGS_test_str1);
// State of flag test_str1:
// default value - "second"
// current value - "second"
// not set - true
SetCommandLineOptionWithMode("test_str2", "third", SET_FLAGS_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str2);
// State of flag test_str2:
// default value - "third"
// current value - "second"
// not set - false
SetCommandLineOptionWithMode("test_str3", "third", SET_FLAGS_VALUE);
EXPECT_EQ("third", FLAGS_test_str3);
// State of flag test_str1:
// default value - "second"
// current value - "third"
// not set - false
// 4. Restores the flag states.
}
// 5. Verifies that the states were restored.
// Verifies that the value of test_str1 was restored.
EXPECT_EQ("initial", FLAGS_test_str1);
// Verifies that the "not set" attribute of test_str1 was restored to true.
SetCommandLineOptionWithMode("test_str1", "second", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str1);
// Verifies that the value of test_str2 was restored.
EXPECT_EQ("second", FLAGS_test_str2);
// Verifies that the "not set" attribute of test_str2 was restored to false.
SetCommandLineOptionWithMode("test_str2", "fourth", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("second", FLAGS_test_str2);
// Verifies that the value of test_str3 was restored.
EXPECT_EQ("second", FLAGS_test_str3);
// Verifies that the "not set" attribute of test_str3 was restored to true.
SetCommandLineOptionWithMode("test_str3", "fourth", SET_FLAG_IF_DEFAULT);
EXPECT_EQ("fourth", FLAGS_test_str3);
}
// Tests that FlagSaver can save the values of various-typed flags.
TEST(FlagSaverTest, CanSaveVariousTypedFlagValues) {
// Initializes the flags.
FLAGS_test_bool = false;
FLAGS_test_int32 = -1;
FLAGS_test_int64 = -2;
FLAGS_test_uint64 = 3;
FLAGS_test_double = 4.0;
FLAGS_test_string = "good";
// Saves the flag states.
{
FlagSaver fs;
// Modifies the flags.
FLAGS_test_bool = true;
FLAGS_test_int32 = -5;
FLAGS_test_int64 = -6;
FLAGS_test_uint64 = 7;
FLAGS_test_double = 8.0;
FLAGS_test_string = "bad";
// Restores the flag states.
}
// Verifies the flag values were restored.
EXPECT_FALSE(FLAGS_test_bool);
EXPECT_EQ(-1, FLAGS_test_int32);
EXPECT_EQ(-2, FLAGS_test_int64);
EXPECT_EQ(3, FLAGS_test_uint64);
EXPECT_DOUBLE_EQ(4.0, FLAGS_test_double);
EXPECT_EQ("good", FLAGS_test_string);
}
TEST(GetAllFlagsTest, BaseTest) {
vector<CommandLineFlagInfo> flags;
GetAllFlags(&flags);
bool found_test_bool = false;
vector<CommandLineFlagInfo>::const_iterator i;
for (i = flags.begin(); i != flags.end(); ++i) {
if (i->name == "test_bool") {
found_test_bool = true;
EXPECT_EQ(i->type, "bool");
EXPECT_EQ(i->default_value, "false");
break;
}
}
EXPECT_EQ(true, found_test_bool);
}
TEST(ShowUsageWithFlagsTest, BaseTest) {
// TODO(csilvers): test this by allowing output other than to stdout.
// Not urgent since this functionality is tested via
// gflags_unittest.sh, though only through use of --help.
}
TEST(ShowUsageWithFlagsRestrictTest, BaseTest) {
// TODO(csilvers): test this by allowing output other than to stdout.
// Not urgent since this functionality is tested via
// gflags_unittest.sh, though only through use of --helpmatch.
}
// Note: all these argv-based tests depend on SetArgv being called
// before InitGoogle() in main(), below.
TEST(GetArgvsTest, BaseTest) {
vector<string> argvs = GetArgvs();
EXPECT_EQ(4, argvs.size());
EXPECT_EQ("/test/argv/for/gflags_unittest", argvs[0]);
EXPECT_EQ("argv 2", argvs[1]);
EXPECT_EQ("3rd argv", argvs[2]);
EXPECT_EQ("argv #4", argvs[3]);
}
TEST(GetArgvTest, BaseTest) {
EXPECT_STREQ("/test/argv/for/gflags_unittest "
"argv 2 3rd argv argv #4", GetArgv());
}
TEST(GetArgv0Test, BaseTest) {
EXPECT_STREQ("/test/argv/for/gflags_unittest", GetArgv0());
}
TEST(GetArgvSumTest, BaseTest) {
// This number is just the sum of the ASCII values of all the chars
// in GetArgv().
EXPECT_EQ(4904, GetArgvSum());
}
TEST(ProgramInvocationNameTest, BaseTest) {
EXPECT_STREQ("/test/argv/for/gflags_unittest",
ProgramInvocationName());
}
TEST(ProgramInvocationShortNameTest, BaseTest) {
EXPECT_STREQ("gflags_unittest", ProgramInvocationShortName());
}
TEST(ProgramUsageTest, BaseTest) { // Depends on 1st arg to InitGoogle in main()
EXPECT_STREQ("/test/argv/for/gflags_unittest: "
"<useless flag> [...]\nDoes something useless.\n",
ProgramUsage());
}
TEST(GetCommandLineOptionTest, NameExistsAndIsDefault) {
string value("will be changed");
bool is_default;
bool r = GetCommandLineOption("test_bool", &value, &is_default);
EXPECT_EQ(true, r);
EXPECT_EQ("false", value);
EXPECT_EQ(true, is_default);
r = GetCommandLineOption("test_int32", &value, &is_default);
EXPECT_EQ(true, r);
EXPECT_EQ("-1", value);
EXPECT_EQ(true, is_default);
}
TEST(GetCommandLineOptionTest, NameExistsAndWasAssigned) {
FLAGS_test_int32 = 400;
string value("will be changed");
bool is_default;
const bool r = GetCommandLineOption("test_int32", &value, &is_default);
EXPECT_EQ(true, r);
EXPECT_EQ("400", value);
EXPECT_EQ(false, is_default);
}
TEST(GetCommandLineOptionTest, NameExistsAndWasSet) {
SetCommandLineOption("test_int32", "700");
string value("will be changed");
bool is_default;
const bool r = GetCommandLineOption("test_int32", &value, &is_default);
EXPECT_EQ(true, r);
EXPECT_EQ("700", value);
EXPECT_EQ(false, is_default);
}
TEST(GetCommandLineOptionTest, NameExistsAndWasNotSet) {
// This doesn't set the flag's value, but rather its default value.
// is_default is still true, but the 'default' value returned has changed!
SetCommandLineOptionWithMode("test_int32", "800", SET_FLAGS_DEFAULT);
string value("will be changed");
bool is_default;
const bool r = GetCommandLineOption("test_int32", &value, &is_default);
EXPECT_EQ(true, r);
EXPECT_EQ("800", value);
EXPECT_EQ(true, is_default);
}
TEST(GetCommandLineOptionTest, NameExistsAndWasConditionallySet) {
SetCommandLineOptionWithMode("test_int32", "900", SET_FLAG_IF_DEFAULT);
string value("will be changed");
bool is_default;
const bool r = GetCommandLineOption("test_int32", &value, &is_default);
EXPECT_EQ(true, r);
EXPECT_EQ("900", value);
EXPECT_EQ(false, is_default);
}
TEST(GetCommandLineOptionTest, NameDoesNotExist) {
string value("will not be changed");
bool is_default = false;
const bool r = GetCommandLineOption("test_int3210", &value, &is_default);
EXPECT_EQ(false, r);
EXPECT_EQ("will not be changed", value);
EXPECT_EQ(false, is_default);
}
TEST(GetCommandLineOptionTest, NoLastArg) {
// Mostly, makes sure passing in NULL as last arg doesn't cause a crash
string value("will not be changed, at first");
bool r = GetCommandLineOption("test_int3210", &value, NULL);
EXPECT_EQ(false, r);
EXPECT_EQ("will not be changed, at first", value);
r = GetCommandLineOption("test_int32", &value, NULL);
EXPECT_EQ(true, r);
EXPECT_EQ("-1", value);
}
TEST(GetCommandLineFlagInfoTest, FlagExists) {
CommandLineFlagInfo info;
bool r = GetCommandLineFlagInfo("test_int32", &info);
EXPECT_EQ(true, r);
EXPECT_EQ("test_int32", info.name);
EXPECT_EQ("int32", info.type);
EXPECT_EQ("", info.description);
EXPECT_EQ("-1", info.default_value);
r = GetCommandLineFlagInfo("test_bool", &info);
EXPECT_EQ(true, r);
EXPECT_EQ("test_bool", info.name);
EXPECT_EQ("bool", info.type);
EXPECT_EQ("tests bool-ness", info.description);
EXPECT_EQ("false", info.default_value);
}
TEST(GetCommandLineFlagInfoTest, FlagDoesNotExist) {
CommandLineFlagInfo info;
bool r = GetCommandLineFlagInfo("test_int3210", &info);
EXPECT_EQ(false, r);
}
// These are lightly tested because they're deprecated. Basically,
// the tests are meant to cover how existing users use these functions,
// but not necessarily how new users could use them.
TEST(DeprecatedFunctionsTest, CommandlineFlagsIntoString) {
string s = CommandlineFlagsIntoString();
EXPECT_NE(string::npos, s.find("--test_bool="));
}
TEST(DeprecatedFunctionsTest, AppendFlagsIntoFile) {
FLAGS_test_int32 = 10; // just to make the test more interesting
string filename(FLAGS_test_tmpdir + "/flagfile");
unlink(filename.c_str()); // just to be safe
const bool r = AppendFlagsIntoFile(filename, "not the real argv0");
EXPECT_EQ(true, r);
FILE* fp = fopen(filename.c_str(), "r");
EXPECT_TRUE(fp != NULL);
char line[8192];
fgets(line, sizeof(line)-1, fp); // first line should be progname
EXPECT_STREQ("not the real argv0\n", line);
bool found_bool = false, found_int32 = false;
while (fgets(line, sizeof(line)-1, fp)) {
line[sizeof(line)-1] = '\0'; // just to be safe
if (strcmp(line, "--test_bool=false\n") == 0)
found_bool = true;
if (strcmp(line, "--test_int32=10\n") == 0)
found_int32 = true;
}
EXPECT_EQ(true, found_int32);
EXPECT_EQ(true, found_bool);
fclose(fp);
}
TEST(DeprecatedFunctionsTest, ReadFromFlagsFile) {
FLAGS_test_int32 = -10; // just to make the test more interesting
string filename(FLAGS_test_tmpdir + "/flagfile2");
unlink(filename.c_str()); // just to be safe
bool r = AppendFlagsIntoFile(filename, GetArgv0());
EXPECT_EQ(true, r);
FLAGS_test_int32 = -11;
r = ReadFromFlagsFile(filename, GetArgv0(), true);
EXPECT_EQ(true, r);
EXPECT_EQ(-10, FLAGS_test_int32);
} // unnamed namespace
TEST(DeprecatedFunctionsTest, ReadFromFlagsFileFailure) {
FLAGS_test_int32 = -20;
string filename(FLAGS_test_tmpdir + "/flagfile3");
FILE* fp = fopen(filename.c_str(), "w");
EXPECT_TRUE(fp != NULL);
// Note the error in the bool assignment below...
fprintf(fp, "%s\n--test_int32=-21\n--test_bool=not_a_bool!\n", GetArgv0());
fclose(fp);
FLAGS_test_int32 = -22;
const bool r = ReadFromFlagsFile(filename, GetArgv0(), false);
EXPECT_EQ(false, r);
EXPECT_EQ(-22, FLAGS_test_int32); // the -21 from the flagsfile didn't take
}
TEST(FlagsSetBeforeInitGoogleTest, TryFromEnv) {
EXPECT_EQ("pre-set", FLAGS_test_tryfromenv);
}
static int Main(int argc, char **argv) {
// We need to call SetArgv before InitGoogle, so our "test" argv will
// win out over this executable's real argv. That makes running this
// test with a real --help flag kinda annoying, unfortunately.
const char* test_argv[] = { "/test/argv/for/gflags_unittest",
"argv 2", "3rd argv", "argv #4" };
SetArgv(sizeof(test_argv)/sizeof(*test_argv), test_argv);
// The first arg is the usage message, also important for testing.
string usage_message = (string(GetArgv0()) +
": <useless flag> [...]\nDoes something useless.\n");
// We test setting tryfromenv manually, and making sure initgoogle still
// evaluates it.
FLAGS_tryfromenv = "test_tryfromenv";
setenv("FLAGS_test_tryfromenv", "pre-set", 1);
SetUsageMessage(usage_message.c_str());
ParseCommandLineFlags(&argc, &argv, true);
mkdir(FLAGS_test_tmpdir.c_str(), 0755);
return RUN_ALL_TESTS();
}
_END_GOOGLE_NAMESPACE_
int main(int argc, char** argv) {
return GOOGLE_NAMESPACE::Main(argc, argv);
}

View file

@ -1,178 +0,0 @@
#!/bin/sh
# Copyright (c) 2006, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ---
# Author: Craig Silverstein
#
# Just tries to run gflags_unittest with various flags defined in
# gflags.cc, and make sure they give the appropriate exit
# status and appropriate error message.
if [ -z "$1" ]
then
echo "USAGE: $0 <unittest exe> [tmpdir]"
exit 1
fi
EXE=$1
TMPDIR=${2:-/tmp/gflags}
# $1: line-number $2: expected return code. $3: substring of expected output.
# $4: a substring you *don't* expect to find in the output. $5+ flags
Expect() {
local line_number="$1"
shift
local expected_rc="$1"
shift
local expected_output="$1"
shift
local unexpected_output="$1"
shift
$EXE "$@" > "$TMPDIR/test.$line_number" 2>&1
local actual_rc=$?
if [ $actual_rc != $expected_rc ]; then
echo "Test on line $line_number failed:" \
"expected rc $expected_rc, got $actual_rc"
exit 1;
fi
if [ -n "$expected_output" ] &&
! fgrep -q "$expected_output" "$TMPDIR/test.$line_number"; then
echo "Test on line $line_number failed:" \
"did not find expected substring '$expected_output'"
exit 1;
fi
if [ -n "$unexpected_output" ] &&
fgrep -q "$unexpected_output" "$TMPDIR/test.$line_number"; then
echo "Test line $line_number failed:" \
"found unexpected substring '$unexpected_output'"
exit 1;
fi
}
rm -rf $TMPDIR
mkdir $TMPDIR || exit 2
# Create a few flagfiles we can use later
echo "--version" > $TMPDIR/flagfile.1
echo "--foo=bar" > $TMPDIR/flagfile.2
echo "--nounused_bool" >> $TMPDIR/flagfile.2
echo "--flagfile=$TMPDIR/flagfile.2" > $TMPDIR/flagfile.3
# Set a few environment variables (useful for --tryfromenv)
export FLAGS_undefok=foo,bar
export FLAGS_weirdo=
export FLAGS_version=true
export FLAGS_help=false
# First, just make sure the unittest works as-is
Expect $LINENO 0 "PASS" ""
# --help should show all flags, including flags from gflags_reporting.cc
Expect $LINENO 1 "/gflags_reporting.cc" "" --help
# --nohelp and --help=false should be as if we didn't say anything
Expect $LINENO 0 "PASS" "" --nohelp
Expect $LINENO 0 "PASS" "" --help=false
# --helpfull is the same as help
Expect $LINENO 1 "/gflags_reporting.cc" "" -helpfull
# --helpshort should show only flags from the unittest itself
Expect $LINENO 1 "/gflags_unittest.cc" "/gflags_reporting.cc" --helpshort
# --helpon needs an argument
Expect $LINENO 1 "'--helpon' is missing its argument" "" --helpon
# --helpon argument indicates what file we'll show args from
Expect $LINENO 1 "/gflags.cc" "/gflags_unittest.cc" --helpon=gflags
# another way of specifying the argument
Expect $LINENO 1 "/gflags.cc" "/gflags_unittest.cc" --helpon gflags
# test another argument
Expect $LINENO 1 "/gflags_unittest.cc" "/gflags.cc" \
--helpon gflags_unittest
# helpmatch is like helpon but takes substrings
Expect $LINENO 1 "/gflags_unittest.cc" "/gflags.cc" \
-helpmatch _
Expect $LINENO 1 "/gflags_unittest.cc" "/gflags.cc" \
-helpmatch=unittest
# helppackage shows all the flags in the same dir as this unittest
# --help should show all flags, including flags from google.cc
Expect $LINENO 1 "/gflags_reporting.cc" "" --helppackage
# xml!
Expect $LINENO 1 "/gflags_unittest.cc</file>" \
"/gflags_unittest.cc:" --helpxml
# just print the version info and exit
Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" --version
# --undefok is a fun flag...
Expect $LINENO 1 "unknown command line flag 'foo'" "" --undefok= --foo --unused_bool
Expect $LINENO 0 "PASS" "" --undefok=foo --foo --unused_bool
# It's ok if the foo is in the middle
Expect $LINENO 0 "PASS" "" --undefok=fee,fi,foo,fum --foo --unused_bool
# But the spelling has to be just right...
Expect $LINENO 1 "unknown command line flag 'foo'" "" --undefok=fo --foo --unused_bool
Expect $LINENO 1 "unknown command line flag 'foo'" "" --undefok=foot --foo --unused_bool
# See if we can successfully load our flags from the flagfile
Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
--flagfile=$TMPDIR/flagfile.1
Expect $LINENO 0 "PASS" "" --flagfile=$TMPDIR/flagfile.2
Expect $LINENO 0 "PASS" "" --flagfile=$TMPDIR/flagfile.3
# Also try to load flags from the environment
Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" --fromenv=version
Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" --tryfromenv=version
Expect $LINENO 0 "PASS" "" --fromenv=help
Expect $LINENO 0 "PASS" "" --tryfromenv=help
Expect $LINENO 1 "helpfull not found in environment" "" --fromenv=helpfull
Expect $LINENO 0 "PASS" "" --tryfromenv=helpfull
Expect $LINENO 0 "PASS" "" --tryfromenv=undefok --foo
Expect $LINENO 1 "unknown command line flag" "" --tryfromenv=weirdo
Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
--tryfromenv=test_bool,version,unused_bool
Expect $LINENO 1 "not found in environment" "" --fromenv=test_bool
Expect $LINENO 1 "unknown command line flag" "" --fromenv=test_bool,ok
# Here, the --version overrides the fromenv
Expect $LINENO 0 "gflags_unittest" "gflags_unittest.cc" \
--fromenv=test_bool,version,ok
# Make sure -- by itself stops argv processing
Expect $LINENO 0 "PASS" "" -- --help
echo "PASS"
exit 0

View file

@ -1,387 +0,0 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// Author: Ray Sidney
// Revamped and reorganized by Craig Silverstein
//
// This is the file that should be included by any file which declares
// or defines a command line flag or wants to parse command line flags
// or print a program usage message (which will include information about
// flags). Executive summary, in the form of an example foo.cc file:
//
// #include "foo.h" // foo.h has a line "DECLARE_int32(start);"
//
// DEFINE_int32(end, 1000, "The last record to read");
// DECLARE_bool(verbose); // some other file has a DEFINE_bool(verbose, ...)
//
// void MyFunc() {
// if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end);
// }
//
// Then, at the command-line:
// ./foo --noverbose --start=5 --end=100
//
// For more details, see
// doc/gflags.html
#ifndef BASE_COMMANDLINEFLAGS_H__
#define BASE_COMMANDLINEFLAGS_H__
#include <string>
#include <vector>
// We care a lot about number of bits things take up. Unfortunately,
// systems define their bit-specific ints in a lot of different ways.
// We use our own way, and have a typedef to get there.
// Note: these commands below may look like "#if 1" or "#if 0", but
// that's because they were constructed that way at ./configure time.
// Look at gflags.h.in to see how they're calculated (based on your config).
#if @ac_cv_have_stdint_h@
#include <stdint.h> // the normal place uint16_t is defined
#endif
#if @ac_cv_have_systypes_h@
#include <sys/types.h> // the normal place u_int16_t is defined
#endif
#if @ac_cv_have_inttypes_h@
#include <inttypes.h> // a third place for uint16_t or u_int16_t
#endif
@ac_google_start_namespace@
#if @ac_cv_have_uint16_t@ // the C99 format
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
#elif @ac_cv_have_u_int16_t@ // the BSD format
typedef int32_t int32;
typedef u_int32_t uint32;
typedef int64_t int64;
typedef u_int64_t uint64;
#elif @ac_cv_have___uint16@ // the windows (vc7) format
typedef __int32 int32;
typedef __uint32 uint32;
typedef __int64 int64;
typedef __uint64 uint64;
#else
#error Do not know how to define a 32-bit integer quantity on your system
#endif
// --------------------------------------------------------------------
// These methods are the best way to get access to info about the
// list of commandline flags. Note that these routines are pretty slow.
// GetAllFlags: mostly-complete info about the list, sorted by file.
// ShowUsageWithFlags: pretty-prints the list to stdout (what --help does)
// ShowUsageWithFlagsRestrict: limit to filenames with restrict as a substr
//
// In addition to accessing flags, you can also access argv[0] (the program
// name) and argv (the entire commandline), which we sock away a copy of.
// These variables are static, so you should only set them once.
struct CommandLineFlagInfo {
std::string name; // the name of the flag
std::string type; // the type of the flag: int32, etc
std::string description; // the "help text" associated with the flag
std::string current_value; // the current value, as a string
std::string default_value; // the default value, as a string
std::string filename; // 'cleaned' version of filename holding the flag
};
extern void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
// These two are actually defined in commandlineflags_reporting.cc.
extern void ShowUsageWithFlags(const char *argv0); // what --help does
extern void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict);
extern void SetArgv(int argc, const char** argv);
extern const std::vector<std::string>& GetArgvs(); // all of argv as a vector
extern const char* GetArgv(); // all of argv as a string
extern const char* GetArgv0(); // only argv0
extern uint32 GetArgvSum(); // simple checksum of argv
extern const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
extern const char* ProgramInvocationShortName(); // basename(argv0)
extern const char* ProgramUsage(); // string set by SetUsageMessage()
// --------------------------------------------------------------------
// Normally you access commandline flags by just saying "if (FLAGS_foo)"
// or whatever, and set them by calling "FLAGS_foo = bar" (or, more
// commonly, via the DEFINE_foo macro). But if you need a bit more
// control, we have programmatic ways to get/set the flags as well.
// Return true iff the flagname was found. If is_default_value is not
// NULL, set to true iff the flag's value had never been set explicitly.
// OUTPUT is set to the flag's value, or unchanged if we return false.
extern bool GetCommandLineOption(const char* name, std::string* OUTPUT,
bool *is_default_value = NULL);
// Return true iff the flagname was found. OUTPUT is set to the flag's
// CommandLineFlagInfo or unchanged if we return false.
extern bool GetCommandLineFlagInfo(const char* name,
CommandLineFlagInfo* OUTPUT);
enum FlagSettingMode {
// update the flag's value (can call this multiple times).
SET_FLAGS_VALUE,
// update the flag's value, but *only if* it has not yet been updated
// with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef".
SET_FLAG_IF_DEFAULT,
// set the flag's default value to this. If the flag has not yet updated
// yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef")
// change the flag's current value to the new default value as well.
SET_FLAGS_DEFAULT
};
// Set a particular flag ("command line option"). Returns a string
// describing the new value that the option has been set to. The
// return value API is not well-specified, so basically just depend on
// it to be empty if the setting failed for some reason -- the name is
// not a valid flag name, or the value is not a valid value -- and
// non-empty else.
// SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case)
extern std::string SetCommandLineOption(const char* name, const char* value);
extern std::string SetCommandLineOptionWithMode(const char* name, const char* value,
FlagSettingMode set_mode);
// --------------------------------------------------------------------
// Saves the states (value, default value, whether the user has set
// the flag, etc) of all flags, and restores them when the FlagSaver
// is destroyed. This is very useful in tests, say, when you want to
// let your tests change the flags, but make sure that they get
// reverted to the original states when your test is complete.
//
// Example usage:
// void TestFoo() {
// FlagSaver s1;
// FLAG_foo = false;
// FLAG_bar = "some value";
//
// // test happens here. You can return at any time
// // without worrying about restoring the FLAG values.
// }
//
// Note: This class is marked with __attribute__((unused)) because all the
// work is done in the constructor and destructor, so in the standard
// usage example above, the compiler would complain that it's an
// unused variable.
// This is a trick to work with autoconf, which sets a var to "yes" or "no"
#define HAVE___ATTRIBUTE__yes 1 // will only be referenced if autoconf says yes
class FlagSaver {
public:
FlagSaver();
~FlagSaver();
private:
class FlagSaverImpl* impl_; // we use pimpl here to keep API steady
FlagSaver(const FlagSaver&); // no copying!
void operator=(const FlagSaver&);
}
// swig seems to have trouble with __attribute__ for some reason
#if !defined SWIG && defined HAVE___ATTRIBUTE__@ac_cv___attribute__@
__attribute__ ((unused))
#endif
;
// --------------------------------------------------------------------
// Some deprecated or hopefully-soon-to-be-deprecated functions.
// This is often used for logging. TODO(csilvers): figure out a better way
extern std::string CommandlineFlagsIntoString();
// DEPRECATED. Usually where this is used, a FlagSaver should be used instead.
extern bool ReadFlagsFromString(const std::string& flagfilecontents,
const char* prog_name,
bool errors_are_fatal); // uses SET_FLAGS_VALUE
// These let you manually implement --flagfile functionality.
// DEPRECATED.
extern bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
extern bool SaveCommandFlags(); // actually defined in google.cc !
extern bool ReadFromFlagsFile(const std::string& filename, const char* prog_name,
bool errors_are_fatal); // uses SET_FLAGS_VALUE
// --------------------------------------------------------------------
// Useful routines for initializing flags from the environment.
// In each case, if 'varname' does not exist in the environment
// return defval. If 'varname' does exist but is not valid
// (e.g., not a number for an int32 flag), abort with an error.
// Otherwise, return the value. NOTE: for booleans, for true use
// 't' or 'T' or 'true' or '1', for false 'f' or 'F' or 'false' or '0'.
extern bool BoolFromEnv(const char *varname, bool defval);
extern int32 Int32FromEnv(const char *varname, int32 defval);
extern int64 Int64FromEnv(const char *varname, int64 defval);
extern uint64 Uint64FromEnv(const char *varname, uint64 defval);
extern double DoubleFromEnv(const char *varname, double defval);
extern const char *StringFromEnv(const char *varname, const char *defval);
// --------------------------------------------------------------------
// The next two functions parse commandlineflags from main():
// Set the "usage" message for this program. For example:
// string usage("This program does nothing. Sample usage:\n");
// usage += argv[0] + " <uselessarg1> <uselessarg2>";
// SetUsageMessage(usage);
// Do not include commandline flags in the usage: we do that for you!
extern void SetUsageMessage(const std::string& usage);
// Looks for flags in argv and parses them. Rearranges argv to put
// flags first, or removes them entirely if remove_flags is true.
// See top-of-file for more details on this function.
#ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead.
extern uint32 ParseCommandLineFlags(int *argc, char*** argv,
bool remove_flags);
#endif
// Calls to ParseCommandLineNonHelpFlags and then to
// HandleCommandLineHelpFlags can be used instead of a call to
// ParseCommandLineFlags during initialization, in order to allow for
// changing default values for some FLAGS (via
// e.g. SetCommandLineOptionWithMode calls) between the time of
// command line parsing and the time of dumping help information for
// the flags as a result of command line parsing.
extern uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv,
bool remove_flags);
// This is actually defined in commandlineflags_reporting.cc.
// This function is misnamed (it also handles --version, etc.), but
// it's too late to change that now. :-(
extern void HandleCommandLineHelpFlags(); // in commandlineflags_reporting.cc
// Allow command line reparsing. Disables the error normaly generated
// when an unknown flag is found, since it may be found in a later parse.
extern void AllowCommandLineReparsing();
// Reparse the flags that have not yet been recognized.
// Only flags registered since the last parse will be recognized.
// Any flag value must be provided as part of the argument using "=",
// not as a separate command line argument that follows the flag argument.
// Intended for handling flags from dynamically loaded libraries,
// since their flags are not registered until they are loaded.
extern uint32 ReparseCommandLineNonHelpFlags();
// --------------------------------------------------------------------
// Now come the command line flag declaration/definition macros that
// will actually be used. They're kind of hairy. A major reason
// for this is initialization: we want people to be able to access
// variables in global constructors and have that not crash, even if
// their global constructor runs before the global constructor here.
// (Obviously, we can't guarantee the flags will have the correct
// default value in that case, but at least accessing them is safe.)
// The only way to do that is have flags point to a static buffer.
// So we make one, using a union to ensure proper alignment, and
// then use placement-new to actually set up the flag with the
// correct default value. In the same vein, we have to worry about
// flag access in global destructors, so FlagRegisterer has to be
// careful never to destroy the flag-values it constructs.
//
// Note that when we define a flag variable FLAGS_<name>, we also
// preemptively define a junk variable, FLAGS_no<name>. This is to
// cause a link-time error if someone tries to define 2 flags with
// names like "logging" and "nologging". We do this because a bool
// flag FLAG can be set from the command line to true with a "-FLAG"
// argument, and to false with a "-noFLAG" argument, and so this can
// potentially avert confusion.
//
// We also put flags into their own namespace. It is purposefully
// named in an opaque way that people should have trouble typing
// directly. The idea is that DEFINE puts the flag in the weird
// namespace, and DECLARE imports the flag from there into the current
// namespace. The net result is to force people to use DECLARE to get
// access to a flag, rather than saying "extern bool FLAGS_whatever;"
// or some such instead. We want this so we can put extra
// functionality (like sanity-checking) in DECLARE if we want, and
// make sure it is picked up everywhere.
//
// We also put the type of the variable in the namespace, so that
// people can't DECLARE_int32 something that they DEFINE_bool'd
// elsewhere.
class FlagRegisterer {
public:
FlagRegisterer(const char* name, const char* type,
const char* help, const char* filename,
void* current_storage, void* defvalue_storage);
private:
class CommandLineFlag* flag_;
};
// namespc should be 'std::', and type 'string', for a var of type 'std::string'
#define DECLARE_VARIABLE(namespc, type, name) \
namespace Flag_Names_##type { \
extern namespc type& FLAGS_##name; \
} \
using Flag_Names_##type::FLAGS_##name
#define DEFINE_VARIABLE(namespc, type, name, value, help) \
namespace Flag_Names_##type { \
static union { void* align; char store[sizeof(namespc type)]; } cur_##name;\
static union { void* align; char store[sizeof(namespc type)]; } dfl_##name;\
static @ac_google_namespace@::FlagRegisterer object_##name( \
#name, #type, help, __FILE__, \
new (cur_##name.store) namespc type(value), \
new (dfl_##name.store) namespc type(value)); \
namespc type& FLAGS_##name = \
*(reinterpret_cast<namespc type*>(cur_##name.store)); \
char FLAGS_no##name; \
} \
using Flag_Names_##type::FLAGS_##name
#ifndef SWIG // In swig, ignore the main flag declarations
#define DECLARE_bool(name) DECLARE_VARIABLE(, bool, name)
#define DEFINE_bool(name, val, txt) DEFINE_VARIABLE(, bool, name, val, txt)
#define DECLARE_int32(name) DECLARE_VARIABLE(@ac_google_namespace@::,int32, name)
#define DEFINE_int32(name, val, txt) DEFINE_VARIABLE(@ac_google_namespace@::,int32, name, val, txt)
#define DECLARE_int64(name) DECLARE_VARIABLE(@ac_google_namespace@::,int64, name)
#define DEFINE_int64(name, val, txt) DEFINE_VARIABLE(@ac_google_namespace@::,int64, name, val, txt)
#define DECLARE_uint64(name) DECLARE_VARIABLE(@ac_google_namespace@::,uint64, name)
#define DEFINE_uint64(name, val, txt) DEFINE_VARIABLE(@ac_google_namespace@::,uint64, name, val, txt)
#define DECLARE_double(name) DECLARE_VARIABLE(, double, name)
#define DEFINE_double(name, val, txt) DEFINE_VARIABLE(, double, name, val, txt)
#define DECLARE_string(name) DECLARE_VARIABLE(std::, string, name)
#define DEFINE_string(name, val, txt) DEFINE_VARIABLE(std::, string, name, val, txt)
#endif // SWIG
@ac_google_end_namespace@
#endif // BASE_COMMANDLINEFLAGS_H__

348
src/mutex.h Normal file
View file

@ -0,0 +1,348 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
//
// A simple mutex wrapper, supporting locks and read-write locks.
// You should assume the locks are *not* re-entrant.
//
// This class is meant to be internal-only and should be wrapped by an
// internal namespace. Before you use this module, please give the
// name of your internal namespace for this module. Or, if you want
// to expose it, you'll want to move it to the Google namespace. We
// cannot put this class in global namespace because there can be some
// problems when we have multiple versions of Mutex in each shared object.
//
// NOTE: by default, we have #ifdef'ed out the TryLock() method.
// This is for two reasons:
// 1) TryLock() under Windows is a bit annoying (it requires a
// #define to be defined very early).
// 2) TryLock() is broken for NO_THREADS mode, at least in NDEBUG
// mode.
// If you need TryLock(), and either these two caveats are not a
// problem for you, or you're willing to work around them, then
// feel free to #define GMUTEX_TRYLOCK, or to remove the #ifdefs
// in the code below.
//
// CYGWIN NOTE: Cygwin support for rwlock seems to be buggy:
// http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html
// Because of that, we might as well use windows locks for
// cygwin. They seem to be more reliable than the cygwin pthreads layer.
//
// TRICKY IMPLEMENTATION NOTE:
// This class is designed to be safe to use during
// dynamic-initialization -- that is, by global constructors that are
// run before main() starts. The issue in this case is that
// dynamic-initialization happens in an unpredictable order, and it
// could be that someone else's dynamic initializer could call a
// function that tries to acquire this mutex -- but that all happens
// before this mutex's constructor has run. (This can happen even if
// the mutex and the function that uses the mutex are in the same .cc
// file.) Basically, because Mutex does non-trivial work in its
// constructor, it's not, in the naive implementation, safe to use
// before dynamic initialization has run on it.
//
// The solution used here is to pair the actual mutex primitive with a
// bool that is set to true when the mutex is dynamically initialized.
// (Before that it's false.) Then we modify all mutex routines to
// look at the bool, and not try to lock/unlock until the bool makes
// it to true (which happens after the Mutex constructor has run.)
//
// This works because before main() starts -- particularly, during
// dynamic initialization -- there are no threads, so a) it's ok that
// the mutex operations are a no-op, since we don't need locking then
// anyway; and b) we can be quite confident our bool won't change
// state between a call to Lock() and a call to Unlock() (that would
// require a global constructor in one translation unit to call Lock()
// and another global constructor in another translation unit to call
// Unlock() later, which is pretty perverse).
//
// That said, it's tricky, and can conceivably fail; it's safest to
// avoid trying to acquire a mutex in a global constructor, if you
// can. One way it can fail is that a really smart compiler might
// initialize the bool to true at static-initialization time (too
// early) rather than at dynamic-initialization time. To discourage
// that, we set is_safe_ to true in code (not the constructor
// colon-initializer) and set it to true via a function that always
// evaluates to true, but that the compiler can't know always
// evaluates to true. This should be good enough.
//
// A related issue is code that could try to access the mutex
// after it's been destroyed in the global destructors (because
// the Mutex global destructor runs before some other global
// destructor, that tries to acquire the mutex). The way we
// deal with this is by taking a constructor arg that global
// mutexes should pass in, that causes the destructor to do no
// work. We still depend on the compiler not doing anything
// weird to a Mutex's memory after it is destroyed, but for a
// static global variable, that's pretty safe.
#ifndef GFLAGS_MUTEX_H_
#define GFLAGS_MUTEX_H_
#include "gflags/gflags_declare.h" // to figure out pthreads support
#if defined(NO_THREADS)
typedef int MutexType; // to keep a lock-count
#elif defined(OS_WINDOWS)
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN // We only need minimal includes
# endif
# ifndef NOMINMAX
# define NOMINMAX // Don't want windows to override min()/max()
# endif
# ifdef GMUTEX_TRYLOCK
// We need Windows NT or later for TryEnterCriticalSection(). If you
// don't need that functionality, you can remove these _WIN32_WINNT
// lines, and change TryLock() to assert(0) or something.
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0400
# endif
# endif
# include <windows.h>
typedef CRITICAL_SECTION MutexType;
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
// Needed for pthread_rwlock_*. If it causes problems, you could take it
// out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it
// *does* cause problems for FreeBSD, or MacOSX, but isn't needed
// for locking there.)
# ifdef __linux__
# if _XOPEN_SOURCE < 500 // including not being defined at all
# undef _XOPEN_SOURCE
# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
# endif
# endif
# include <pthread.h>
typedef pthread_rwlock_t MutexType;
#elif defined(HAVE_PTHREAD)
# include <pthread.h>
typedef pthread_mutex_t MutexType;
#else
# error Need to implement mutex.h for your architecture, or #define NO_THREADS
#endif
#include <assert.h>
#include <stdlib.h> // for abort()
#define MUTEX_NAMESPACE gflags_mutex_namespace
namespace MUTEX_NAMESPACE {
class Mutex {
public:
// This is used for the single-arg constructor
enum LinkerInitialized { LINKER_INITIALIZED };
// Create a Mutex that is not held by anybody. This constructor is
// typically used for Mutexes allocated on the heap or the stack.
inline Mutex();
// This constructor should be used for global, static Mutex objects.
// It inhibits work being done by the destructor, which makes it
// safer for code that tries to acqiure this mutex in their global
// destructor.
explicit inline Mutex(LinkerInitialized);
// Destructor
inline ~Mutex();
inline void Lock(); // Block if needed until free then acquire exclusively
inline void Unlock(); // Release a lock acquired via Lock()
#ifdef GMUTEX_TRYLOCK
inline bool TryLock(); // If free, Lock() and return true, else return false
#endif
// Note that on systems that don't support read-write locks, these may
// be implemented as synonyms to Lock() and Unlock(). So you can use
// these for efficiency, but don't use them anyplace where being able
// to do shared reads is necessary to avoid deadlock.
inline void ReaderLock(); // Block until free or shared then acquire a share
inline void ReaderUnlock(); // Release a read share of this Mutex
inline void WriterLock() { Lock(); } // Acquire an exclusive lock
inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
private:
MutexType mutex_;
// We want to make sure that the compiler sets is_safe_ to true only
// when we tell it to, and never makes assumptions is_safe_ is
// always true. volatile is the most reliable way to do that.
volatile bool is_safe_;
// This indicates which constructor was called.
bool destroy_;
inline void SetIsSafe() { is_safe_ = true; }
// Catch the error of writing Mutex when intending MutexLock.
explicit Mutex(Mutex* /*ignored*/) {}
// Disallow "evil" constructors
Mutex(const Mutex&);
void operator=(const Mutex&);
};
// Now the implementation of Mutex for various systems
#if defined(NO_THREADS)
// When we don't have threads, we can be either reading or writing,
// but not both. We can have lots of readers at once (in no-threads
// mode, that's most likely to happen in recursive function calls),
// but only one writer. We represent this by having mutex_ be -1 when
// writing and a number > 0 when reading (and 0 when no lock is held).
//
// In debug mode, we assert these invariants, while in non-debug mode
// we do nothing, for efficiency. That's why everything is in an
// assert.
Mutex::Mutex() : mutex_(0) { }
Mutex::Mutex(Mutex::LinkerInitialized) : mutex_(0) { }
Mutex::~Mutex() { assert(mutex_ == 0); }
void Mutex::Lock() { assert(--mutex_ == -1); }
void Mutex::Unlock() { assert(mutex_++ == -1); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; }
#endif
void Mutex::ReaderLock() { assert(++mutex_ > 0); }
void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
#elif defined(OS_WINDOWS)
Mutex::Mutex() : destroy_(true) {
InitializeCriticalSection(&mutex_);
SetIsSafe();
}
Mutex::Mutex(LinkerInitialized) : destroy_(false) {
InitializeCriticalSection(&mutex_);
SetIsSafe();
}
Mutex::~Mutex() { if (destroy_) DeleteCriticalSection(&mutex_); }
void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); }
void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
TryEnterCriticalSection(&mutex_) != 0 : true; }
#endif
void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks
void Mutex::ReaderUnlock() { Unlock(); }
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
Mutex::Mutex() : destroy_(true) {
SetIsSafe();
if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
}
Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
SetIsSafe();
if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
}
Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_rwlock_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
pthread_rwlock_trywrlock(&mutex_) == 0 : true; }
#endif
void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); }
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#undef SAFE_PTHREAD
#elif defined(HAVE_PTHREAD)
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
Mutex::Mutex() : destroy_(true) {
SetIsSafe();
if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
}
Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
SetIsSafe();
if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
}
Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_mutex_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
pthread_mutex_trylock(&mutex_) == 0 : true; }
#endif
void Mutex::ReaderLock() { Lock(); }
void Mutex::ReaderUnlock() { Unlock(); }
#undef SAFE_PTHREAD
#endif
// --------------------------------------------------------------------------
// Some helper classes
// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
class MutexLock {
public:
explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
~MutexLock() { mu_->Unlock(); }
private:
Mutex * const mu_;
// Disallow "evil" constructors
MutexLock(const MutexLock&);
void operator=(const MutexLock&);
};
// ReaderMutexLock and WriterMutexLock do the same, for rwlocks
class ReaderMutexLock {
public:
explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
~ReaderMutexLock() { mu_->ReaderUnlock(); }
private:
Mutex * const mu_;
// Disallow "evil" constructors
ReaderMutexLock(const ReaderMutexLock&);
void operator=(const ReaderMutexLock&);
};
class WriterMutexLock {
public:
explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
~WriterMutexLock() { mu_->WriterUnlock(); }
private:
Mutex * const mu_;
// Disallow "evil" constructors
WriterMutexLock(const WriterMutexLock&);
void operator=(const WriterMutexLock&);
};
// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
} // namespace MUTEX_NAMESPACE
#endif /* #define GFLAGS_MUTEX_H__ */

373
src/util.h Normal file
View file

@ -0,0 +1,373 @@
// Copyright (c) 2011, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
//
// Some generically useful utility routines that in google-land would
// be their own projects. We make a shortened version here.
#ifndef GFLAGS_UTIL_H_
#define GFLAGS_UTIL_H_
#include "config.h"
#include <assert.h>
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#include <stdarg.h> // for va_*
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <errno.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h> // for mkdir
#endif
namespace GFLAGS_NAMESPACE {
// This is used for unittests for death-testing. It is defined in gflags.cc.
extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int);
// Work properly if either strtoll or strtoq is on this system.
#if defined(strtoll) || defined(HAVE_STRTOLL)
# define strto64 strtoll
# define strtou64 strtoull
#elif defined(HAVE_STRTOQ)
# define strto64 strtoq
# define strtou64 strtouq
// Neither strtoll nor strtoq are defined. I hope strtol works!
#else
# define strto64 strtol
# define strtou64 strtoul
#endif
// If we have inttypes.h, it will have defined PRId32/etc for us.
// If not, take our best guess.
#ifndef PRId32
# define PRId32 "d"
#endif
#ifndef PRId64
# define PRId64 "lld"
#endif
#ifndef PRIu64
# define PRIu64 "llu"
#endif
typedef signed char int8;
typedef unsigned char uint8;
// -- utility macros ---------------------------------------------------------
template <bool b> struct CompileAssert;
template <> struct CompileAssert<true> {};
#define COMPILE_ASSERT(expr, msg) \
enum { assert_##msg = sizeof(CompileAssert<bool(expr)>) }
// Returns the number of elements in an array.
#define arraysize(arr) (sizeof(arr)/sizeof(*(arr)))
// -- logging and testing ---------------------------------------------------
// For now, we ignore the level for logging, and don't show *VLOG's at
// all, except by hand-editing the lines below
#define LOG(level) std::cerr
#define VLOG(level) if (true) {} else std::cerr
#define DVLOG(level) if (true) {} else std::cerr
// CHECK dies with a fatal error if condition is not true. It is *not*
// controlled by NDEBUG, so the check will be executed regardless of
// compilation mode. Therefore, it is safe to do things like:
// CHECK(fp->Write(x) == 4)
// We allow stream-like objects after this for debugging, but they're ignored.
#define EXPECT_TRUE(condition) \
if (true) { \
if (!(condition)) { \
fprintf(stderr, "Check failed: %s\n", #condition); \
exit(1); \
} \
} else std::cerr << ""
#define EXPECT_OP(op, val1, val2) \
if (true) { \
if (!((val1) op (val2))) { \
fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
exit(1); \
} \
} else std::cerr << ""
#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
#define EXPECT_LE(val1, val2) EXPECT_OP(<=, val1, val2)
#define EXPECT_LT(val1, val2) EXPECT_OP(< , val1, val2)
#define EXPECT_GE(val1, val2) EXPECT_OP(>=, val1, val2)
#define EXPECT_GT(val1, val2) EXPECT_OP(> , val1, val2)
#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
// C99 declares isnan and isinf should be macros, so the #ifdef test
// should be reliable everywhere. Of course, it's not, but these
// are testing pertty marginal functionality anyway, so it's ok to
// not-run them even in situations they might, with effort, be made to work.
#ifdef isnan // Some compilers, like sun's for Solaris 10, don't define this
#define EXPECT_NAN(arg) \
do { \
if (!isnan(arg)) { \
fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
exit(1); \
} \
} while (0)
#else
#define EXPECT_NAN(arg)
#endif
#ifdef isinf // Some compilers, like sun's for Solaris 10, don't define this
#define EXPECT_INF(arg) \
do { \
if (!isinf(arg)) { \
fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
exit(1); \
} \
} while (0)
#else
#define EXPECT_INF(arg)
#endif
#define EXPECT_DOUBLE_EQ(val1, val2) \
do { \
if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
exit(1); \
} \
} while (0)
#define EXPECT_STREQ(val1, val2) \
do { \
if (strcmp((val1), (val2)) != 0) { \
fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
exit(1); \
} \
} while (0)
// Call this in a .cc file where you will later call RUN_ALL_TESTS in main().
#define TEST_INIT \
static std::vector<void (*)()> g_testlist; /* the tests to run */ \
static int RUN_ALL_TESTS() { \
std::vector<void (*)()>::const_iterator it; \
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { \
(*it)(); /* The test will error-exit if there's a problem. */ \
} \
fprintf(stderr, "\nPassed %d tests\n\nPASS\n", \
static_cast<int>(g_testlist.size())); \
return 0; \
}
// Note that this macro uses a FlagSaver to keep tests isolated.
#define TEST(a, b) \
struct Test_##a##_##b { \
Test_##a##_##b() { g_testlist.push_back(&Run); } \
static void Run() { \
FlagSaver fs; \
fprintf(stderr, "Running test %s/%s\n", #a, #b); \
RunTest(); \
} \
static void RunTest(); \
}; \
static Test_##a##_##b g_test_##a##_##b; \
void Test_##a##_##b::RunTest()
// This is a dummy class that eases the google->opensource transition.
namespace testing {
class Test {};
}
// Call this in a .cc file where you will later call EXPECT_DEATH
#define EXPECT_DEATH_INIT \
static bool g_called_exit; \
static void CalledExit(int) { g_called_exit = true; }
#define EXPECT_DEATH(fn, msg) \
do { \
g_called_exit = false; \
gflags_exitfunc = &CalledExit; \
fn; \
gflags_exitfunc = &exit; /* set back to its default */ \
if (!g_called_exit) { \
fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
exit(1); \
} \
} while (0)
#define GTEST_HAS_DEATH_TEST 1
// -- path routines ----------------------------------------------------------
// Tries to create the directory path as a temp-dir. If it fails,
// changes path to some directory it *can* create.
#if defined(__MINGW32__)
#include <io.h>
inline void MakeTmpdir(std::string* path) {
if (!path->empty()) {
path->append("/gflags_unittest_testdir");
int err = mkdir(path->c_str());
if (err == 0 || errno == EEXIST) return;
}
// I had trouble creating a directory in /tmp from mingw
*path = "./gflags_unittest";
mkdir(path->c_str());
}
#elif defined(_MSC_VER)
#include <direct.h>
inline void MakeTmpdir(std::string* path) {
if (!path->empty()) {
int err = _mkdir(path->c_str());
if (err == 0 || errno == EEXIST) return;
}
char tmppath_buffer[1024];
int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it
*path = std::string(tmppath_buffer) + "gflags_unittest";
_mkdir(path->c_str());
}
#else
inline void MakeTmpdir(std::string* path) {
if (!path->empty()) {
int err = mkdir(path->c_str(), 0755);
if (err == 0 || errno == EEXIST) return;
}
mkdir("/tmp/gflags_unittest", 0755);
}
#endif
// -- string routines --------------------------------------------------------
inline void InternalStringPrintf(std::string* output, const char* format,
va_list ap) {
char space[128]; // try a small buffer and hope it fits
// It's possible for methods that use a va_list to invalidate
// the data in it upon use. The fix is to make a copy
// of the structure before using it and use that copy instead.
va_list backup_ap;
va_copy(backup_ap, ap);
int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap);
va_end(backup_ap);
if ((bytes_written >= 0) && (static_cast<size_t>(bytes_written) < sizeof(space))) {
output->append(space, bytes_written);
return;
}
// Repeatedly increase buffer size until it fits.
int length = sizeof(space);
while (true) {
if (bytes_written < 0) {
// Older snprintf() behavior. :-( Just try doubling the buffer size
length *= 2;
} else {
// We need exactly "bytes_written+1" characters
length = bytes_written+1;
}
char* buf = new char[length];
// Restore the va_list before we use it again
va_copy(backup_ap, ap);
bytes_written = vsnprintf(buf, length, format, backup_ap);
va_end(backup_ap);
if ((bytes_written >= 0) && (bytes_written < length)) {
output->append(buf, bytes_written);
delete[] buf;
return;
}
delete[] buf;
}
}
// Clears output before writing to it.
inline void SStringPrintf(std::string* output, const char* format, ...) {
va_list ap;
va_start(ap, format);
output->clear();
InternalStringPrintf(output, format, ap);
va_end(ap);
}
inline void StringAppendF(std::string* output, const char* format, ...) {
va_list ap;
va_start(ap, format);
InternalStringPrintf(output, format, ap);
va_end(ap);
}
inline std::string StringPrintf(const char* format, ...) {
va_list ap;
va_start(ap, format);
std::string output;
InternalStringPrintf(&output, format, ap);
va_end(ap);
return output;
}
inline bool SafeGetEnv(const char *varname, std::string &valstr)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400
char *val;
size_t sz;
if (_dupenv_s(&val, &sz, varname) != 0 || !val) return false;
valstr = val;
free(val);
#else
const char * const val = getenv(varname);
if (!val) return false;
valstr = val;
#endif
return true;
}
inline int SafeFOpen(FILE **fp, const char* fname, const char *mode)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400
return fopen_s(fp, fname, mode);
#else
assert(fp != NULL);
*fp = fopen(fname, mode);
// errno only guaranteed to be set on failure
return ((*fp == NULL) ? errno : 0);
#endif
}
} // namespace GFLAGS_NAMESPACE
#endif // GFLAGS_UTIL_H_

73
src/windows_port.cc Normal file
View file

@ -0,0 +1,73 @@
/* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ---
* Author: Craig Silverstein
*/
#ifndef _WIN32
# error You should only be including windows/port.cc in a windows environment!
#endif
#include <string.h> // for strlen(), memset(), memcmp()
#include <assert.h>
#include <stdarg.h> // for va_list, va_start, va_end
#include <windows.h>
#include "windows_port.h"
// These call the windows _vsnprintf, but always NUL-terminate.
#if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */
#if !(defined(_MSC_VER) && _MSC_VER >= 1900) /* msvc 2015 already defines */
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4996) // ignore _vsnprintf security warning
#endif
int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
if (size == 0) // not even room for a \0?
return -1; // not what C99 says to do, but what windows does
str[size-1] = '\0';
return _vsnprintf(str, size-1, format, ap);
}
#ifdef _MSC_VER
# pragma warning(pop)
#endif
int snprintf(char *str, size_t size, const char *format, ...) {
int r;
va_list ap;
va_start(ap, format);
r = vsnprintf(str, size, format, ap);
va_end(ap);
return r;
}
#endif /* if !(defined(_MSC_VER) && _MSC_VER >= 1900) */
#endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */

135
src/windows_port.h Normal file
View file

@ -0,0 +1,135 @@
/* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ---
* Author: Craig Silverstein
*
* These are some portability typedefs and defines to make it a bit
* easier to compile this code under VC++.
*
* Several of these are taken from glib:
* http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
*/
#ifndef GFLAGS_WINDOWS_PORT_H_
#define GFLAGS_WINDOWS_PORT_H_
#include "config.h"
// This must be defined before the windows.h is included.
// It's needed for mutex.h, to give access to the TryLock method.
# if !defined(_WIN32_WINNT) && !(defined( __MINGW32__) || defined(__MINGW64__))
# define _WIN32_WINNT 0x0400
# endif
// We always want minimal includes
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <direct.h> /* for mkdir */
#include <stdlib.h> /* for _putenv, getenv */
#include <stdio.h> /* need this to override stdio's snprintf, also defines _unlink used by unit tests */
#include <stdarg.h> /* util.h uses va_copy */
#include <string.h> /* for _stricmp and _strdup */
/* We can't just use _vsnprintf and _snprintf as drop-in-replacements,
* because they don't always NUL-terminate. :-( We also can't use the
* name vsnprintf, since windows defines that (but not snprintf (!)).
*/
#if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */
#if !(defined(_MSC_VER) && _MSC_VER >= 1900) /* msvc 2015 already defines */
extern GFLAGS_DLL_DECL int snprintf(char *str, size_t size,
const char *format, ...);
extern int GFLAGS_DLL_DECL safe_vsnprintf(char *str, size_t size,
const char *format, va_list ap);
#define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap)
#define va_copy(dst, src) (dst) = (src)
#endif
#endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4996) // ignore getenv security warning
#endif
#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L
inline void setenv(const char* name, const char* value, int) {
// In windows, it's impossible to set a variable to the empty string.
// We handle this by setting it to "0" and the NUL-ing out the \0.
// That is, we putenv("FOO=0") and then find out where in memory the
// putenv wrote "FOO=0", and change it in-place to "FOO=\0".
// c.f. http://svn.apache.org/viewvc/stdcxx/trunk/tests/src/environ.cpp?r1=611451&r2=637508&pathrev=637508
static const char* const kFakeZero = "0";
if (*value == '\0')
value = kFakeZero;
// Apparently the semantics of putenv() is that the input
// must live forever, so we leak memory here. :-(
const size_t nameval_len = strlen(name) + 1 + strlen(value) + 1;
char* nameval = reinterpret_cast<char*>(malloc(nameval_len));
snprintf(nameval, nameval_len, "%s=%s", name, value);
_putenv(nameval);
if (value == kFakeZero) {
nameval[nameval_len - 2] = '\0'; // works when putenv() makes no copy
if (*getenv(name) != '\0')
*getenv(name) = '\0'; // works when putenv() copies nameval
}
}
#endif
#ifdef _MSC_VER
# pragma warning(pop)
#endif
#define strcasecmp _stricmp
#if defined(_MSC_VER) && _MSC_VER >= 1400
#define strdup _strdup
#define unlink _unlink
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1800
#include <inttypes.h>
#else
#define PRId32 "d"
#define PRIu32 "u"
#define PRId64 "I64d"
#define PRIu64 "I64u"
#endif
#if !defined(__MINGW32__) && !defined(__MINGW64__)
#define strtoq _strtoi64
#define strtouq _strtoui64
#define strtoll _strtoi64
#define strtoull _strtoui64
#define atoll _atoi64
#endif
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#endif /* GFLAGS_WINDOWS_PORT_H_ */

227
test/CMakeLists.txt Normal file
View file

@ -0,0 +1,227 @@
## gflags tests
# ----------------------------------------------------------------------------
# output directories
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
# set working directory of test commands
set (GFLAGS_FLAGFILES_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
# ----------------------------------------------------------------------------
# common include directories and link libraries
include_directories ("${CMAKE_CURRENT_SOURCE_DIR}")
include_directories ("${gflags_SOURCE_DIR}/src")
include_directories ("${gflags_BINARY_DIR}/include")
include_directories ("${gflags_BINARY_DIR}/include/gflags")
if (BUILD_SHARED_LIBS)
set (type shared)
if (GFLAGS_IS_A_DLL)
add_definitions(-DGFLAGS_IS_A_DLL)
endif ()
else ()
set (type static)
endif ()
if (BUILD_gflags_LIB)
link_libraries (gflags_${type})
else ()
link_libraries (gflags_nothreads_${type})
endif ()
# ----------------------------------------------------------------------------
# STRIP_FLAG_HELP
add_executable (gflags_strip_flags_test gflags_strip_flags_test.cc)
# Make sure the --help output doesn't print the stripped text.
add_gflags_test (strip_flags_help 1 "" "This text should be stripped out" gflags_strip_flags_test --help)
# Make sure the stripped text isn't in the binary at all.
add_test (
NAME strip_flags_binary
COMMAND "${CMAKE_COMMAND}" "-DBINARY=$<TARGET_FILE:gflags_strip_flags_test>"
-P "${CMAKE_CURRENT_SOURCE_DIR}/gflags_strip_flags_test.cmake"
CONFIGURATIONS Release MinSizeRel
)
# ----------------------------------------------------------------------------
# unit tests
configure_file (gflags_unittest.cc gflags_unittest-main.cc COPYONLY)
configure_file (gflags_unittest.cc gflags_unittest_main.cc COPYONLY)
add_executable (gflags_unittest gflags_unittest.cc)
add_executable (gflags_unittest-main gflags_unittest-main.cc)
add_executable (gflags_unittest_main gflags_unittest_main.cc)
if (OS_WINDOWS)
set (SLASH "\\\\")
else ()
set (SLASH "/")
endif ()
# First, just make sure the gflags_unittest works as-is
add_gflags_test(unittest 0 "" "" gflags_unittest)
# --help should show all flags, including flags from gflags_reporting
add_gflags_test(help-reporting 1 "${SLASH}gflags_reporting.cc:" "" gflags_unittest --help)
# Make sure that --help prints even very long helpstrings.
add_gflags_test(long-helpstring 1 "end of a long helpstring" "" gflags_unittest --help)
# Make sure --help reflects flag changes made before flag-parsing
add_gflags_test(changed_bool1 1 "-changed_bool1 (changed) type: bool default: true" "" gflags_unittest --help)
add_gflags_test(changed_bool2 1 "-changed_bool2 (changed) type: bool default: false currently: true" "" gflags_unittest --help)
# And on the command-line, too
add_gflags_test(changeable_string_var 1 "-changeable_string_var () type: string default: \"1\" currently: \"2\"" "" gflags_unittest --changeable_string_var 2 --help)
# --nohelp and --help=false should be as if we didn't say anything
add_gflags_test(nohelp 0 "PASS" "" gflags_unittest --nohelp)
add_gflags_test(help=false 0 "PASS" "" gflags_unittest --help=false)
# --helpful is the same as help
add_gflags_test(helpful 1 "${SLASH}gflags_reporting.cc:" "" gflags_unittest --helpful)
# --helpshort should show only flags from the gflags_unittest itself
add_gflags_test(helpshort 1 "${SLASH}gflags_unittest.cc:" "${SLASH}gflags_reporting.cc:" gflags_unittest --helpshort)
# --helpshort should show the tldflag we created in the gflags_unittest dir
add_gflags_test(helpshort-tldflag1 1 "tldflag1" "${SLASH}google.cc:" gflags_unittest --helpshort)
add_gflags_test(helpshort-tldflag2 1 "tldflag2" "${SLASH}google.cc:" gflags_unittest --helpshort)
# --helpshort should work if the main source file is suffixed with [_-]main
add_gflags_test(helpshort-main 1 "${SLASH}gflags_unittest-main.cc:" "${SLASH}gflags_reporting.cc:" gflags_unittest-main --helpshort)
add_gflags_test(helpshort_main 1 "${SLASH}gflags_unittest_main.cc:" "${SLASH}gflags_reporting.cc:" gflags_unittest_main --helpshort)
# --helpon needs an argument
add_gflags_test(helpon 1 "'--helpon' is missing its argument; flag description: show help on" "" gflags_unittest --helpon)
# --helpon argument indicates what file we'll show args from
add_gflags_test(helpon=gflags 1 "${SLASH}gflags.cc:" "${SLASH}gflags_unittest.cc:" gflags_unittest --helpon=gflags)
# another way of specifying the argument
add_gflags_test(helpon_gflags 1 "${SLASH}gflags.cc:" "${SLASH}gflags_unittest.cc:" gflags_unittest --helpon gflags)
# test another argument
add_gflags_test(helpon=gflags_unittest 1 "${SLASH}gflags_unittest.cc:" "${SLASH}gflags.cc:" gflags_unittest --helpon=gflags_unittest)
# helpmatch is like helpon but takes substrings
add_gflags_test(helpmatch_reporting 1 "${SLASH}gflags_reporting.cc:" "${SLASH}gflags_unittest.cc:" gflags_unittest -helpmatch reporting)
add_gflags_test(helpmatch=unittest 1 "${SLASH}gflags_unittest.cc:" "${SLASH}gflags.cc:" gflags_unittest -helpmatch=unittest)
# if no flags are found with helpmatch or helpon, suggest --help
add_gflags_test(helpmatch=nosuchsubstring 1 "No modules matched" "${SLASH}gflags_unittest.cc:" gflags_unittest -helpmatch=nosuchsubstring)
add_gflags_test(helpon=nosuchmodule 1 "No modules matched" "${SLASH}gflags_unittest.cc:" gflags_unittest -helpon=nosuchmodule)
# helppackage shows all the flags in the same dir as this unittest
# --help should show all flags, including flags from google.cc
add_gflags_test(helppackage 1 "${SLASH}gflags_reporting.cc:" "" gflags_unittest --helppackage)
# xml!
add_gflags_test(helpxml 1 "${SLASH}gflags_unittest.cc</file>" "${SLASH}gflags_unittest.cc:" gflags_unittest --helpxml)
# just print the version info and exit
add_gflags_test(version-1 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --version)
add_gflags_test(version-2 0 "version test_version" "${SLASH}gflags_unittest.cc:" gflags_unittest --version)
# --undefok is a fun flag...
add_gflags_test(undefok-1 1 "unknown command line flag 'foo'" "" gflags_unittest --undefok= --foo --unused_bool)
add_gflags_test(undefok-2 0 "PASS" "" gflags_unittest --undefok=foo --foo --unused_bool)
# If you say foo is ok to be undefined, we'll accept --nofoo as well
add_gflags_test(undefok-3 0 "PASS" "" gflags_unittest --undefok=foo --nofoo --unused_bool)
# It's ok if the foo is in the middle
add_gflags_test(undefok-4 0 "PASS" "" gflags_unittest --undefok=fee,fi,foo,fum --foo --unused_bool)
# But the spelling has to be just right...
add_gflags_test(undefok-5 1 "unknown command line flag 'foo'" "" gflags_unittest --undefok=fo --foo --unused_bool)
add_gflags_test(undefok-6 1 "unknown command line flag 'foo'" "" gflags_unittest --undefok=foot --foo --unused_bool)
# See if we can successfully load our flags from the flagfile
add_gflags_test(flagfile.1 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest "--flagfile=flagfile.1")
add_gflags_test(flagfile.2 0 "PASS" "" gflags_unittest "--flagfile=flagfile.2")
add_gflags_test(flagfile.3 0 "PASS" "" gflags_unittest "--flagfile=flagfile.3")
# Also try to load flags from the environment
add_gflags_test(fromenv=version 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --fromenv=version)
add_gflags_test(tryfromenv=version 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --tryfromenv=version)
add_gflags_test(fromenv=help 0 "PASS" "" gflags_unittest --fromenv=help)
add_gflags_test(tryfromenv=help 0 "PASS" "" gflags_unittest --tryfromenv=help)
add_gflags_test(fromenv=helpful 1 "helpful not found in environment" "" gflags_unittest --fromenv=helpful)
add_gflags_test(tryfromenv=helpful 0 "PASS" "" gflags_unittest --tryfromenv=helpful)
add_gflags_test(tryfromenv=undefok 0 "PASS" "" gflags_unittest --tryfromenv=undefok --foo)
add_gflags_test(tryfromenv=weirdo 1 "unknown command line flag" "" gflags_unittest --tryfromenv=weirdo)
add_gflags_test(tryfromenv-multiple 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --tryfromenv=test_bool,version,unused_bool)
add_gflags_test(fromenv=test_bool 1 "not found in environment" "" gflags_unittest --fromenv=test_bool)
add_gflags_test(fromenv=test_bool-ok 1 "unknown command line flag" "" gflags_unittest --fromenv=test_bool,ok)
# Here, the --version overrides the fromenv
add_gflags_test(version-overrides-fromenv 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --fromenv=test_bool,version,ok)
# Make sure -- by itself stops argv processing
add_gflags_test(dashdash 0 "PASS" "" gflags_unittest -- --help)
# And we should die if the flag value doesn't pass the validator
add_gflags_test(always_fail 1 "ERROR: failed validation of new value 'true' for flag 'always_fail'" "" gflags_unittest --always_fail)
# And if locking in validators fails
# TODO(andreas): Worked on Windows 7 Release configuration, but causes
# debugger abort() intervention in case of Debug configuration.
#add_gflags_test(deadlock_if_cant_lock 0 "PASS" "" gflags_unittest --deadlock_if_cant_lock)
# ----------------------------------------------------------------------------
# use gflags_declare.h
add_executable (gflags_declare_test gflags_declare_test.cc gflags_declare_flags.cc)
add_test(NAME gflags_declare COMMAND gflags_declare_test --message "Hello gflags!")
set_tests_properties(gflags_declare PROPERTIES PASS_REGULAR_EXPRESSION "Hello gflags!")
# ----------------------------------------------------------------------------
# qnx specific test installation (ctest not compatible)
if (QNX)
install (
DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
DESTINATION ${RUNTIME_INSTALL_DIR}/gflags_tests
)
install (
DIRECTORY ${PROJECT_SOURCE_DIR}/test/
DESTINATION ${RUNTIME_INSTALL_DIR}/gflags_tests
FILES_MATCHING
PATTERN "flagfile.*"
PATTERN "gflags_unittest_flagfile"
PATTERN "config" EXCLUDE
PATTERN "nc" EXCLUDE
)
endif ()
# ----------------------------------------------------------------------------
# configure Python script which configures and builds a test project
if (BUILD_NC_TESTS OR BUILD_CONFIG_TESTS)
find_package (PythonInterp)
if (NOT PYTHON_EXECUTABLE)
message (FATAL_ERROR "No Python installation found! It is required by the (negative) compilation tests."
" Either install Python or set BUILD_NC_TESTS and BUILD_CONFIG_TESTS to FALSE.")
endif ()
set (TMPDIR "${PROJECT_BINARY_DIR}/Testing/Temporary")
configure_file (gflags_build.py.in "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/build.py" @ONLY)
function (add_gflags_build_test name srcdir expect_fail)
set (srcdir "${CMAKE_CURRENT_SOURCE_DIR}/${srcdir}")
add_test (
NAME "${name}"
COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/build.py"
${name} ${srcdir} ${expect_fail}
)
endfunction ()
endif ()
# ----------------------------------------------------------------------------
# negative compilation tests
option (BUILD_NC_TESTS "Request addition of negative compilation tests." OFF)
mark_as_advanced (BUILD_NC_TESTS)
if (BUILD_NC_TESTS)
add_gflags_build_test (nc_sanity nc 0)
add_gflags_build_test (nc_swapped_args nc 1)
add_gflags_build_test (nc_int_instead_of_bool nc 1)
add_gflags_build_test (nc_bool_in_quotes nc 1)
add_gflags_build_test (nc_define_string_with_0 nc 1)
endif ()
# ----------------------------------------------------------------------------
# build configuration test
option (BUILD_CONFIG_TESTS "Request addition of package configuration tests." OFF)
mark_as_advanced (BUILD_CONFIG_TESTS)
if (BUILD_CONFIG_TESTS)
add_gflags_build_test (cmake_config config 0)
endif ()

View file

@ -0,0 +1,10 @@
## gflags package configuration tests
cmake_minimum_required (VERSION 3.5 FATAL_ERROR)
project (gflags_${TEST_NAME})
find_package (gflags REQUIRED)
add_executable (foo main.cc)
target_link_libraries (foo gflags::gflags)

20
test/config/main.cc Normal file
View file

@ -0,0 +1,20 @@
#include <iostream>
#include <gflags/gflags.h>
DEFINE_string(message, "Hello World!", "The message to print");
static bool ValidateMessage(const char* flagname, const std::string &message)
{
return !message.empty();
}
DEFINE_validator(message, ValidateMessage);
int main(int argc, char **argv)
{
gflags::SetUsageMessage("Test CMake configuration of gflags library (gflags-config.cmake)");
gflags::SetVersionString("0.1");
gflags::ParseCommandLineFlags(&argc, &argv, true);
std::cout << FLAGS_message << std::endl;
gflags::ShutDownCommandLineFlags();
return 0;
}

1
test/flagfile.1 Normal file
View file

@ -0,0 +1 @@
--version

2
test/flagfile.2 Normal file
View file

@ -0,0 +1,2 @@
--foo=bar
--nounused_bool

1
test/flagfile.3 Normal file
View file

@ -0,0 +1 @@
--flagfile=flagfile.2

43
test/gflags_build.py.in Normal file
View file

@ -0,0 +1,43 @@
#!/usr/bin/env python3
import os
import sys
import subprocess
import shutil
CMAKE = '@CMAKE_COMMAND@'
CMAKE_BUILD_TYPE = '@CMAKE_BUILD_TYPE@'
TMPDIR = '@TMPDIR@'
SRCDIR = '@SRCDIR@'
GFLAGS_DIR = '@gflags_BINARY_DIR@'
if __name__ == "__main__":
if len(sys.argv) != 4:
sys.stderr.write(' '.join(['usage:', sys.argv[0], '<test_name> <srcdir> <expect_fail:0|1>\n']))
sys.exit(1)
test_name = sys.argv[1]
srcdir = sys.argv[2]
expect_fail = (sys.argv[3].lower() in ['true', 'yes', 'on', '1'])
bindir = os.path.join(TMPDIR, test_name)
if TMPDIR == '':
sys.stderr.write('Temporary directory not set!\n')
sys.exit(1)
# create build directory
if os.path.isdir(bindir): shutil.rmtree(bindir)
os.makedirs(bindir)
# configure the build tree
if subprocess.call([CMAKE, '-DCMAKE_BUILD_TYPE:STRING='+CMAKE_BUILD_TYPE,
'-Dgflags_DIR:PATH='+GFLAGS_DIR,
'-DTEST_NAME:STRING='+test_name, srcdir], cwd=bindir) != 0:
sys.stderr.write('Failed to configure the build tree!\n')
sys.exit(1)
# build the test project
exit_code = subprocess.call([CMAKE, '--build', bindir, '--config', CMAKE_BUILD_TYPE], cwd=bindir)
if expect_fail == True:
if exit_code == 0:
sys.stderr.write('Build expected to fail, but it succeeded!\n')
sys.exit(1)
else:
sys.stderr.write('Build failed as expected\n')
exit_code = 0
sys.exit(exit_code)

14
test/gflags_declare_flags.cc Executable file
View file

@ -0,0 +1,14 @@
// The macro can already be defined when using Unity builds.
#undef GFLAGS_DLL_DECLARE_FLAG
#define GFLAGS_DLL_DECLARE_FLAG
#include <iostream>
#include <gflags/gflags_declare.h>
DECLARE_string(message); // in gflags_delcare_test.cc
void print_message();
void print_message()
{
std::cout << FLAGS_message << std::endl;
}

View file

@ -0,0 +1,12 @@
#include <gflags/gflags.h>
DEFINE_string(message, "", "The message to print");
void print_message(); // in gflags_declare_flags.cc
int main(int argc, char **argv)
{
GFLAGS_NAMESPACE::SetUsageMessage("Test compilation and use of gflags_declare.h");
GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true);
print_message();
return 0;
}

60
test/gflags_strip_flags_test.cc Executable file
View file

@ -0,0 +1,60 @@
// Copyright (c) 2011, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
// Author: csilvers@google.com (Craig Silverstein)
//
// A simple program that uses STRIP_FLAG_HELP. We'll have a shell
// script that runs 'strings' over this program and makes sure
// that the help string is not in there.
#define STRIP_FLAG_HELP 1
#include <gflags/gflags.h>
#include <stdio.h>
using GFLAGS_NAMESPACE::SetUsageMessage;
using GFLAGS_NAMESPACE::ParseCommandLineFlags;
DEFINE_bool(test, true, "This text should be stripped out");
int main(int argc, char** argv) {
SetUsageMessage("Usage message");
ParseCommandLineFlags(&argc, &argv, false);
// Unfortunately, for us, libtool can replace executables with a shell
// script that does some work before calling the 'real' executable
// under a different name. We need the 'real' executable name to run
// 'strings' on it, so we construct this binary to print the real
// name (argv[0]) on stdout when run.
puts(argv[0]);
return 0;
}

View file

@ -0,0 +1,7 @@
if (NOT BINARY)
message (FATAL_ERROR "BINARY file to check not specified!")
endif ()
file (STRINGS "${BINARY}" strings REGEX "This text should be stripped out")
if (strings)
message (FATAL_ERROR "Text not stripped from binary like it should be: ${BINARY}")
endif ()

1572
test/gflags_unittest.cc Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
--test_flag=1
--test_flag=2

16
test/nc/CMakeLists.txt Normal file
View file

@ -0,0 +1,16 @@
## gflags negative compilation tests
cmake_minimum_required (VERSION 3.5 FATAL_ERROR)
if (NOT TEST_NAME)
message (FATAL_ERROR "Missing TEST_NAME CMake flag")
endif ()
string (TOUPPER ${TEST_NAME} TEST_NAME_UPPER)
project (gflags_${TEST_NAME})
find_package (gflags REQUIRED)
include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/..")
add_definitions (-DTEST_${TEST_NAME_UPPER})
add_executable (gflags_${TEST_NAME} gflags_nc.cc)
target_link_libraries(gflags_${TEST_NAME} gflags)

73
test/nc/gflags_nc.cc Normal file
View file

@ -0,0 +1,73 @@
// Copyright (c) 2009, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
//
// A negative comiple test for gflags.
#include <gflags/gflags.h>
#if defined(TEST_NC_SWAPPED_ARGS)
DEFINE_bool(some_bool_flag,
"the default value should go here, not the description",
false);
#elif defined(TEST_NC_INT_INSTEAD_OF_BOOL)
DEFINE_bool(some_bool_flag_2,
0,
"should have been an int32 flag but mistakenly used bool instead");
#elif defined(TEST_NC_BOOL_IN_QUOTES)
DEFINE_bool(some_bool_flag_3,
"false",
"false in in quotes, which is wrong");
#elif defined(TEST_NC_SANITY)
DEFINE_bool(some_bool_flag_4,
true,
"this is the correct usage of DEFINE_bool");
#elif defined(TEST_NC_DEFINE_STRING_WITH_0)
DEFINE_string(some_string_flag,
0,
"Trying to construct a string by passing 0 would cause a crash.");
#endif
int main(int, char **)
{
return 0;
}