command_line_interface.h 20 KB

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