Merge pull request #126 from hevy-CC4477/master
Use ```_static``` suffix in filename of static library on Windows to distinguish it from the import library.
diff --git a/BUILD b/BUILD
new file mode 100644
index 0000000..3e6d358
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,102 @@
+# Bazel build file for gflags
+#
+# See INSTALL.md for instructions for adding gflags to a Bazel workspace.
+
+licenses(["notice"])
+
+cc_library(
+ name = "gflags",
+ srcs = [
+ "src/gflags.cc",
+ "src/gflags_completions.cc",
+ "src/gflags_reporting.cc",
+ "src/mutex.h",
+ "src/util.h",
+ ":config_h",
+ ":gflags_completions_h",
+ ":gflags_declare_h",
+ ":gflags_h",
+ ":includes",
+ ],
+ hdrs = ["gflags.h"],
+ copts = [
+ "-Wno-sign-compare",
+ "-DHAVE_STDINT_H",
+ "-DHAVE_SYS_TYPES_H",
+ "-DHAVE_INTTYPES_H",
+ "-DHAVE_SYS_STAT_H",
+ "-DHAVE_UNISTD_H",
+ "-DHAVE_FNMATCH_H",
+ "-DHAVE_STRTOLL",
+ "-DHAVE_STRTOQ",
+ "-DHAVE_PTHREAD",
+ "-DHAVE_RWLOCK",
+ "-DGFLAGS_INTTYPES_FORMAT_C99",
+ ],
+ includes = [
+ "include",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+genrule(
+ name = "config_h",
+ srcs = [
+ "src/config.h.in",
+ ],
+ outs = [
+ "config.h",
+ ],
+ cmd = "sed -r -e 's,^#cmakedefine,// cmakedefine,' $(<) > $(@)",
+)
+
+genrule(
+ name = "gflags_h",
+ srcs = [
+ "src/gflags.h.in",
+ ],
+ outs = [
+ "gflags.h",
+ ],
+ cmd = "sed -r -e 's/@[A-Z_]+@//' $(<) > $(@)",
+)
+
+genrule(
+ name = "gflags_completions_h",
+ srcs = [
+ "src/gflags_completions.h.in",
+ ],
+ outs = [
+ "gflags_completions.h",
+ ],
+ cmd = "sed -r -e 's/@GFLAGS_NAMESPACE@/gflags/' $(<) > $(@)",
+)
+
+genrule(
+ name = "gflags_declare_h",
+ srcs = [
+ "src/gflags_declare.h.in",
+ ],
+ outs = [
+ "gflags_declare.h",
+ ],
+ cmd = ("sed -r -e '" +
+ "s/@GFLAGS_NAMESPACE@/gflags/;" +
+ "s/@(HAVE_STDINT_H|HAVE_SYS_TYPES_H|HAVE_INTTYPES_H" +
+ "|GFLAGS_INTTYPES_FORMAT_C99)@/1/;" +
+ "s/@([A-Z0-9_]+)@/0/" +
+ "' $(<) > $(@)"),
+)
+
+genrule(
+ name = "includes",
+ srcs = [
+ ":gflags_h",
+ ":gflags_declare_h",
+ ],
+ outs = [
+ "include/gflags/gflags.h",
+ "include/gflags/gflags_declare.h",
+ ],
+ cmd = "mkdir -p $(@D)/include/gflags && cp $(SRCS) $(@D)/include/gflags",
+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4ac6853..21c8660 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -326,7 +326,7 @@
PRIVATE "${PROJECT_SOURCE_DIR}/src;${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}"
)
if (opts MATCHES "nothreads")
- set (defines "GFLAGS_IS_A_DLL=${GFLAGS_IS_A_DLL};NOTHREADS")
+ set (defines "GFLAGS_IS_A_DLL=${GFLAGS_IS_A_DLL};NO_THREADS")
else ()
set (defines "GFLAGS_IS_A_DLL=${GFLAGS_IS_A_DLL}")
if (CMAKE_USE_PTHREADS_INIT)
diff --git a/INSTALL.md b/INSTALL.md
index b89d86d..a206bda 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -11,7 +11,7 @@
sudo apt-get install gflags
-Compiling the source code
+Compiling the source code with CMake
=========================
The build system of gflags is since version 2.1 based on [CMake](http://cmake.org).
@@ -65,3 +65,24 @@
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.
+
+Using gflags with [Bazel](http://bazel.io)
+=========================
+
+To use gflags in a Bazel project, map it in as an external dependency by editing
+your WORKSPACE file:
+
+ git_repository(
+ name = "gflags_git",
+ commit = "", # Use the current HEAD commit
+ remote = "https://github.com/gflags/gflags.git",
+ )
+
+ bind(
+ name = "gflags",
+ actual = "@gflags_git//:gflags",
+ )
+
+You can then add `//external: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.
diff --git a/doc b/doc
index e1d15b3..16651b7 160000
--- a/doc
+++ b/doc
@@ -1 +1 @@
-Subproject commit e1d15b33406ec571095e7a91dbc4b2ada1ae3bac
+Subproject commit 16651b78706e7ac3a1697146dd3b41f885ac73f1
diff --git a/src/gflags.cc b/src/gflags.cc
index a35bbfe..85b1ef7 100644
--- a/src/gflags.cc
+++ b/src/gflags.cc
@@ -1454,65 +1454,58 @@
// These values are not protected by a Mutex because they are normally
// set only once during program startup.
-static const char* argv0 = "UNKNOWN"; // just the program name
-static const char* cmdline = ""; // the entire command-line
+static string argv0("UNKNOWN"); // just the program name
+static string cmdline; // the entire command-line
+static string program_usage;
static vector<string> argvs;
static uint32 argv_sum = 0;
-static const char* program_usage = NULL;
void SetArgv(int argc, const char** argv) {
static bool called_set_argv = false;
- if (called_set_argv) // we already have an argv for you
- return;
-
+ if (called_set_argv) return;
called_set_argv = true;
- assert(argc > 0); // every program has at least a progname
- argv0 = strdup(argv[0]); // small memory leak, but fn only called once
- assert(argv0);
+ assert(argc > 0); // every program has at least a name
+ argv0 = argv[0];
- string cmdline_string; // easier than doing strcats
+ cmdline.clear();
for (int i = 0; i < argc; i++) {
- if (i != 0) {
- cmdline_string += " ";
- }
- cmdline_string += argv[i];
+ if (i != 0) cmdline += " ";
+ cmdline += argv[i];
argvs.push_back(argv[i]);
}
- cmdline = strdup(cmdline_string.c_str()); // another small memory leak
- assert(cmdline);
// Compute a simple sum of all the chars in argv
- for (const char* c = cmdline; *c; c++)
+ argv_sum = 0;
+ for (string::const_iterator c = cmdline.begin(); c != cmdline.end(); ++c) {
argv_sum += *c;
+ }
}
const vector<string>& GetArgvs() { return argvs; }
-const char* GetArgv() { return cmdline; }
-const char* GetArgv0() { return argv0; }
+const char* GetArgv() { return cmdline.c_str(); }
+const char* GetArgv0() { return argv0.c_str(); }
uint32 GetArgvSum() { return argv_sum; }
const char* ProgramInvocationName() { // like the GNU libc fn
return GetArgv0();
}
const char* ProgramInvocationShortName() { // like the GNU libc fn
- const char* slash = strrchr(argv0, '/');
+ size_t pos = argv0.rfind('/');
#ifdef OS_WINDOWS
- if (!slash) slash = strrchr(argv0, '\\');
+ if (pos == string::npos) pos = argv0.rfind('\\');
#endif
- return slash ? slash + 1 : argv0;
+ return (pos == string::npos ? argv0.c_str() : (argv0.c_str() + pos + 1));
}
void SetUsageMessage(const string& usage) {
- if (program_usage != NULL)
- ReportError(DIE, "ERROR: SetUsageMessage() called twice\n");
- program_usage = strdup(usage.c_str()); // small memory leak
+ program_usage = usage;
}
const char* ProgramUsage() {
- if (program_usage) {
- return program_usage;
+ if (program_usage.empty()) {
+ return "Warning: SetUsageMessage() never called";
}
- return "Warning: SetUsageMessage() never called";
+ return program_usage.c_str();
}
// --------------------------------------------------------------------
@@ -1520,16 +1513,14 @@
// VersionString()
// --------------------------------------------------------------------
-static const char* version_string = NULL;
+static string version_string;
void SetVersionString(const string& version) {
- if (version_string != NULL)
- ReportError(DIE, "ERROR: SetVersionString() called twice\n");
- version_string = strdup(version.c_str()); // small memory leak
+ version_string = version;
}
const char* VersionString() {
- return version_string ? version_string : "";
+ return version_string.c_str();
}
diff --git a/src/gflags.h.in b/src/gflags.h.in
index 0324d39..88ab1aa 100644
--- a/src/gflags.h.in
+++ b/src/gflags.h.in
@@ -538,6 +538,26 @@
}
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
@@ -557,6 +577,7 @@
static GFLAGS_NAMESPACE::FlagRegisterer o_##name( \
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
s_##name[0].s, 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; \
diff --git a/src/gflags_completions.cc b/src/gflags_completions.cc
index 3a47623..d7097ca 100644
--- a/src/gflags_completions.cc
+++ b/src/gflags_completions.cc
@@ -47,6 +47,8 @@
// 5b) Trim most flag's descriptions to fit on a single terminal line
+#include "gflags_completions.h"
+
#include "config.h"
#include <stdio.h>
diff --git a/src/util.h b/src/util.h
index fb59b38..164e3cf 100644
--- a/src/util.h
+++ b/src/util.h
@@ -37,7 +37,6 @@
#include "config.h"
#include <assert.h>
-#include <config.h>
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
diff --git a/src/windows_port.cc b/src/windows_port.cc
index 9ccb630..b5b7194 100644
--- a/src/windows_port.cc
+++ b/src/windows_port.cc
@@ -44,6 +44,7 @@
// 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)
@@ -59,8 +60,6 @@
# pragma warning(pop)
#endif
-#if _MSC_VER < 1900 // msvs 2015 finally includes snprintf
-
int snprintf(char *str, size_t size, const char *format, ...) {
int r;
va_list ap;
@@ -70,6 +69,5 @@
return r;
}
-#endif
-
+#endif /* if !(defined(_MSC_VER) && _MSC_VER >= 1900) */
#endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
diff --git a/src/windows_port.h b/src/windows_port.h
index c8ff24f..554b9c9 100644
--- a/src/windows_port.h
+++ b/src/windows_port.h
@@ -63,12 +63,14 @@
* 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
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 77b582f..70644cf 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -2,9 +2,9 @@
# ----------------------------------------------------------------------------
# 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 (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/Testing/bin")
+set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/Testing/lib")
+set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/Testing/lib")
# set working directory of test commands
set (GFLAGS_FLAGFILES_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
diff --git a/test/config/main.cc b/test/config/main.cc
index 9b2b898..3c033e3 100644
--- a/test/config/main.cc
+++ b/test/config/main.cc
@@ -3,10 +3,18 @@
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;
}
diff --git a/test/gflags_declare_flags.cc b/test/gflags_declare_flags.cc
index dc53de5..2491686 100644
--- a/test/gflags_declare_flags.cc
+++ b/test/gflags_declare_flags.cc
@@ -3,6 +3,7 @@
DECLARE_string(message); // in gflags_delcare_test.cc
+void print_message();
void print_message()
{
std::cout << FLAGS_message << std::endl;
diff --git a/test/gflags_unittest.cc b/test/gflags_unittest.cc
index 80f7398..f205466 100644
--- a/test/gflags_unittest.cc
+++ b/test/gflags_unittest.cc
@@ -1485,7 +1485,7 @@
} // unnamed namespace
-int main(int argc, char **argv) {
+static int main(int argc, char **argv) {
// Run unit tests only if called without arguments, otherwise this program
// is used by an "external" usage test
@@ -1514,7 +1514,7 @@
// The non-recommended way:
FLAGS_changed_bool2 = true;
- SetUsageMessage(usage_message.c_str());
+ SetUsageMessage(usage_message);
SetVersionString("test_version");
ParseCommandLineFlags(&argc, &argv, true);
MakeTmpdir(&FLAGS_test_tmpdir);