Flags.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
  2. #ifndef C10_UTIL_FLAGS_H_
  3. #define C10_UTIL_FLAGS_H_
  4. /* Commandline flags support for C10.
  5. *
  6. * This is a portable commandline flags tool for c10, so we can optionally
  7. * choose to use gflags or a lightweight custom implementation if gflags is
  8. * not possible on a certain platform. If you have gflags installed, set the
  9. * macro C10_USE_GFLAGS will seamlessly route everything to gflags.
  10. *
  11. * To define a flag foo of type bool default to true, do the following in the
  12. * *global* namespace:
  13. * C10_DEFINE_bool(foo, true, "An example.");
  14. *
  15. * To use it in another .cc file, you can use C10_DECLARE_* as follows:
  16. * C10_DECLARE_bool(foo);
  17. *
  18. * In both cases, you can then access the flag via FLAGS_foo.
  19. *
  20. * It is recommended that you build with gflags. To learn more about the flags
  21. * usage, refer to the gflags page here:
  22. *
  23. * https://gflags.github.io/gflags/
  24. *
  25. * Note about Python users / devs: gflags is initiated from a C++ function
  26. * ParseCommandLineFlags, and is usually done in native binaries in the main
  27. * function. As Python does not have a modifiable main function, it is usually
  28. * difficult to change the flags after Python starts. Hence, it is recommended
  29. * that one sets the default value of the flags to one that's acceptable in
  30. * general - that will allow Python to run without wrong flags.
  31. */
  32. #include <c10/macros/Export.h>
  33. #include <string>
  34. #include <c10/util/Registry.h>
  35. namespace c10 {
  36. /**
  37. * Sets the usage message when a commandline tool is called with "--help".
  38. */
  39. C10_API void SetUsageMessage(const std::string& str);
  40. /**
  41. * Returns the usage message for the commandline tool set by SetUsageMessage.
  42. */
  43. C10_API const char* UsageMessage();
  44. /**
  45. * Parses the commandline flags.
  46. *
  47. * This command parses all the commandline arguments passed in via pargc
  48. * and argv. Once it is finished, partc and argv will contain the remaining
  49. * commandline args that c10 does not deal with. Note that following
  50. * convention, argv[0] contains the binary name and is not parsed.
  51. */
  52. C10_API bool ParseCommandLineFlags(int* pargc, char*** pargv);
  53. /**
  54. * Checks if the commandline flags has already been passed.
  55. */
  56. C10_API bool CommandLineFlagsHasBeenParsed();
  57. } // namespace c10
  58. ////////////////////////////////////////////////////////////////////////////////
  59. // Below are gflags and non-gflags specific implementations.
  60. // In general, they define the following macros for one to declare (use
  61. // C10_DECLARE) or define (use C10_DEFINE) flags:
  62. // C10_{DECLARE,DEFINE}_{int,int64,double,bool,string}
  63. ////////////////////////////////////////////////////////////////////////////////
  64. #ifdef C10_USE_GFLAGS
  65. ////////////////////////////////////////////////////////////////////////////////
  66. // Begin gflags section: most functions are basically rerouted to gflags.
  67. ////////////////////////////////////////////////////////////////////////////////
  68. #include <gflags/gflags.h>
  69. // C10 uses hidden visibility by default. However, in gflags, it only uses
  70. // export on Windows platform (with dllexport) but not on linux/mac (with
  71. // default visibility). As a result, to ensure that we are always exporting
  72. // global variables, we will redefine the GFLAGS_DLL_DEFINE_FLAG macro if we
  73. // are building C10 as a shared library.
  74. // This has to be done after the inclusion of gflags, because some early
  75. // versions of gflags.h (e.g. 2.0 on ubuntu 14.04) directly defines the
  76. // macros, so we need to do definition after gflags is done.
  77. #ifdef GFLAGS_DLL_DEFINE_FLAG
  78. #undef GFLAGS_DLL_DEFINE_FLAG
  79. #endif // GFLAGS_DLL_DEFINE_FLAG
  80. #ifdef GFLAGS_DLL_DECLARE_FLAG
  81. #undef GFLAGS_DLL_DECLARE_FLAG
  82. #endif // GFLAGS_DLL_DECLARE_FLAG
  83. #define GFLAGS_DLL_DEFINE_FLAG C10_EXPORT
  84. #define GFLAGS_DLL_DECLARE_FLAG C10_IMPORT
  85. // gflags before 2.0 uses namespace google and after 2.1 uses namespace gflags.
  86. // Using GFLAGS_GFLAGS_H_ to capture this change.
  87. #ifndef GFLAGS_GFLAGS_H_
  88. namespace gflags = google;
  89. #endif // GFLAGS_GFLAGS_H_
  90. // Motivation about the gflags wrapper:
  91. // (1) We would need to make sure that the gflags version and the non-gflags
  92. // version of C10 are going to expose the same flags abstraction. One should
  93. // explicitly use FLAGS_flag_name to access the flags.
  94. // (2) For flag names, it is recommended to start with c10_ to distinguish it
  95. // from regular gflags flags. For example, do
  96. // C10_DEFINE_BOOL(c10_my_flag, true, "An example");
  97. // to allow one to use FLAGS_c10_my_flag.
  98. // (3) Gflags has a design issue that does not properly expose the global flags,
  99. // if one builds the library with -fvisibility=hidden. The current gflags (as of
  100. // Aug 2018) only deals with the Windows case using dllexport, and not the Linux
  101. // counterparts. As a result, we will explicitly use C10_EXPORT to export the
  102. // flags defined in C10. This is done via a global reference, so the flag
  103. // itself is not duplicated - under the hood it is the same global gflags flag.
  104. #define C10_GFLAGS_DEF_WRAPPER(type, real_type, name, default_value, help_str) \
  105. DEFINE_##type(name, default_value, help_str);
  106. #define C10_DEFINE_int(name, default_value, help_str) \
  107. C10_GFLAGS_DEF_WRAPPER(int32, gflags::int32, name, default_value, help_str)
  108. #define C10_DEFINE_int32(name, default_value, help_str) \
  109. C10_DEFINE_int(name, default_value, help_str)
  110. #define C10_DEFINE_int64(name, default_value, help_str) \
  111. C10_GFLAGS_DEF_WRAPPER(int64, gflags::int64, name, default_value, help_str)
  112. #define C10_DEFINE_double(name, default_value, help_str) \
  113. C10_GFLAGS_DEF_WRAPPER(double, double, name, default_value, help_str)
  114. #define C10_DEFINE_bool(name, default_value, help_str) \
  115. C10_GFLAGS_DEF_WRAPPER(bool, bool, name, default_value, help_str)
  116. #define C10_DEFINE_string(name, default_value, help_str) \
  117. C10_GFLAGS_DEF_WRAPPER(string, ::fLS::clstring, name, default_value, help_str)
  118. // DECLARE_typed_var should be used in header files and in the global namespace.
  119. #define C10_GFLAGS_DECLARE_WRAPPER(type, real_type, name) DECLARE_##type(name);
  120. #define C10_DECLARE_int(name) \
  121. C10_GFLAGS_DECLARE_WRAPPER(int32, gflags::int32, name)
  122. #define C10_DECLARE_int32(name) C10_DECLARE_int(name)
  123. #define C10_DECLARE_int64(name) \
  124. C10_GFLAGS_DECLARE_WRAPPER(int64, gflags::int64, name)
  125. #define C10_DECLARE_double(name) \
  126. C10_GFLAGS_DECLARE_WRAPPER(double, double, name)
  127. #define C10_DECLARE_bool(name) C10_GFLAGS_DECLARE_WRAPPER(bool, bool, name)
  128. #define C10_DECLARE_string(name) \
  129. C10_GFLAGS_DECLARE_WRAPPER(string, ::fLS::clstring, name)
  130. #define TORCH_DECLARE_int(name) C10_DECLARE_int(name)
  131. #define TORCH_DECLARE_int32(name) C10_DECLARE_int32(name)
  132. #define TORCH_DECLARE_int64(name) C10_DECLARE_int64(name)
  133. #define TORCH_DECLARE_double(name) C10_DECLARE_double(name)
  134. #define TORCH_DECLARE_bool(name) C10_DECLARE_bool(name)
  135. #define TORCH_DECLARE_string(name) C10_DECLARE_string(name)
  136. ////////////////////////////////////////////////////////////////////////////////
  137. // End gflags section.
  138. ////////////////////////////////////////////////////////////////////////////////
  139. #else // C10_USE_GFLAGS
  140. ////////////////////////////////////////////////////////////////////////////////
  141. // Begin non-gflags section: providing equivalent functionality.
  142. ////////////////////////////////////////////////////////////////////////////////
  143. namespace c10 {
  144. class C10_API C10FlagParser {
  145. public:
  146. bool success() {
  147. return success_;
  148. }
  149. protected:
  150. template <typename T>
  151. bool Parse(const std::string& content, T* value);
  152. bool success_{false};
  153. };
  154. C10_DECLARE_REGISTRY(C10FlagsRegistry, C10FlagParser, const std::string&);
  155. } // namespace c10
  156. // The macros are defined outside the c10 namespace. In your code, you should
  157. // write the C10_DEFINE_* and C10_DECLARE_* macros outside any namespace
  158. // as well.
  159. #define C10_DEFINE_typed_var(type, name, default_value, help_str) \
  160. C10_EXPORT type FLAGS_##name = default_value; \
  161. namespace c10 { \
  162. namespace { \
  163. class C10FlagParser_##name : public C10FlagParser { \
  164. public: \
  165. explicit C10FlagParser_##name(const std::string& content) { \
  166. success_ = C10FlagParser::Parse<type>(content, &FLAGS_##name); \
  167. } \
  168. }; \
  169. RegistererC10FlagsRegistry g_C10FlagsRegistry_##name( \
  170. #name, \
  171. C10FlagsRegistry(), \
  172. RegistererC10FlagsRegistry::DefaultCreator<C10FlagParser_##name>, \
  173. "(" #type ", default " #default_value ") " help_str); \
  174. } \
  175. }
  176. #define C10_DEFINE_int(name, default_value, help_str) \
  177. C10_DEFINE_typed_var(int, name, default_value, help_str)
  178. #define C10_DEFINE_int32(name, default_value, help_str) \
  179. C10_DEFINE_int(name, default_value, help_str)
  180. #define C10_DEFINE_int64(name, default_value, help_str) \
  181. C10_DEFINE_typed_var(int64_t, name, default_value, help_str)
  182. #define C10_DEFINE_double(name, default_value, help_str) \
  183. C10_DEFINE_typed_var(double, name, default_value, help_str)
  184. #define C10_DEFINE_bool(name, default_value, help_str) \
  185. C10_DEFINE_typed_var(bool, name, default_value, help_str)
  186. #define C10_DEFINE_string(name, default_value, help_str) \
  187. C10_DEFINE_typed_var(std::string, name, default_value, help_str)
  188. // DECLARE_typed_var should be used in header files and in the global namespace.
  189. #define C10_DECLARE_typed_var(type, name) C10_API extern type FLAGS_##name
  190. #define C10_DECLARE_int(name) C10_DECLARE_typed_var(int, name)
  191. #define C10_DECLARE_int32(name) C10_DECLARE_int(name)
  192. #define C10_DECLARE_int64(name) C10_DECLARE_typed_var(int64_t, name)
  193. #define C10_DECLARE_double(name) C10_DECLARE_typed_var(double, name)
  194. #define C10_DECLARE_bool(name) C10_DECLARE_typed_var(bool, name)
  195. #define C10_DECLARE_string(name) C10_DECLARE_typed_var(std::string, name)
  196. #define TORCH_DECLARE_typed_var(type, name) TORCH_API extern type FLAGS_##name
  197. #define TORCH_DECLARE_int(name) TORCH_DECLARE_typed_var(int, name)
  198. #define TORCH_DECLARE_int32(name) TORCH_DECLARE_int(name)
  199. #define TORCH_DECLARE_int64(name) TORCH_DECLARE_typed_var(int64_t, name)
  200. #define TORCH_DECLARE_double(name) TORCH_DECLARE_typed_var(double, name)
  201. #define TORCH_DECLARE_bool(name) TORCH_DECLARE_typed_var(bool, name)
  202. #define TORCH_DECLARE_string(name) TORCH_DECLARE_typed_var(std::string, name)
  203. ////////////////////////////////////////////////////////////////////////////////
  204. // End non-gflags section.
  205. ////////////////////////////////////////////////////////////////////////////////
  206. #endif // C10_USE_GFLAGS
  207. #endif // C10_UTIL_FLAGS_H_
  208. #else
  209. #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
  210. #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)