Spaces:
Running
Running
/* Commandline flags support for C10. | |
* | |
* This is a portable commandline flags tool for c10, so we can optionally | |
* choose to use gflags or a lightweight custom implementation if gflags is | |
* not possible on a certain platform. If you have gflags installed, set the | |
* macro C10_USE_GFLAGS will seamlessly route everything to gflags. | |
* | |
* To define a flag foo of type bool default to true, do the following in the | |
* *global* namespace: | |
* C10_DEFINE_bool(foo, true, "An example."); | |
* | |
* To use it in another .cc file, you can use C10_DECLARE_* as follows: | |
* C10_DECLARE_bool(foo); | |
* | |
* In both cases, you can then access the flag via FLAGS_foo. | |
* | |
* It is recommended that you build with gflags. To learn more about the flags | |
* usage, refer to the gflags page here: | |
* | |
* https://gflags.github.io/gflags/ | |
* | |
* Note about Python users / devs: gflags is initiated from a C++ function | |
* ParseCommandLineFlags, and is usually done in native binaries in the main | |
* function. As Python does not have a modifiable main function, it is usually | |
* difficult to change the flags after Python starts. Hence, it is recommended | |
* that one sets the default value of the flags to one that's acceptable in | |
* general - that will allow Python to run without wrong flags. | |
*/ | |
namespace c10 { | |
/** | |
* Sets the usage message when a commandline tool is called with "--help". | |
*/ | |
C10_API void SetUsageMessage(const std::string& str); | |
/** | |
* Returns the usage message for the commandline tool set by SetUsageMessage. | |
*/ | |
C10_API const char* UsageMessage(); | |
/** | |
* Parses the commandline flags. | |
* | |
* This command parses all the commandline arguments passed in via pargc | |
* and argv. Once it is finished, partc and argv will contain the remaining | |
* commandline args that c10 does not deal with. Note that following | |
* convention, argv[0] contains the binary name and is not parsed. | |
*/ | |
C10_API bool ParseCommandLineFlags(int* pargc, char*** pargv); | |
/** | |
* Checks if the commandline flags has already been passed. | |
*/ | |
C10_API bool CommandLineFlagsHasBeenParsed(); | |
} // namespace c10 | |
//////////////////////////////////////////////////////////////////////////////// | |
// Below are gflags and non-gflags specific implementations. | |
// In general, they define the following macros for one to declare (use | |
// C10_DECLARE) or define (use C10_DEFINE) flags: | |
// C10_{DECLARE,DEFINE}_{int,int64,double,bool,string} | |
//////////////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
// Begin gflags section: most functions are basically rerouted to gflags. | |
//////////////////////////////////////////////////////////////////////////////// | |
// C10 uses hidden visibility by default. However, in gflags, it only uses | |
// export on Windows platform (with dllexport) but not on linux/mac (with | |
// default visibility). As a result, to ensure that we are always exporting | |
// global variables, we will redefine the GFLAGS_DLL_DEFINE_FLAG macro if we | |
// are building C10 as a shared library. | |
// This has to be done after the inclusion of gflags, because some early | |
// versions of gflags.h (e.g. 2.0 on ubuntu 14.04) directly defines the | |
// macros, so we need to do definition after gflags is done. | |
// gflags before 2.0 uses namespace google and after 2.1 uses namespace gflags. | |
// Using GFLAGS_GFLAGS_H_ to capture this change. | |
namespace gflags = google; | |
// Motivation about the gflags wrapper: | |
// (1) We would need to make sure that the gflags version and the non-gflags | |
// version of C10 are going to expose the same flags abstraction. One should | |
// explicitly use FLAGS_flag_name to access the flags. | |
// (2) For flag names, it is recommended to start with c10_ to distinguish it | |
// from regular gflags flags. For example, do | |
// C10_DEFINE_BOOL(c10_my_flag, true, "An example"); | |
// to allow one to use FLAGS_c10_my_flag. | |
// (3) Gflags has a design issue that does not properly expose the global flags, | |
// if one builds the library with -fvisibility=hidden. The current gflags (as of | |
// Aug 2018) only deals with the Windows case using dllexport, and not the Linux | |
// counterparts. As a result, we will explicitly use C10_EXPORT to export the | |
// flags defined in C10. This is done via a global reference, so the flag | |
// itself is not duplicated - under the hood it is the same global gflags flag. | |
DEFINE_# | |
C10_GFLAGS_DEF_WRAPPER(int32, gflags::int32, name, default_value, help_str) | |
C10_DEFINE_int(name, default_value, help_str) | |
C10_GFLAGS_DEF_WRAPPER(int64, gflags::int64, name, default_value, help_str) | |
C10_GFLAGS_DEF_WRAPPER(double, double, name, default_value, help_str) | |
C10_GFLAGS_DEF_WRAPPER(bool, bool, name, default_value, help_str) | |
C10_GFLAGS_DEF_WRAPPER(string, ::fLS::clstring, name, default_value, help_str) | |
// DECLARE_typed_var should be used in header files and in the global namespace. | |
C10_GFLAGS_DECLARE_WRAPPER(int32, gflags::int32, name) | |
C10_GFLAGS_DECLARE_WRAPPER(int64, gflags::int64, name) | |
C10_GFLAGS_DECLARE_WRAPPER(double, double, name) | |
C10_GFLAGS_DECLARE_WRAPPER(string, ::fLS::clstring, name) | |
//////////////////////////////////////////////////////////////////////////////// | |
// End gflags section. | |
//////////////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
// Begin non-gflags section: providing equivalent functionality. | |
//////////////////////////////////////////////////////////////////////////////// | |
namespace c10 { | |
class C10_API C10FlagParser { | |
public: | |
bool success() { | |
return success_; | |
} | |
protected: | |
template <typename T> | |
bool Parse(const std::string& content, T* value); | |
bool success_{false}; | |
}; | |
C10_DECLARE_REGISTRY(C10FlagsRegistry, C10FlagParser, const std::string&); | |
} // namespace c10 | |
// The macros are defined outside the c10 namespace. In your code, you should | |
// write the C10_DEFINE_* and C10_DECLARE_* macros outside any namespace | |
// as well. | |
C10_EXPORT type FLAGS_# | |
namespace c10 { \ | |
namespace { \ | |
class C10FlagParser_##name : public C10FlagParser { \ | |
public: \ | |
explicit C10FlagParser_# | |
success_ = C10FlagParser::Parse<type>(content, &FLAGS_# | |
} \ | |
}; \ | |
} \ | |
RegistererC10FlagsRegistry g_C10FlagsRegistry_# | |
C10FlagsRegistry(), \ | |
RegistererC10FlagsRegistry::DefaultCreator<C10FlagParser_# | |
"(" | |
} | |
C10_DEFINE_typed_var(int, name, default_value, help_str) | |
C10_DEFINE_int(name, default_value, help_str) | |
C10_DEFINE_typed_var(int64_t, name, default_value, help_str) | |
C10_DEFINE_typed_var(double, name, default_value, help_str) | |
C10_DEFINE_typed_var(bool, name, default_value, help_str) | |
C10_DEFINE_typed_var(std::string, name, default_value, help_str) | |
// DECLARE_typed_var should be used in header files and in the global namespace. | |
//////////////////////////////////////////////////////////////////////////////// | |
// End non-gflags section. | |
//////////////////////////////////////////////////////////////////////////////// | |