|  | #ifndef C10_UTIL_FLAGS_H_ | 
|  | #define C10_UTIL_FLAGS_H_ | 
|  |  | 
|  | /* Commandline flags support for C10. | 
|  | * | 
|  | * This is a portable commandline flags tool for c10, so we can optionally | 
|  | * choose to use gflags or a lightweighted 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. | 
|  | */ | 
|  |  | 
|  | #include <string> | 
|  |  | 
|  | #include "c10/macros/Macros.h" | 
|  | #include "c10/util/Registry.h" | 
|  |  | 
|  | 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} | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | #ifdef C10_USE_GFLAGS | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | // Begin gflags section: most functions are basically rerouted to gflags. | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | #include <gflags/gflags.h> | 
|  |  | 
|  | // 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 libray. | 
|  | // 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. | 
|  | #ifdef GFLAGS_DLL_DEFINE_FLAG | 
|  | #undef GFLAGS_DLL_DEFINE_FLAG | 
|  | #endif // GFLAGS_DLL_DEFINE_FLAG | 
|  | #ifdef GFLAGS_DLL_DECLARE_FLAG | 
|  | #undef GFLAGS_DLL_DECLARE_FLAG | 
|  | #endif // GFLAGS_DLL_DECLARE_FLAG | 
|  | #define GFLAGS_DLL_DEFINE_FLAG C10_EXPORT | 
|  | #define GFLAGS_DLL_DECLARE_FLAG C10_IMPORT | 
|  |  | 
|  | // gflags before 2.0 uses namespace google and after 2.1 uses namespace gflags. | 
|  | // Using GFLAGS_GFLAGS_H_ to capture this change. | 
|  | #ifndef GFLAGS_GFLAGS_H_ | 
|  | namespace gflags = google; | 
|  | #endif // GFLAGS_GFLAGS_H_ | 
|  |  | 
|  | // 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 explciitly 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(type, real_type, name, default_value, help_str) \ | 
|  | DEFINE_##type(name, default_value, help_str);                                \ | 
|  |  | 
|  | #define C10_DEFINE_int(name, default_value, help_str) \ | 
|  | C10_GFLAGS_DEF_WRAPPER(int32, gflags::int32, name, default_value, help_str) | 
|  | #define C10_DEFINE_int32(name, default_value, help_str) \ | 
|  | C10_DEFINE_int(name, default_value, help_str) | 
|  | #define C10_DEFINE_int64(name, default_value, help_str) \ | 
|  | C10_GFLAGS_DEF_WRAPPER(int64, gflags::int64, name, default_value, help_str) | 
|  | #define C10_DEFINE_double(name, default_value, help_str) \ | 
|  | C10_GFLAGS_DEF_WRAPPER(double, double, name, default_value, help_str) | 
|  | #define C10_DEFINE_bool(name, default_value, help_str) \ | 
|  | C10_GFLAGS_DEF_WRAPPER(bool, bool, name, default_value, help_str) | 
|  | #define C10_DEFINE_string(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. | 
|  | #define C10_GFLAGS_DECLARE_WRAPPER(type, real_type, name) \ | 
|  | DECLARE_##type(name);                                   \ | 
|  |  | 
|  | #define C10_DECLARE_int(name) \ | 
|  | C10_GFLAGS_DECLARE_WRAPPER(int32, gflags::int32, name) | 
|  | #define C10_DECLARE_int32(name) C10_DECLARE_int(name) | 
|  | #define C10_DECLARE_int64(name) \ | 
|  | C10_GFLAGS_DECLARE_WRAPPER(int64, gflags::int64, name) | 
|  | #define C10_DECLARE_double(name) \ | 
|  | C10_GFLAGS_DECLARE_WRAPPER(double, double, name) | 
|  | #define C10_DECLARE_bool(name) C10_GFLAGS_DECLARE_WRAPPER(bool, bool, name) | 
|  | #define C10_DECLARE_string(name) \ | 
|  | C10_GFLAGS_DECLARE_WRAPPER(string, ::fLS::clstring, name) | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | // End gflags section. | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | #else // C10_USE_GFLAGS | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | // Begin non-gflags section: providing equivalent functionality. | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | namespace c10 { | 
|  |  | 
|  | class C10_API C10FlagParser { | 
|  | public: | 
|  | C10FlagParser() {} | 
|  | bool success() { | 
|  | return success_; | 
|  | } | 
|  |  | 
|  | protected: | 
|  | template <typename T> | 
|  | bool Parse(const std::string& content, T* value); | 
|  | bool success_; | 
|  | }; | 
|  |  | 
|  | 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. | 
|  |  | 
|  | #define C10_DEFINE_typed_var(type, name, default_value, help_str)       \ | 
|  | C10_EXPORT type FLAGS_##name = default_value;                         \ | 
|  | namespace c10 {                                                       \ | 
|  | namespace {                                                           \ | 
|  | class C10FlagParser_##name : public C10FlagParser {                   \ | 
|  | public:                                                              \ | 
|  | explicit C10FlagParser_##name(const std::string& content) {         \ | 
|  | success_ = C10FlagParser::Parse<type>(content, &FLAGS_##name);    \ | 
|  | }                                                                   \ | 
|  | };                                                                    \ | 
|  | }                                                                     \ | 
|  | RegistererC10FlagsRegistry g_C10FlagsRegistry_##name(                 \ | 
|  | #name,                                                            \ | 
|  | C10FlagsRegistry(),                                               \ | 
|  | RegistererC10FlagsRegistry::DefaultCreator<C10FlagParser_##name>, \ | 
|  | "(" #type ", default " #default_value ") " help_str);             \ | 
|  | } | 
|  |  | 
|  | #define C10_DEFINE_int(name, default_value, help_str) \ | 
|  | C10_DEFINE_typed_var(int, name, default_value, help_str) | 
|  | #define C10_DEFINE_int32(name, default_value, help_str) \ | 
|  | C10_DEFINE_int(name, default_value, help_str) | 
|  | #define C10_DEFINE_int64(name, default_value, help_str) \ | 
|  | C10_DEFINE_typed_var(int64_t, name, default_value, help_str) | 
|  | #define C10_DEFINE_double(name, default_value, help_str) \ | 
|  | C10_DEFINE_typed_var(double, name, default_value, help_str) | 
|  | #define C10_DEFINE_bool(name, default_value, help_str) \ | 
|  | C10_DEFINE_typed_var(bool, name, default_value, help_str) | 
|  | #define C10_DEFINE_string(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. | 
|  | #define C10_DECLARE_typed_var(type, name) C10_IMPORT extern type FLAGS_##name | 
|  |  | 
|  | #define C10_DECLARE_int(name) C10_DECLARE_typed_var(int, name) | 
|  | #define C10_DECLARE_int32(name) C10_DECLARE_int(name) | 
|  | #define C10_DECLARE_int64(name) C10_DECLARE_typed_var(int64_t, name) | 
|  | #define C10_DECLARE_double(name) C10_DECLARE_typed_var(double, name) | 
|  | #define C10_DECLARE_bool(name) C10_DECLARE_typed_var(bool, name) | 
|  | #define C10_DECLARE_string(name) C10_DECLARE_typed_var(std::string, name) | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | // End non-gflags section. | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | #endif // C10_USE_GFLAGS | 
|  |  | 
|  | #endif // C10_UTIL_FLAGS_H_ |