Commit c44e0559 authored by Craig Silverstein's avatar Craig Silverstein

* Reduce .o size by decomposing switches (jyrki)

	* Document how to change the default flag value (csilvers)
	* Add a windows-specific README (csilvers)
	* A few comment updates (wojtekm)


git-svn-id: https://gflags.googlecode.com/svn/trunk@39 6586e3c6-dcc4-952a-343f-ff74eb82781d
parent 20500a9e
...@@ -34,7 +34,7 @@ docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION) ...@@ -34,7 +34,7 @@ docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION)
## Add your documentation files (in doc/) in addition to these ## Add your documentation files (in doc/) in addition to these
## top-level boilerplate files. Also add a TODO file if you have one. ## top-level boilerplate files. Also add a TODO file if you have one.
dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \ 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 ## The libraries (.so's) you want to install
lib_LTLIBRARIES = lib_LTLIBRARIES =
......
...@@ -307,7 +307,7 @@ googleincludedir = $(includedir)/google ...@@ -307,7 +307,7 @@ googleincludedir = $(includedir)/google
googleinclude_HEADERS = src/google/gflags.h src/google/gflags_completions.h googleinclude_HEADERS = src/google/gflags.h src/google/gflags_completions.h
bin_SCRIPTS = src/gflags_completions.sh bin_SCRIPTS = src/gflags_completions.sh
dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \ 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 lib_LTLIBRARIES = libgflags.la libgflags_nothreads.la
WINDOWS_PROJECTS = google-gflags.sln \ WINDOWS_PROJECTS = google-gflags.sln \
......
...@@ -6,5 +6,4 @@ module. ...@@ -6,5 +6,4 @@ module.
See INSTALL for (generic) installation instructions for C++: basically See INSTALL for (generic) installation instructions for C++: basically
./configure && make && make install ./configure && make && make install
You can also compile this under Windows, if you want. The solution See README_windows.txt for instructions on using under windows.
file (for VC 7.1 and later) is in this directory.
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.
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
<dd> <a href="#together">Putting It Together: How to Set Up Flags</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="#commandline">Setting Flags on the Command Line</a> </dd>
<dd> <a href="#varz">Setting Flags at Runtime</a> </dd> <dd> <a href="#varz">Setting Flags at Runtime</a> </dd>
<dd> <a href="#default">Changing the Default Flag Value</a> </dd>
<dd> <a href="#special">Special Flags</a> </dd> <dd> <a href="#special">Special Flags</a> </dd>
<dd> <a href="#api">The API</a> </dd> <dd> <a href="#api">The API</a> </dd>
<dd> <br/> </dd> <dd> <br/> </dd>
...@@ -348,6 +349,26 @@ the getopt library, nor do we allow "combining" flags behind a ...@@ -348,6 +349,26 @@ the getopt library, nor do we allow "combining" flags behind a
single dash, as in <code>ls -la</code>.</p> single dash, as in <code>ls -la</code>.</p>
<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</code> </h2> <h2> <A name="special">Special Flags</code> </h2>
<p>There are a few flags defined by the commandlineflags module <p>There are a few flags defined by the commandlineflags module
......
...@@ -143,6 +143,8 @@ ...@@ -143,6 +143,8 @@
# define PRIu64 "llu" # define PRIu64 "llu"
#endif #endif
typedef unsigned char uint8;
// Special flags, type 1: the 'recursive' flags. They set another flag's val. // Special flags, type 1: the 'recursive' flags. They set another flag's val.
DEFINE_string(flagfile, "", DEFINE_string(flagfile, "",
"load flags from file"); "load flags from file");
...@@ -235,8 +237,15 @@ class FlagValue { ...@@ -235,8 +237,15 @@ class FlagValue {
friend bool TryParseLocked(const CommandLineFlag*, FlagValue*, friend bool TryParseLocked(const CommandLineFlag*, FlagValue*,
const char*, string*); // for New(), CopyFrom() 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; const char* TypeName() const;
bool Equal(const FlagValue& x) const; bool Equal(const FlagValue& x) const;
FlagValue* New() const; // creates a new one with default value FlagValue* New() const; // creates a new one with default value
...@@ -249,9 +258,8 @@ class FlagValue { ...@@ -249,9 +258,8 @@ class FlagValue {
// (*validate_fn)(bool) for a bool flag). // (*validate_fn)(bool) for a bool flag).
bool Validate(const char* flagname, ValidateFnProto validate_fn_proto) const; bool Validate(const char* flagname, ValidateFnProto validate_fn_proto) const;
void* value_buffer_; // points to the buffer holding our data 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! FlagValue(const FlagValue&); // no copying!
void operator=(const FlagValue&); void operator=(const FlagValue&);
...@@ -265,13 +273,12 @@ class FlagValue { ...@@ -265,13 +273,12 @@ class FlagValue {
#define SET_VALUE_AS(type, value) VALUE_AS(type) = (value) #define SET_VALUE_AS(type, value) VALUE_AS(type) = (value)
FlagValue::FlagValue(void* valbuf, const char* type) : value_buffer_(valbuf) { FlagValue::FlagValue(void* valbuf, const char* type) : value_buffer_(valbuf) {
if (strcmp(type, "bool") == 0) type_ = FV_BOOL; for (type_ = 0; type_ <= FV_MAX_INDEX; ++type_) {
else if (strcmp(type, "int32") == 0) type_ = FV_INT32; if (!strcmp(type, TypeName())) {
else if (strcmp(type, "int64") == 0) type_ = FV_INT64; break;
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; assert(type_ <= FV_MAX_INDEX); // Unknown typename
else assert(false); // Unknown typename
} }
FlagValue::~FlagValue() { FlagValue::~FlagValue() {
...@@ -405,15 +412,20 @@ bool FlagValue::Validate(const char* flagname, ...@@ -405,15 +412,20 @@ bool FlagValue::Validate(const char* flagname,
} }
const char* FlagValue::TypeName() const { const char* FlagValue::TypeName() const {
switch (type_) { static const char types[] =
case FV_BOOL: return "bool"; "bool\0xx"
case FV_INT32: return "int32"; "int32\0x"
case FV_INT64: return "int64"; "int64\0x"
case FV_UINT64: return "uint64"; "uint64\0"
case FV_DOUBLE: return "double"; "double\0"
case FV_STRING: return "string"; "string";
default: assert(false); return ""; // unknown type 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 { bool FlagValue::Equal(const FlagValue& x) const {
...@@ -431,13 +443,14 @@ bool FlagValue::Equal(const FlagValue& x) const { ...@@ -431,13 +443,14 @@ bool FlagValue::Equal(const FlagValue& x) const {
} }
FlagValue* FlagValue::New() const { FlagValue* FlagValue::New() const {
const char *type = TypeName();
switch (type_) { switch (type_) {
case FV_BOOL: return new FlagValue(new bool(false), "bool"); case FV_BOOL: return new FlagValue(new bool(false), type);
case FV_INT32: return new FlagValue(new int32(0), "int32"); case FV_INT32: return new FlagValue(new int32(0), type);
case FV_INT64: return new FlagValue(new int64(0), "int64"); case FV_INT64: return new FlagValue(new int64(0), type);
case FV_UINT64: return new FlagValue(new uint64(0), "uint64"); case FV_UINT64: return new FlagValue(new uint64(0), type);
case FV_DOUBLE: return new FlagValue(new double(0.0), "double"); case FV_DOUBLE: return new FlagValue(new double(0.0), type);
case FV_STRING: return new FlagValue(new string, "string"); case FV_STRING: return new FlagValue(new string, type);
default: assert(false); return NULL; // unknown type default: assert(false); return NULL; // unknown type
} }
} }
...@@ -456,15 +469,19 @@ void FlagValue::CopyFrom(const FlagValue& x) { ...@@ -456,15 +469,19 @@ void FlagValue::CopyFrom(const FlagValue& x) {
} }
int FlagValue::ValueSize() const { int FlagValue::ValueSize() const {
switch (type_) { if (type_ > FV_MAX_INDEX) {
case FV_BOOL: return sizeof(bool); assert(false); // unknown type
case FV_INT32: return sizeof(int32); return 0;
case FV_INT64: return sizeof(int64); }
case FV_UINT64: return sizeof(uint64); static const uint8 valuesize[] = {
case FV_DOUBLE: return sizeof(double); sizeof(bool),
case FV_STRING: return sizeof(string); sizeof(int32),
default: assert(false); return 0; // unknown type sizeof(int64),
} sizeof(uint64),
sizeof(double),
sizeof(string),
};
return valuesize[type_];
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
......
...@@ -124,7 +124,8 @@ typedef unsigned __int64 uint64; ...@@ -124,7 +124,8 @@ typedef unsigned __int64 uint64;
// DEFINE_string, etc. at the bottom of this file. You may also find // 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 // 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 // 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 // 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 // false otherwise. If the function returns false for the new setting of the
...@@ -180,7 +181,9 @@ struct CommandLineFlagInfo { ...@@ -180,7 +181,9 @@ struct CommandLineFlagInfo {
std::string default_value; // the default value, as a string std::string default_value; // the default value, as a string
std::string filename; // 'cleaned' version of filename holding the flag std::string filename; // 'cleaned' version of filename holding the flag
bool has_validator_fn; // true if RegisterFlagValidator called on 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. // Using this inside of a validator is a recipe for a deadlock.
......
...@@ -99,12 +99,26 @@ ...@@ -99,12 +99,26 @@
#endif #endif
// Annoying stuff for windows -- makes sure clients can import these functions // Annoying stuff for windows -- makes sure clients can import these functions
#ifndef GFLAGS_DLL_DECL #if defined(_WIN32)
# ifdef _WIN32 # ifndef GFLAGS_DLL_DECL
# define GFLAGS_DLL_DECL __declspec(dllimport) # 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 # define GFLAGS_DLL_DECL
# endif # endif
# ifndef GFLAGS_DLL_DECLARE_FLAG
# define GFLAGS_DLL_DECLARE_FLAG
# endif
# ifndef GFLAGS_DLL_DEFINE_FLAG
# define GFLAGS_DLL_DEFINE_FLAG
# endif
#endif #endif
namespace google { namespace google {
...@@ -133,7 +147,8 @@ typedef unsigned __int64 uint64; ...@@ -133,7 +147,8 @@ typedef unsigned __int64 uint64;
// DEFINE_string, etc. at the bottom of this file. You may also find // 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 // 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 // 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 // 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 // false otherwise. If the function returns false for the new setting of the
...@@ -189,7 +204,9 @@ struct GFLAGS_DLL_DECL CommandLineFlagInfo { ...@@ -189,7 +204,9 @@ struct GFLAGS_DLL_DECL CommandLineFlagInfo {
std::string default_value; // the default value, as a string std::string default_value; // the default value, as a string
std::string filename; // 'cleaned' version of filename holding the flag std::string filename; // 'cleaned' version of filename holding the flag
bool has_validator_fn; // true if RegisterFlagValidator called on 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. // Using this inside of a validator is a recipe for a deadlock.
...@@ -471,7 +488,7 @@ extern const char kStrippedFlagHelp[]; ...@@ -471,7 +488,7 @@ extern const char kStrippedFlagHelp[];
namespace fL##shorttype { \ namespace fL##shorttype { \
static const type FLAGS_nono##name = value; \ static const type FLAGS_nono##name = value; \
/* We always want to export defined variables, dll or no */ \ /* 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; \ type FLAGS_no##name = FLAGS_nono##name; \
static ::google::FlagRegisterer o_##name( \ static ::google::FlagRegisterer o_##name( \
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \ #name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
...@@ -482,7 +499,7 @@ extern const char kStrippedFlagHelp[]; ...@@ -482,7 +499,7 @@ extern const char kStrippedFlagHelp[];
#define DECLARE_VARIABLE(type, shorttype, name) \ #define DECLARE_VARIABLE(type, shorttype, name) \
namespace fL##shorttype { \ namespace fL##shorttype { \
/* We always want to import declared variables, dll or no */ \ /* 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 using fL##shorttype::FLAGS_##name
...@@ -528,7 +545,7 @@ GFLAGS_DLL_DECL bool IsBoolFlag(bool from); ...@@ -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 // 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 // the string, which we can static-initialize, and then placement-new
// into it later. It's not perfect, but the best we can do. // 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 using fLS::FLAGS_##name
// We need to define a var named FLAGS_no##name so people don't define // 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); ...@@ -545,7 +562,7 @@ GFLAGS_DLL_DECL bool IsBoolFlag(bool from);
static ::google::FlagRegisterer o_##name( \ static ::google::FlagRegisterer o_##name( \
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \ #name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
s_##name[0].s, new (s_##name[1].s) std::string(*FLAGS_no##name)); \ 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; \ using fLS::FLAGS_##name; \
std::string& FLAGS_##name = *FLAGS_no##name; \ std::string& FLAGS_##name = *FLAGS_no##name; \
} \ } \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment