123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- #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 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.
- */
- #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:
- 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.
- #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_
|