diff --git a/Makefile.am b/Makefile.am index 01e3431..16002d9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,7 +34,7 @@ docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION) ## 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/designstyle.css doc/gflags.html + README_windows.txt doc/designstyle.css doc/gflags.html ## The libraries (.so's) you want to install lib_LTLIBRARIES = diff --git a/Makefile.in b/Makefile.in index b0390d2..3eaf258 100644 --- a/Makefile.in +++ b/Makefile.in @@ -307,7 +307,7 @@ googleincludedir = $(includedir)/google googleinclude_HEADERS = src/google/gflags.h src/google/gflags_completions.h bin_SCRIPTS = src/gflags_completions.sh dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \ - doc/designstyle.css doc/gflags.html + README_windows.txt doc/designstyle.css doc/gflags.html lib_LTLIBRARIES = libgflags.la libgflags_nothreads.la WINDOWS_PROJECTS = google-gflags.sln \ diff --git a/README b/README index b49fac9..7422982 100644 --- a/README +++ b/README @@ -6,5 +6,4 @@ module. See INSTALL for (generic) installation instructions for C++: basically ./configure && make && make install -You can also compile this under Windows, if you want. The solution -file (for VC 7.1 and later) is in this directory. +See README_windows.txt for instructions on using under windows. diff --git a/README_windows.txt b/README_windows.txt new file mode 100644 index 0000000..33f839b --- /dev/null +++ b/README_windows.txt @@ -0,0 +1,20 @@ +You can compile this under Windows, if you want. The solution file +(for VC 7.1 and later) is in this directory. + +I've been told the following steps work to compile this under win64: + 1) Open the provided solution file + 2) Click on the Win32 target (on the right of Debug/Release) + 3) Choose Configuration Manager + 4) In Active Solution Platforms, choose New... + 5) In "Type of select the new platform", choose x64. + In "Copy settings from:" choose Win32. + 6) Ok and then Close + +I don't know very much about how to install DLLs on Windows, so you'll +have to figure out that part for yourself. If you choose to just +re-use the existing .sln, make sure you set the IncludeDir's +appropriately! Look at the properties for libgflags.dll. + +You can also link gflags code in statically. For this to work, you'll +need to add "/D GFLAGS_DLL_DECL=" to the compile line of every +gflags .cc file. diff --git a/doc/gflags.html b/doc/gflags.html index cf0c4b3..fe202d1 100644 --- a/doc/gflags.html +++ b/doc/gflags.html @@ -47,6 +47,7 @@
ls -la
.
+
+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 main()
,
+before calling ParseCommandLineFlags()
:
+ 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(...); + } ++ +
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.
+ +There are a few flags defined by the commandlineflags module diff --git a/src/gflags.cc b/src/gflags.cc index d233e50..01067a4 100644 --- a/src/gflags.cc +++ b/src/gflags.cc @@ -143,6 +143,8 @@ # define PRIu64 "llu" #endif +typedef unsigned char uint8; + // Special flags, type 1: the 'recursive' flags. They set another flag's val. DEFINE_string(flagfile, "", "load flags from file"); @@ -235,8 +237,15 @@ class FlagValue { friend bool TryParseLocked(const CommandLineFlag*, FlagValue*, const char*, string*); // for New(), CopyFrom() - enum ValueType {FV_BOOL, FV_INT32, FV_INT64, FV_UINT64, FV_DOUBLE, FV_STRING}; - + enum ValueType { + FV_BOOL = 0, + FV_INT32 = 1, + FV_INT64 = 2, + FV_UINT64 = 3, + FV_DOUBLE = 4, + FV_STRING = 5, + FV_MAX_INDEX = 5, + }; const char* TypeName() const; bool Equal(const FlagValue& x) const; FlagValue* New() const; // creates a new one with default value @@ -249,9 +258,8 @@ class FlagValue { // (*validate_fn)(bool) for a bool flag). bool Validate(const char* flagname, ValidateFnProto validate_fn_proto) const; - void* value_buffer_; // points to the buffer holding our data - ValueType type_; // how to interpret value_ + uint32 type_; // how to interpret value_ FlagValue(const FlagValue&); // no copying! void operator=(const FlagValue&); @@ -265,13 +273,12 @@ class FlagValue { #define SET_VALUE_AS(type, value) VALUE_AS(type) = (value) FlagValue::FlagValue(void* valbuf, const char* type) : value_buffer_(valbuf) { - if (strcmp(type, "bool") == 0) type_ = FV_BOOL; - else if (strcmp(type, "int32") == 0) type_ = FV_INT32; - else if (strcmp(type, "int64") == 0) type_ = FV_INT64; - else if (strcmp(type, "uint64") == 0) type_ = FV_UINT64; - else if (strcmp(type, "double") == 0) type_ = FV_DOUBLE; - else if (strcmp(type, "string") == 0) type_ = FV_STRING; - else assert(false); // Unknown typename + for (type_ = 0; type_ <= FV_MAX_INDEX; ++type_) { + if (!strcmp(type, TypeName())) { + break; + } + } + assert(type_ <= FV_MAX_INDEX); // Unknown typename } FlagValue::~FlagValue() { @@ -405,15 +412,20 @@ bool FlagValue::Validate(const char* flagname, } const char* FlagValue::TypeName() const { - switch (type_) { - case FV_BOOL: return "bool"; - case FV_INT32: return "int32"; - case FV_INT64: return "int64"; - case FV_UINT64: return "uint64"; - case FV_DOUBLE: return "double"; - case FV_STRING: return "string"; - default: assert(false); return ""; // unknown type + static const char types[] = + "bool\0xx" + "int32\0x" + "int64\0x" + "uint64\0" + "double\0" + "string"; + if (type_ > FV_MAX_INDEX) { + assert(false); + return ""; } + // Directly indexing the strigns in the 'types' string, each of them + // is 7 bytes long. + return &types[type_ * 7]; } bool FlagValue::Equal(const FlagValue& x) const { @@ -431,13 +443,14 @@ bool FlagValue::Equal(const FlagValue& x) const { } FlagValue* FlagValue::New() const { + const char *type = TypeName(); switch (type_) { - case FV_BOOL: return new FlagValue(new bool(false), "bool"); - case FV_INT32: return new FlagValue(new int32(0), "int32"); - case FV_INT64: return new FlagValue(new int64(0), "int64"); - case FV_UINT64: return new FlagValue(new uint64(0), "uint64"); - case FV_DOUBLE: return new FlagValue(new double(0.0), "double"); - case FV_STRING: return new FlagValue(new string, "string"); + case FV_BOOL: return new FlagValue(new bool(false), type); + case FV_INT32: return new FlagValue(new int32(0), type); + case FV_INT64: return new FlagValue(new int64(0), type); + case FV_UINT64: return new FlagValue(new uint64(0), type); + case FV_DOUBLE: return new FlagValue(new double(0.0), type); + case FV_STRING: return new FlagValue(new string, type); default: assert(false); return NULL; // unknown type } } @@ -456,15 +469,19 @@ void FlagValue::CopyFrom(const FlagValue& x) { } int FlagValue::ValueSize() const { - switch (type_) { - case FV_BOOL: return sizeof(bool); - case FV_INT32: return sizeof(int32); - case FV_INT64: return sizeof(int64); - case FV_UINT64: return sizeof(uint64); - case FV_DOUBLE: return sizeof(double); - case FV_STRING: return sizeof(string); - default: assert(false); return 0; // unknown type + if (type_ > FV_MAX_INDEX) { + assert(false); // unknown type + return 0; } + static const uint8 valuesize[] = { + sizeof(bool), + sizeof(int32), + sizeof(int64), + sizeof(uint64), + sizeof(double), + sizeof(string), + }; + return valuesize[type_]; } // -------------------------------------------------------------------- diff --git a/src/gflags/gflags.h.in b/src/gflags/gflags.h.in index 2d38071..889c3fa 100644 --- a/src/gflags/gflags.h.in +++ b/src/gflags/gflags.h.in @@ -124,7 +124,8 @@ typedef unsigned __int64 uint64; // 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. +// 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 @@ -180,7 +181,9 @@ struct CommandLineFlagInfo { 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 flag - bool is_default; // true if the flag has default value + bool is_default; // true if the flag has the default value and + // has not been set explicitly from the cmdline + // or via SetCommandLineOption }; // Using this inside of a validator is a recipe for a deadlock. diff --git a/src/windows/gflags/gflags.h b/src/windows/gflags/gflags.h index 38bc3c3..191c6e3 100644 --- a/src/windows/gflags/gflags.h +++ b/src/windows/gflags/gflags.h @@ -99,12 +99,26 @@ #endif // Annoying stuff for windows -- makes sure clients can import these functions -#ifndef GFLAGS_DLL_DECL -# ifdef _WIN32 +#if defined(_WIN32) +# ifndef GFLAGS_DLL_DECL # define GFLAGS_DLL_DECL __declspec(dllimport) -# else +# endif +# ifndef GFLAGS_DLL_DECLARE_FLAG +# define GFLAGS_DLL_DECLARE_FLAG __declspec(import) +# endif +# ifndef GFLAGS_DLL_DEFINE_FLAG +# define GFLAGS_DLL_DEFINE_FLAG __declspec(dllexport) +# endif +#else +# ifndef GFLAGS_DLL_DECL # define GFLAGS_DLL_DECL # endif +# ifndef GFLAGS_DLL_DECLARE_FLAG +# define GFLAGS_DLL_DECLARE_FLAG +# endif +# ifndef GFLAGS_DLL_DEFINE_FLAG +# define GFLAGS_DLL_DEFINE_FLAG +# endif #endif namespace google { @@ -133,7 +147,8 @@ typedef unsigned __int64 uint64; // 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. +// 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 @@ -189,7 +204,9 @@ struct GFLAGS_DLL_DECL CommandLineFlagInfo { 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 flag - bool is_default; // true if the flag has default value + bool is_default; // true if the flag has the default value and + // has not been set explicitly from the cmdline + // or via SetCommandLineOption }; // Using this inside of a validator is a recipe for a deadlock. @@ -471,7 +488,7 @@ extern const char kStrippedFlagHelp[]; namespace fL##shorttype { \ static const type FLAGS_nono##name = value; \ /* We always want to export defined variables, dll or no */ \ - __declspec(dllexport) type FLAGS_##name = FLAGS_nono##name; \ + GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \ type FLAGS_no##name = FLAGS_nono##name; \ static ::google::FlagRegisterer o_##name( \ #name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \ @@ -482,7 +499,7 @@ extern const char kStrippedFlagHelp[]; #define DECLARE_VARIABLE(type, shorttype, name) \ namespace fL##shorttype { \ /* We always want to import declared variables, dll or no */ \ - extern __declspec(dllimport) type FLAGS_##name; \ + extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; \ } \ using fL##shorttype::FLAGS_##name @@ -528,7 +545,7 @@ GFLAGS_DLL_DECL bool IsBoolFlag(bool from); // 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. -#define DECLARE_string(name) namespace fLS { extern __declspec(dllimport) std::string& FLAGS_##name; } \ +#define DECLARE_string(name) namespace fLS { extern GFLAGS_DLL_DECLARE_FLAG std::string& FLAGS_##name; } \ using fLS::FLAGS_##name // We need to define a var named FLAGS_no##name so people don't define @@ -545,7 +562,7 @@ GFLAGS_DLL_DECL bool IsBoolFlag(bool from); static ::google::FlagRegisterer o_##name( \ #name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \ s_##name[0].s, new (s_##name[1].s) std::string(*FLAGS_no##name)); \ - extern __declspec(dllexport) std::string& FLAGS_##name; \ + extern GFLAGS_DLL_DEFINE_FLAG std::string& FLAGS_##name; \ using fLS::FLAGS_##name; \ std::string& FLAGS_##name = *FLAGS_no##name; \ } \