command_line_interface.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // Author: kenton@google.com (Kenton Varda)
  31. // Based on original Protocol Buffers design by
  32. // Sanjay Ghemawat, Jeff Dean, and others.
  33. //
  34. // Implements the Protocol Compiler front-end such that it may be reused by
  35. // custom compilers written to support other languages.
  36. #ifndef GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
  37. #define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
  38. #include <cstdint>
  39. #include <map>
  40. #include <memory>
  41. #include <set>
  42. #include <string>
  43. #include <unordered_map>
  44. #include <unordered_set>
  45. #include <utility>
  46. #include <vector>
  47. #include <google/protobuf/stubs/common.h>
  48. #include <google/protobuf/port_def.inc>
  49. namespace google {
  50. namespace protobuf {
  51. class Descriptor; // descriptor.h
  52. class DescriptorDatabase; // descriptor_database.h
  53. class DescriptorPool; // descriptor.h
  54. class FileDescriptor; // descriptor.h
  55. class FileDescriptorSet; // descriptor.h
  56. class FileDescriptorProto; // descriptor.pb.h
  57. template <typename T>
  58. class RepeatedPtrField; // repeated_field.h
  59. class SimpleDescriptorDatabase; // descriptor_database.h
  60. namespace compiler {
  61. class CodeGenerator; // code_generator.h
  62. class GeneratorContext; // code_generator.h
  63. class DiskSourceTree; // importer.h
  64. // This class implements the command-line interface to the protocol compiler.
  65. // It is designed to make it very easy to create a custom protocol compiler
  66. // supporting the languages of your choice. For example, if you wanted to
  67. // create a custom protocol compiler binary which includes both the regular
  68. // C++ support plus support for your own custom output "Foo", you would
  69. // write a class "FooGenerator" which implements the CodeGenerator interface,
  70. // then write a main() procedure like this:
  71. //
  72. // int main(int argc, char* argv[]) {
  73. // google::protobuf::compiler::CommandLineInterface cli;
  74. //
  75. // // Support generation of C++ source and headers.
  76. // google::protobuf::compiler::cpp::CppGenerator cpp_generator;
  77. // cli.RegisterGenerator("--cpp_out", &cpp_generator,
  78. // "Generate C++ source and header.");
  79. //
  80. // // Support generation of Foo code.
  81. // FooGenerator foo_generator;
  82. // cli.RegisterGenerator("--foo_out", &foo_generator,
  83. // "Generate Foo file.");
  84. //
  85. // return cli.Run(argc, argv);
  86. // }
  87. //
  88. // The compiler is invoked with syntax like:
  89. // protoc --cpp_out=outdir --foo_out=outdir --proto_path=src src/foo.proto
  90. //
  91. // The .proto file to compile can be specified on the command line using either
  92. // its physical file path, or a virtual path relative to a directory specified
  93. // in --proto_path. For example, for src/foo.proto, the following two protoc
  94. // invocations work the same way:
  95. // 1. protoc --proto_path=src src/foo.proto (physical file path)
  96. // 2. protoc --proto_path=src foo.proto (virtual path relative to src)
  97. //
  98. // If a file path can be interpreted both as a physical file path and as a
  99. // relative virtual path, the physical file path takes precedence.
  100. //
  101. // For a full description of the command-line syntax, invoke it with --help.
  102. class PROTOC_EXPORT CommandLineInterface {
  103. public:
  104. static const char* const kPathSeparator;
  105. CommandLineInterface();
  106. ~CommandLineInterface();
  107. // Register a code generator for a language.
  108. //
  109. // Parameters:
  110. // * flag_name: The command-line flag used to specify an output file of
  111. // this type. The name must start with a '-'. If the name is longer
  112. // than one letter, it must start with two '-'s.
  113. // * generator: The CodeGenerator which will be called to generate files
  114. // of this type.
  115. // * help_text: Text describing this flag in the --help output.
  116. //
  117. // Some generators accept extra parameters. You can specify this parameter
  118. // on the command-line by placing it before the output directory, separated
  119. // by a colon:
  120. // protoc --foo_out=enable_bar:outdir
  121. // The text before the colon is passed to CodeGenerator::Generate() as the
  122. // "parameter".
  123. void RegisterGenerator(const std::string& flag_name, CodeGenerator* generator,
  124. const std::string& help_text);
  125. // Register a code generator for a language.
  126. // Besides flag_name you can specify another option_flag_name that could be
  127. // used to pass extra parameters to the registered code generator.
  128. // Suppose you have registered a generator by calling:
  129. // command_line_interface.RegisterGenerator("--foo_out", "--foo_opt", ...)
  130. // Then you could invoke the compiler with a command like:
  131. // protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz
  132. // This will pass "enable_bar,enable_baz" as the parameter to the generator.
  133. void RegisterGenerator(const std::string& flag_name,
  134. const std::string& option_flag_name,
  135. CodeGenerator* generator,
  136. const std::string& help_text);
  137. // Enables "plugins". In this mode, if a command-line flag ends with "_out"
  138. // but does not match any registered generator, the compiler will attempt to
  139. // find a "plugin" to implement the generator. Plugins are just executables.
  140. // They should live somewhere in the PATH.
  141. //
  142. // The compiler determines the executable name to search for by concatenating
  143. // exe_name_prefix with the unrecognized flag name, removing "_out". So, for
  144. // example, if exe_name_prefix is "protoc-" and you pass the flag --foo_out,
  145. // the compiler will try to run the program "protoc-gen-foo".
  146. //
  147. // The plugin program should implement the following usage:
  148. // plugin [--out=OUTDIR] [--parameter=PARAMETER] PROTO_FILES < DESCRIPTORS
  149. // --out indicates the output directory (as passed to the --foo_out
  150. // parameter); if omitted, the current directory should be used. --parameter
  151. // gives the generator parameter, if any was provided (see below). The
  152. // PROTO_FILES list the .proto files which were given on the compiler
  153. // command-line; these are the files for which the plugin is expected to
  154. // generate output code. Finally, DESCRIPTORS is an encoded FileDescriptorSet
  155. // (as defined in descriptor.proto). This is piped to the plugin's stdin.
  156. // The set will include descriptors for all the files listed in PROTO_FILES as
  157. // well as all files that they import. The plugin MUST NOT attempt to read
  158. // the PROTO_FILES directly -- it must use the FileDescriptorSet.
  159. //
  160. // The plugin should generate whatever files are necessary, as code generators
  161. // normally do. It should write the names of all files it generates to
  162. // stdout. The names should be relative to the output directory, NOT absolute
  163. // names or relative to the current directory. If any errors occur, error
  164. // messages should be written to stderr. If an error is fatal, the plugin
  165. // should exit with a non-zero exit code.
  166. //
  167. // Plugins can have generator parameters similar to normal built-in
  168. // generators. Extra generator parameters can be passed in via a matching
  169. // "_opt" parameter. For example:
  170. // protoc --plug_out=enable_bar:outdir --plug_opt=enable_baz
  171. // This will pass "enable_bar,enable_baz" as the parameter to the plugin.
  172. //
  173. void AllowPlugins(const std::string& exe_name_prefix);
  174. // Run the Protocol Compiler with the given command-line parameters.
  175. // Returns the error code which should be returned by main().
  176. //
  177. // It may not be safe to call Run() in a multi-threaded environment because
  178. // it calls strerror(). I'm not sure why you'd want to do this anyway.
  179. int Run(int argc, const char* const argv[]);
  180. // DEPRECATED. Calling this method has no effect. Protocol compiler now
  181. // always try to find the .proto file relative to the current directory
  182. // first and if the file is not found, it will then treat the input path
  183. // as a virtual path.
  184. void SetInputsAreProtoPathRelative(bool /* enable */) {}
  185. // Provides some text which will be printed when the --version flag is
  186. // used. The version of libprotoc will also be printed on the next line
  187. // after this text.
  188. void SetVersionInfo(const std::string& text) { version_info_ = text; }
  189. private:
  190. // -----------------------------------------------------------------
  191. class ErrorPrinter;
  192. class GeneratorContextImpl;
  193. class MemoryOutputStream;
  194. typedef std::unordered_map<std::string, std::unique_ptr<GeneratorContextImpl>>
  195. GeneratorContextMap;
  196. // Clear state from previous Run().
  197. void Clear();
  198. // Remaps the proto file so that it is relative to one of the directories
  199. // in proto_path_. Returns false if an error occurred.
  200. bool MakeProtoProtoPathRelative(DiskSourceTree* source_tree,
  201. std::string* proto,
  202. DescriptorDatabase* fallback_database);
  203. // Remaps each file in input_files_ so that it is relative to one of the
  204. // directories in proto_path_. Returns false if an error occurred.
  205. bool MakeInputsBeProtoPathRelative(DiskSourceTree* source_tree,
  206. DescriptorDatabase* fallback_database);
  207. // Fails if these files use proto3 optional and the code generator doesn't
  208. // support it. This is a permanent check.
  209. bool EnforceProto3OptionalSupport(
  210. const std::string& codegen_name, uint64_t supported_features,
  211. const std::vector<const FileDescriptor*>& parsed_files) const;
  212. // Return status for ParseArguments() and InterpretArgument().
  213. enum ParseArgumentStatus {
  214. PARSE_ARGUMENT_DONE_AND_CONTINUE,
  215. PARSE_ARGUMENT_DONE_AND_EXIT,
  216. PARSE_ARGUMENT_FAIL
  217. };
  218. // Parse all command-line arguments.
  219. ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
  220. // Read an argument file and append the file's content to the list of
  221. // arguments. Return false if the file cannot be read.
  222. bool ExpandArgumentFile(const std::string& file,
  223. std::vector<std::string>* arguments);
  224. // Parses a command-line argument into a name/value pair. Returns
  225. // true if the next argument in the argv should be used as the value,
  226. // false otherwise.
  227. //
  228. // Examples:
  229. // "-Isrc/protos" ->
  230. // name = "-I", value = "src/protos"
  231. // "--cpp_out=src/foo.pb2.cc" ->
  232. // name = "--cpp_out", value = "src/foo.pb2.cc"
  233. // "foo.proto" ->
  234. // name = "", value = "foo.proto"
  235. bool ParseArgument(const char* arg, std::string* name, std::string* value);
  236. // Interprets arguments parsed with ParseArgument.
  237. ParseArgumentStatus InterpretArgument(const std::string& name,
  238. const std::string& value);
  239. // Print the --help text to stderr.
  240. void PrintHelpText();
  241. // Loads proto_path_ into the provided source_tree.
  242. bool InitializeDiskSourceTree(DiskSourceTree* source_tree,
  243. DescriptorDatabase* fallback_database);
  244. // Verify that all the input files exist in the given database.
  245. bool VerifyInputFilesInDescriptors(DescriptorDatabase* fallback_database);
  246. // Parses input_files_ into parsed_files
  247. bool ParseInputFiles(DescriptorPool* descriptor_pool,
  248. DiskSourceTree* source_tree,
  249. std::vector<const FileDescriptor*>* parsed_files);
  250. // Generate the given output file from the given input.
  251. struct OutputDirective; // see below
  252. bool GenerateOutput(const std::vector<const FileDescriptor*>& parsed_files,
  253. const OutputDirective& output_directive,
  254. GeneratorContext* generator_context);
  255. bool GeneratePluginOutput(
  256. const std::vector<const FileDescriptor*>& parsed_files,
  257. const std::string& plugin_name, const std::string& parameter,
  258. GeneratorContext* generator_context, std::string* error);
  259. // Implements --encode and --decode.
  260. bool EncodeOrDecode(const DescriptorPool* pool);
  261. // Implements the --descriptor_set_out option.
  262. bool WriteDescriptorSet(
  263. const std::vector<const FileDescriptor*>& parsed_files);
  264. // Implements the --dependency_out option
  265. bool GenerateDependencyManifestFile(
  266. const std::vector<const FileDescriptor*>& parsed_files,
  267. const GeneratorContextMap& output_directories,
  268. DiskSourceTree* source_tree);
  269. // Get all transitive dependencies of the given file (including the file
  270. // itself), adding them to the given list of FileDescriptorProtos. The
  271. // protos will be ordered such that every file is listed before any file that
  272. // depends on it, so that you can call DescriptorPool::BuildFile() on them
  273. // in order. Any files in *already_seen will not be added, and each file
  274. // added will be inserted into *already_seen. If include_source_code_info is
  275. // true then include the source code information in the FileDescriptorProtos.
  276. // If include_json_name is true, populate the json_name field of
  277. // FieldDescriptorProto for all fields.
  278. static void GetTransitiveDependencies(
  279. const FileDescriptor* file, bool include_json_name,
  280. bool include_source_code_info,
  281. std::set<const FileDescriptor*>* already_seen,
  282. RepeatedPtrField<FileDescriptorProto>* output);
  283. // Implements the --print_free_field_numbers. This function prints free field
  284. // numbers into stdout for the message and it's nested message types in
  285. // post-order, i.e. nested types first. Printed range are left-right
  286. // inclusive, i.e. [a, b].
  287. //
  288. // Groups:
  289. // For historical reasons, groups are considered to share the same
  290. // field number space with the parent message, thus it will not print free
  291. // field numbers for groups. The field numbers used in the groups are
  292. // excluded in the free field numbers of the parent message.
  293. //
  294. // Extension Ranges:
  295. // Extension ranges are considered ocuppied field numbers and they will not be
  296. // listed as free numbers in the output.
  297. void PrintFreeFieldNumbers(const Descriptor* descriptor);
  298. // -----------------------------------------------------------------
  299. // The name of the executable as invoked (i.e. argv[0]).
  300. std::string executable_name_;
  301. // Version info set with SetVersionInfo().
  302. std::string version_info_;
  303. // Registered generators.
  304. struct GeneratorInfo {
  305. std::string flag_name;
  306. std::string option_flag_name;
  307. CodeGenerator* generator;
  308. std::string help_text;
  309. };
  310. typedef std::map<std::string, GeneratorInfo> GeneratorMap;
  311. GeneratorMap generators_by_flag_name_;
  312. GeneratorMap generators_by_option_name_;
  313. // A map from generator names to the parameters specified using the option
  314. // flag. For example, if the user invokes the compiler with:
  315. // protoc --foo_out=outputdir --foo_opt=enable_bar ...
  316. // Then there will be an entry ("--foo_out", "enable_bar") in this map.
  317. std::map<std::string, std::string> generator_parameters_;
  318. // Similar to generator_parameters_, but stores the parameters for plugins.
  319. std::map<std::string, std::string> plugin_parameters_;
  320. // See AllowPlugins(). If this is empty, plugins aren't allowed.
  321. std::string plugin_prefix_;
  322. // Maps specific plugin names to files. When executing a plugin, this map
  323. // is searched first to find the plugin executable. If not found here, the
  324. // PATH (or other OS-specific search strategy) is searched.
  325. std::map<std::string, std::string> plugins_;
  326. // Stuff parsed from command line.
  327. enum Mode {
  328. MODE_COMPILE, // Normal mode: parse .proto files and compile them.
  329. MODE_ENCODE, // --encode: read text from stdin, write binary to stdout.
  330. MODE_DECODE, // --decode: read binary from stdin, write text to stdout.
  331. MODE_PRINT, // Print mode: print info of the given .proto files and exit.
  332. };
  333. Mode mode_ = MODE_COMPILE;
  334. enum PrintMode {
  335. PRINT_NONE, // Not in MODE_PRINT
  336. PRINT_FREE_FIELDS, // --print_free_fields
  337. };
  338. PrintMode print_mode_ = PRINT_NONE;
  339. enum ErrorFormat {
  340. ERROR_FORMAT_GCC, // GCC error output format (default).
  341. ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs).
  342. };
  343. ErrorFormat error_format_ = ERROR_FORMAT_GCC;
  344. // True if we should treat warnings as errors that fail the compilation.
  345. bool fatal_warnings_ = false;
  346. std::vector<std::pair<std::string, std::string> >
  347. proto_path_; // Search path for proto files.
  348. std::vector<std::string> input_files_; // Names of the input proto files.
  349. // Names of proto files which are allowed to be imported. Used by build
  350. // systems to enforce depend-on-what-you-import.
  351. std::set<std::string> direct_dependencies_;
  352. bool direct_dependencies_explicitly_set_ = false;
  353. // If there's a violation of depend-on-what-you-import, this string will be
  354. // presented to the user. "%s" will be replaced with the violating import.
  355. std::string direct_dependencies_violation_msg_;
  356. // output_directives_ lists all the files we are supposed to output and what
  357. // generator to use for each.
  358. struct OutputDirective {
  359. std::string name; // E.g. "--foo_out"
  360. CodeGenerator* generator; // NULL for plugins
  361. std::string parameter;
  362. std::string output_location;
  363. };
  364. std::vector<OutputDirective> output_directives_;
  365. // When using --encode or --decode, this names the type we are encoding or
  366. // decoding. (Empty string indicates --decode_raw.)
  367. std::string codec_type_;
  368. // If --descriptor_set_in was given, these are filenames containing
  369. // parsed FileDescriptorSets to be used for loading protos. Otherwise, empty.
  370. std::vector<std::string> descriptor_set_in_names_;
  371. // If --descriptor_set_out was given, this is the filename to which the
  372. // FileDescriptorSet should be written. Otherwise, empty.
  373. std::string descriptor_set_out_name_;
  374. // If --dependency_out was given, this is the path to the file where the
  375. // dependency file will be written. Otherwise, empty.
  376. std::string dependency_out_name_;
  377. // True if --include_imports was given, meaning that we should
  378. // write all transitive dependencies to the DescriptorSet. Otherwise, only
  379. // the .proto files listed on the command-line are added.
  380. bool imports_in_descriptor_set_;
  381. // True if --include_source_info was given, meaning that we should not strip
  382. // SourceCodeInfo from the DescriptorSet.
  383. bool source_info_in_descriptor_set_ = false;
  384. // Was the --disallow_services flag used?
  385. bool disallow_services_ = false;
  386. // When using --encode, this will be passed to SetSerializationDeterministic.
  387. bool deterministic_output_ = false;
  388. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface);
  389. };
  390. } // namespace compiler
  391. } // namespace protobuf
  392. } // namespace google
  393. #include <google/protobuf/port_undef.inc>
  394. #endif // GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__