mirror of
https://github.com/gflags/gflags.git
synced 2025-04-09 15:07:00 +00:00
Compare commits
463 commits
Author | SHA1 | Date | |
---|---|---|---|
|
52e94563eb | ||
|
c1f63a168d | ||
|
70c01a642f | ||
|
b364def945 | ||
|
58cf1ef6d0 | ||
|
3c4399ba46 | ||
|
03a4842c9c | ||
|
82793e3f38 | ||
|
c196ce6baa | ||
|
3df39f3a03 | ||
|
a738fdf933 | ||
|
b7fd838331 | ||
|
986e8eed00 | ||
|
9ca7e9ee7a | ||
|
4ace06d024 | ||
|
827c769e5f | ||
|
5d5a6c5501 | ||
|
a386bd0f20 | ||
|
cb68d9eeb8 | ||
|
ae2fae5645 | ||
|
1c86423887 | ||
|
8843f88b69 | ||
|
4405871443 | ||
|
f7388c6655 | ||
|
84968c6bb2 | ||
|
1137acc9e0 | ||
|
ef8e134d48 | ||
|
addd749114 | ||
|
2e227c3daa | ||
|
d9b184bd00 | ||
|
6c8f50b567 | ||
|
6d224d34b6 | ||
|
0b7f8db2c6 | ||
|
f40e43a628 | ||
|
57c5913fb8 | ||
|
2cac878761 | ||
|
28f50e0fed | ||
|
1005485222 | ||
|
be65295633 | ||
|
524b83d026 | ||
|
34819405ab | ||
|
00fcadd9b8 | ||
|
498cfa8b13 | ||
|
e171aa2d15 | ||
|
3d2a101c9e | ||
|
af502c8176 | ||
|
0f439e8407 | ||
|
83fecd3ed0 | ||
|
8411df715c | ||
|
4c0bbc0604 | ||
|
0c7012d647 | ||
|
b051bace27 | ||
|
7e70988188 | ||
|
754d3329a6 | ||
|
82456f220f | ||
|
3e2e349307 | ||
|
c0b1add45f | ||
|
f1ea012a41 | ||
|
b0c4cd29e4 | ||
|
04c8ce76e2 | ||
|
d4a050d173 | ||
|
48677f930d | ||
|
6e536553ef | ||
|
cad38c919c | ||
|
2c49763b73 | ||
|
660603a3df | ||
|
679df49798 | ||
|
48cdc79332 | ||
|
518267d34f | ||
|
f7228d77b5 | ||
|
8b39845d6f | ||
|
9ab4d115cb | ||
|
e292e0452f | ||
|
6d1c363dde | ||
|
77592648e3 | ||
|
23348465a0 | ||
|
60784b53e3 | ||
|
57ceb0ecc8 | ||
|
7d36353579 | ||
|
aa2d0f7b4e | ||
|
4663c80d3a | ||
|
46f73f88b1 | ||
|
66d4386d0e | ||
|
6348ea9d7e | ||
|
3d5bc48dc8 | ||
|
74603f5ed3 | ||
|
4a694e8736 | ||
|
21c7bcd895 | ||
|
95ffb27c9c | ||
|
80ebb424a5 | ||
|
652651b421 | ||
|
9314597d4b | ||
|
48f409438b | ||
|
30dbc81fb5 | ||
|
8935ef4526 | ||
|
20858a49e0 | ||
|
ac6834e979 | ||
|
22ed2ce6c8 | ||
|
f8a0efe03a | ||
|
2f336a2a87 | ||
|
971dd2a4fa | ||
|
c6b937797c | ||
|
84ab952375 | ||
|
78c66b3726 | ||
|
b872d6b5d4 | ||
|
37c4c58371 | ||
|
37e2867335 | ||
|
8f2c22a03f | ||
|
ea6144e243 | ||
|
86d67a3f49 | ||
|
c94a60e2f6 | ||
|
3e7ef74a07 | ||
|
18469830ae | ||
|
3886da50e1 | ||
|
6c0ee003e8 | ||
|
3064f63a6e | ||
|
14c0e93755 | ||
|
cce68f0c9c | ||
|
f4eace1331 | ||
|
408061b469 | ||
|
7d31c02de8 | ||
|
a69b2544d6 | ||
|
15394d356c | ||
|
e58e5303d6 | ||
|
435f949dbb | ||
|
22e4a534c1 | ||
|
c713d2e789 | ||
|
b16653edf0 | ||
|
ec4b5daadf | ||
|
f0be9c88ca | ||
|
78cab6c649 | ||
|
4667f41317 | ||
|
a5a1b28767 | ||
|
7ba9921866 | ||
|
30519426c3 | ||
|
3c0ad4fc9e | ||
|
a1e461d61d | ||
|
46ea10f071 | ||
|
fe57e5af4d | ||
|
fa2663839c | ||
|
5ef4c3c076 | ||
|
2e4159fbe5 | ||
|
3e946c9ebc | ||
|
546819b1d9 | ||
|
0c17f1ee02 | ||
|
ac1a925c2b | ||
|
d701ceac73 | ||
|
7ae23fd1e7 | ||
|
8de80b9a2d | ||
|
eff38cbc18 | ||
|
9353bca5e9 | ||
|
81d8a9234b | ||
|
eaf05340dc | ||
|
74bcd20c0e | ||
|
45341954bc | ||
|
5e3070670f | ||
|
687b2c56d2 | ||
|
58441994df | ||
|
1c8285fd63 | ||
|
ea1cc83b50 | ||
|
12d810d8e6 | ||
|
389ef3f737 | ||
|
752c63249b | ||
|
f9e69b3531 | ||
|
7a21c16f00 | ||
|
a4382e5f37 | ||
|
2de6bf3904 | ||
|
91e16eeff1 | ||
|
b686469597 | ||
|
e50698c200 | ||
|
18cb422451 | ||
|
799e910c74 | ||
|
abe4b10c33 | ||
|
221f327749 | ||
|
2a3454c104 | ||
|
545e9df567 | ||
|
6bd636c964 | ||
|
dd48d704c5 | ||
|
9ef0d5220e | ||
|
02f3189788 | ||
|
92865cee87 | ||
|
8ac4bc41aa | ||
|
b90a325ef3 | ||
|
3ae911f3e7 | ||
|
16651b7870 | ||
|
762f9cbb65 | ||
|
7a69001868 | ||
|
3f968fc16b | ||
|
40b85b18de | ||
|
f9fa30506c | ||
|
b572a72daa | ||
|
03bebcb065 | ||
|
366e9d335c | ||
|
4f100cb6a0 | ||
|
d78b00d2de | ||
|
9db828953a | ||
|
4e61c45ef9 | ||
|
f0523f14a9 | ||
|
4a56d614cf | ||
|
58345b18d9 | ||
|
d4e971c10b | ||
|
16a168763e | ||
|
f4f524df1f | ||
|
73178f0051 | ||
|
e1d15b3340 | ||
|
ed1d91f912 | ||
|
71c656e0e9 | ||
|
73b67041d8 | ||
|
2e5b884fce | ||
|
7eb3d365e3 | ||
|
ccff5658e0 | ||
|
33fc9997bd | ||
|
c3fd5432c3 | ||
|
745082dbd3 | ||
|
73bb1e87c9 | ||
|
5f29c4b940 | ||
|
d7a69edf66 | ||
|
9e937e80fb | ||
|
a9b983a827 | ||
|
f9e1ffaa39 | ||
|
a4bae965eb | ||
|
14e1138441 | ||
|
2861b1c269 | ||
|
06ccc16dec | ||
|
a819f0f019 | ||
|
64ac2e30b6 | ||
|
51f1db7431 | ||
|
35fcdb3b2f | ||
|
3398e7b0c9 | ||
|
13cf9e1b39 | ||
|
afbf3f22ff | ||
|
7fc7826cc1 | ||
|
4b771465b1 | ||
|
76c53b710e | ||
|
2b8deaa5e0 | ||
|
7b5b080a06 | ||
|
64cf9f3249 | ||
|
67dc01d3e0 | ||
|
04c73f86c3 | ||
|
02e8c78f9d | ||
|
957aa3aa62 | ||
|
0133710d47 | ||
|
d8d218ac6f | ||
|
957f0d291c | ||
|
63b9776eee | ||
|
3a49eafd20 | ||
|
6e390924d3 | ||
|
2614f123fd | ||
|
eb89101a1a | ||
|
2a40e19137 | ||
|
376ef823be | ||
|
76cbe0d003 | ||
|
2b81a76bed | ||
|
659b440f9e | ||
|
a93de007a6 | ||
|
05b155ff59 | ||
|
cd7aece14e | ||
|
b8c6fef385 | ||
|
bf889786c2 | ||
|
e160474c52 | ||
|
6828323bc6 | ||
|
31f0e290d6 | ||
|
3c30390ac4 | ||
|
e9144aa159 | ||
|
44d1d163cc | ||
|
d9d06b99a4 | ||
|
55490439d0 | ||
|
e65f49a4cd | ||
|
dc2b2c7fec | ||
|
cac974eb07 | ||
|
44a58145e3 | ||
|
07031f9703 | ||
|
4003103499 | ||
|
cf0619e458 | ||
|
eb3b78a4ff | ||
|
ef5c5474b2 | ||
|
0890b699e9 | ||
|
eb5e1f7fe4 | ||
|
7bc160b304 | ||
|
dc8543a473 | ||
|
9a257c0b66 | ||
|
94c23575c7 | ||
|
0f2751ebfb | ||
|
020dc487c3 | ||
|
0c6e5fdb3f | ||
|
38c4402f58 | ||
|
7c80cfd87c | ||
|
30d045d0ec | ||
|
aff8ef820a | ||
|
38213112a5 | ||
|
4aa1984c51 | ||
|
6040eac5b3 | ||
|
09f7800768 | ||
|
bbe1895559 | ||
|
3fd9fa7000 | ||
|
cf40f73c40 | ||
|
0e1c5ce039 | ||
|
2a9ef084a9 | ||
|
0c15028124 | ||
|
d699559081 | ||
|
04a30c86de | ||
|
882db5d018 | ||
|
33e2cbe2c6 | ||
|
3e96a19026 | ||
|
0100be50ec | ||
|
76f2ffadb4 | ||
|
978c567d02 | ||
|
06ad5027d2 | ||
|
a49a656f1e | ||
|
e8890f274a | ||
|
fc6e079cfc | ||
|
52bf642cf8 | ||
|
4b1ca7d5f1 | ||
|
4258af12b7 | ||
|
313e39e323 | ||
|
dc9674ee46 | ||
|
b6f61ab0ce | ||
|
26a35dd2e4 | ||
|
37a9a90d1d | ||
|
516e028901 | ||
|
13fe86b8fe | ||
|
bf139ea0a8 | ||
|
cb62c00354 | ||
|
9ecc4cab3b | ||
|
ec4ddb403a | ||
|
ddc5357419 | ||
|
9242578bc1 | ||
|
acb460af9e | ||
|
41181669d1 | ||
|
dbc09f12db | ||
|
13025b119f | ||
|
0b116eb439 | ||
|
5250372ab6 | ||
|
9d686e7107 | ||
|
3d142b88d7 | ||
|
8566bcf1eb | ||
|
6e9f41669e | ||
|
d8c6a552aa | ||
|
b18fe77ecd | ||
|
b8f5717416 | ||
|
492ac156bc | ||
|
cf92ec3bf0 | ||
|
1e0b54c6ed | ||
|
e491f0161d | ||
|
e31f179ae0 | ||
|
6b7be9a00a | ||
|
a0dca4df0c | ||
|
eeb4db3234 | ||
|
107681258b | ||
|
8d3797cd15 | ||
|
8d93bca20a | ||
|
0d9486f9a3 | ||
|
505686bd7a | ||
|
c94e9bec36 | ||
|
bf918e630f | ||
|
33ee7ad6ef | ||
|
cb00fb9ec7 | ||
|
c6a9986fa0 | ||
|
7b63ae8f8a | ||
|
9b3c4a81c2 | ||
|
f1e7b37c48 | ||
|
1b1b61d305 | ||
|
c5627a75bc | ||
|
6e4c22e982 | ||
|
f479174573 | ||
|
a4c4a01a37 | ||
|
8477f3174e | ||
|
f0f565fb0f | ||
|
8a563cfca3 | ||
|
15bc2d6c15 | ||
|
70eac23c1b | ||
|
b2180eb52c | ||
|
efc6908bce | ||
|
eb92d6edce | ||
|
38b662ab07 | ||
|
2bd1aeeeb7 | ||
|
d0882077b3 | ||
|
fb21f3cca0 | ||
|
0c65228956 | ||
|
3900860906 | ||
|
01d810e3c0 | ||
|
48316bd345 | ||
|
27c0c9ef79 | ||
|
459e529168 | ||
|
99f52df612 | ||
|
667c52be59 | ||
|
3c0cd06b6d | ||
|
1c9f065dd0 | ||
|
7abcbdcbbd | ||
|
ac3cb02be8 | ||
|
126f36b826 | ||
|
620557ccbc | ||
|
5564469b96 | ||
|
7a07439cf6 | ||
|
2ec91bffad | ||
|
ffbc1cea57 | ||
|
6ec7d7f81e | ||
|
43a33dcd53 | ||
|
42a0018843 | ||
|
6f2a78a26f | ||
|
4eb2cb223b | ||
|
f7e89ba9ea | ||
|
3624d33ae5 | ||
|
392eb67dbf | ||
|
2eed08d94a | ||
|
5ed8ae17a9 | ||
|
4328de857d | ||
|
dba41e672c | ||
|
45a53dea87 | ||
|
8011f61247 | ||
|
f098a54822 | ||
|
1235a6d519 | ||
|
6b215b0a3a | ||
|
e88280ed85 | ||
|
8306eef3ec | ||
|
f18772936d | ||
|
ec7c7a209d | ||
|
80912052d0 | ||
|
be2da58d73 | ||
|
2535e43dd2 | ||
|
c23c6c6fc8 | ||
|
17a627a413 | ||
|
ee44191125 | ||
|
9bf7e65f08 | ||
|
6b70a75081 | ||
|
29f02f9896 | ||
|
10caa99e2d | ||
|
874aed5db7 | ||
|
1b8e9bab5e | ||
|
beb69a876b | ||
|
8233556d44 | ||
|
404970d679 | ||
|
a923d3338e | ||
|
357b3d9d0b | ||
|
b5cdac9950 | ||
|
917f4e7bf3 | ||
|
b7ea065962 | ||
|
69ecf71511 | ||
|
eacb7924c8 | ||
|
ac2abfc8c8 | ||
|
b4bf72b051 | ||
|
71e1be97d8 | ||
|
24b4c59e69 | ||
|
0baf4ab4f6 | ||
|
84b18ac090 | ||
|
3c624b701e | ||
|
c44e0559cf | ||
|
20500a9e59 | ||
|
31226b61f2 | ||
|
31c8edc53e | ||
|
ab3d7650dc | ||
|
688ea02a69 | ||
|
de718176a2 | ||
|
5a3c7f8598 | ||
|
e0b71e5758 | ||
|
67914687b8 | ||
|
c79c32d98c | ||
|
83911c12f3 | ||
|
585a44a0c0 | ||
|
eb2083998d | ||
|
2b66a84406 | ||
|
690172b4d8 | ||
|
290da389e5 |
91 changed files with 8973 additions and 46739 deletions
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal 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
51
.github/workflows/test.yml
vendored
Normal 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
25
.gitignore
vendored
Normal 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
|
2
AUTHORS
2
AUTHORS
|
@ -1,2 +0,0 @@
|
|||
opensource@google.com
|
||||
|
2
AUTHORS.txt
Normal file
2
AUTHORS.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
google-gflags@googlegroups.com
|
||||
|
26
BUILD
Normal file
26
BUILD
Normal 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
754
CMakeLists.txt
Normal 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 ()
|
14
ChangeLog
14
ChangeLog
|
@ -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
276
ChangeLog.txt
Normal 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 c’tor 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
230
INSTALL
|
@ -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
97
INSTALL.md
Normal 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
4
MODULE.bazel
Normal file
|
@ -0,0 +1,4 @@
|
|||
module(
|
||||
name = "gflags",
|
||||
compatibility_level = 1,
|
||||
)
|
77
Makefile.am
77
Makefile.am
|
@ -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)
|
833
Makefile.in
833
Makefile.in
|
@ -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
16
README
|
@ -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
319
README.md
Normal file
|
@ -0,0 +1,319 @@
|
|||
[](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
6
WORKSPACE
Normal 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
7186
aclocal.m4
vendored
File diff suppressed because it is too large
Load diff
5
bazel/expanded_template/BUILD
Normal file
5
bazel/expanded_template/BUILD
Normal file
|
@ -0,0 +1,5 @@
|
|||
cc_binary(
|
||||
name = "expand_template",
|
||||
srcs = ["expand_template.cc"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
63
bazel/expanded_template/expand_template.cc
Normal file
63
bazel/expanded_template/expand_template.cc
Normal 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;
|
||||
}
|
35
bazel/expanded_template/expanded_template.bzl
Normal file
35
bazel/expanded_template/expanded_template.bzl
Normal 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
108
bazel/gflags.bzl
Normal 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
4
cmake/README_runtime.txt
Normal 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.
|
26
cmake/cmake_uninstall.cmake.in
Normal file
26
cmake/cmake_uninstall.cmake.in
Normal 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
183
cmake/config.cmake.in
Normal 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
53
cmake/execute_test.cmake
Normal 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
49
cmake/package.cmake.in
Normal 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
14
cmake/package.pc.in
Normal 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
207
cmake/utils.cmake
Normal 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
21
cmake/version.cmake.in
Normal 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
99
compile
|
@ -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
1491
config.guess
vendored
File diff suppressed because it is too large
Load diff
1606
config.sub
vendored
1606
config.sub
vendored
File diff suppressed because it is too large
Load diff
67
configure.ac
67
configure.ac
|
@ -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
423
depcomp
|
@ -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
|
4
doc/README.md
Normal file
4
doc/README.md
Normal 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
115
doc/designstyle.css
Normal 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; }
|
|
@ -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 <prefix>/lib/cmake/gflags directory
|
||||
containing the gflags-config.cmake file if <prefix> 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 <gflags/gflags.h>
|
||||
|
||||
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><flag>_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 <gflags/gflags.h>
|
||||
</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());
|
251
install-sh
251
install-sh
|
@ -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
|
336
missing
336
missing
|
@ -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
|
|
@ -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
|
|
@ -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"
|
|
@ -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'.
|
|
@ -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
|
||||
|
|
@ -1 +0,0 @@
|
|||
4
|
|
@ -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.
|
|
@ -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.
|
|
@ -1,7 +0,0 @@
|
|||
AUTHORS
|
||||
COPYING
|
||||
ChangeLog
|
||||
INSTALL
|
||||
NEWS
|
||||
README
|
||||
doc/gflags.html
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
1368
python/gflags.py
1368
python/gflags.py
File diff suppressed because it is too large
Load diff
|
@ -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)
|
|
@ -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()
|
|
@ -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
59
src/config.h
Normal 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
48
src/defines.h.in
Normal 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_
|
1793
src/gflags.cc
1793
src/gflags.cc
File diff suppressed because it is too large
Load diff
626
src/gflags.h.in
Normal file
626
src/gflags.h.in
Normal 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
766
src/gflags_completions.cc
Normal 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 ¬able_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,
|
||||
¬able_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,
|
||||
¬able_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 =
|
||||
{ "",
|
||||
"==========",
|
||||
¬able_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 *-",
|
||||
"===========================",
|
||||
¬able_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 *-",
|
||||
"============================",
|
||||
¬able_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 *-",
|
||||
"=========================",
|
||||
¬able_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 *-",
|
||||
"================================",
|
||||
¬able_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 ¬able_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
121
src/gflags_completions.h.in
Normal 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
117
src/gflags_completions.sh
Executable 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
156
src/gflags_declare.h.in
Normal 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
102
src/gflags_ns.h.in
Normal 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_
|
|
@ -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, "&");
|
||||
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, "<");
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
348
src/mutex.h
Normal 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
373
src/util.h
Normal 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
73
src/windows_port.cc
Normal 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
135
src/windows_port.h
Normal 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
227
test/CMakeLists.txt
Normal 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 ()
|
10
test/config/CMakeLists.txt
Normal file
10
test/config/CMakeLists.txt
Normal 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
20
test/config/main.cc
Normal 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
1
test/flagfile.1
Normal file
|
@ -0,0 +1 @@
|
|||
--version
|
2
test/flagfile.2
Normal file
2
test/flagfile.2
Normal file
|
@ -0,0 +1,2 @@
|
|||
--foo=bar
|
||||
--nounused_bool
|
1
test/flagfile.3
Normal file
1
test/flagfile.3
Normal file
|
@ -0,0 +1 @@
|
|||
--flagfile=flagfile.2
|
43
test/gflags_build.py.in
Normal file
43
test/gflags_build.py.in
Normal 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
14
test/gflags_declare_flags.cc
Executable 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;
|
||||
}
|
12
test/gflags_declare_test.cc
Normal file
12
test/gflags_declare_test.cc
Normal 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
60
test/gflags_strip_flags_test.cc
Executable 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;
|
||||
}
|
7
test/gflags_strip_flags_test.cmake
Normal file
7
test/gflags_strip_flags_test.cmake
Normal 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
1572
test/gflags_unittest.cc
Executable file
File diff suppressed because it is too large
Load diff
2
test/gflags_unittest_flagfile
Normal file
2
test/gflags_unittest_flagfile
Normal file
|
@ -0,0 +1,2 @@
|
|||
--test_flag=1
|
||||
--test_flag=2
|
16
test/nc/CMakeLists.txt
Normal file
16
test/nc/CMakeLists.txt
Normal 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
73
test/nc/gflags_nc.cc
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue