• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 // Author: kenton@google.com (Kenton Varda)
9 //  Based on original Protocol Buffers design by
10 //  Sanjay Ghemawat, Jeff Dean, and others.
11 
12 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
13 #define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
14 
15 #include <functional>
16 #include <memory>
17 #include <string>
18 #include <vector>
19 
20 #include "absl/container/flat_hash_map.h"
21 #include "absl/container/flat_hash_set.h"
22 #include "absl/functional/any_invocable.h"
23 #include "absl/log/absl_check.h"
24 #include "absl/strings/string_view.h"
25 #include "google/protobuf/compiler/cpp/enum.h"
26 #include "google/protobuf/compiler/cpp/extension.h"
27 #include "google/protobuf/compiler/cpp/helpers.h"
28 #include "google/protobuf/compiler/cpp/message.h"
29 #include "google/protobuf/compiler/cpp/options.h"
30 #include "google/protobuf/compiler/cpp/service.h"
31 #include "google/protobuf/compiler/scc.h"
32 #include "google/protobuf/descriptor.h"
33 #include "google/protobuf/io/printer.h"
34 
35 // Must be included last.
36 #include "google/protobuf/port_def.inc"
37 
38 namespace google {
39 namespace protobuf {
40 namespace compiler {
41 namespace cpp {
42 class PROTOC_EXPORT FileGenerator {
43  public:
44   FileGenerator(const FileDescriptor* file, const Options& options);
45 
46   FileGenerator(const FileGenerator&) = delete;
47   FileGenerator& operator=(const FileGenerator&) = delete;
48 
49   ~FileGenerator() = default;
50 
51   // info_path, if non-empty, should be the path (relative to printer's
52   // output) to the metadata file describing this proto header.
53   void GenerateProtoHeader(io::Printer* p, absl::string_view info_path);
54   // info_path, if non-empty, should be the path (relative to printer's
55   // output) to the metadata file describing this PB header.
56   void GeneratePBHeader(io::Printer* p, absl::string_view info_path);
57   void GenerateSource(io::Printer* p);
58 
59   // The following member functions are used when the lite_implicit_weak_fields
60   // option is set. In this mode the code is organized a bit differently to
61   // promote better linker stripping of unused code. In particular, we generate
62   // one .cc file per message, one .cc file per extension, and a main pb.cc file
63   // containing everything else.
64 
NumMessages()65   int NumMessages() const { return message_generators_.size(); }
NumExtensions()66   int NumExtensions() const { return extension_generators_.size(); }
67   // Generates the source file for one message.
68   void GenerateSourceForMessage(int idx, io::Printer* p);
69   // Generates the source file for one extension.
70   void GenerateSourceForExtension(int idx, io::Printer* p);
71   // Generates a source file containing everything except messages and
72   // extensions.
73   void GenerateGlobalSource(io::Printer* p);
74 
75  private:
76   // Generates a file, setting up the necessary accoutrements that start and
77   // end the file, calling `cb` in between.
78   //
79   // This includes header guards and file-global variables.
80   void GenerateFile(io::Printer* p, GeneratedFileType file_type,
81                     std::function<void()> cb);
82 
83   // Generates a static initializers with all the existing values from
84   // `static_initializers_`.
85   // They run in `PROTOBUF_ATTRIBUTE_INIT_PRIORITY1` and
86   // `PROTOBUF_ATTRIBUTE_INIT_PRIORITY2` priority respectively.
87   void GenerateStaticInitializer(io::Printer* p);
88 
89   // Shared code between the two header generators.
90   void GenerateSharedHeaderCode(io::Printer* p);
91 
92   // Internal type used by GenerateForwardDeclarations (defined in file.cc).
93   class ForwardDeclarations;
94   struct CrossFileReferences;
95 
IncludeFile(absl::string_view google3_name,io::Printer * p)96   void IncludeFile(absl::string_view google3_name, io::Printer* p) {
97     DoIncludeFile(google3_name, false, p);
98   }
IncludeFileAndExport(absl::string_view google3_name,io::Printer * p)99   void IncludeFileAndExport(absl::string_view google3_name, io::Printer* p) {
100     DoIncludeFile(google3_name, true, p);
101   }
102   void DoIncludeFile(absl::string_view google3_name, bool do_export,
103                      io::Printer* p);
104 
105   std::string CreateHeaderInclude(absl::string_view basename,
106                                   const FileDescriptor* file);
107   void GetCrossFileReferencesForField(const FieldDescriptor* field,
108                                       CrossFileReferences* refs);
109   void GetCrossFileReferencesForFile(const FileDescriptor* file,
110                                      CrossFileReferences* refs);
111   void GenerateInternalForwardDeclarations(const CrossFileReferences& refs,
112                                            io::Printer* p);
113   void GenerateSourceIncludes(io::Printer* p);
114   void GenerateSourcePrelude(io::Printer* p);
115   void GenerateSourceDefaultInstance(int idx, io::Printer* p);
116 
117   void GenerateInitForSCC(const SCC* scc, const CrossFileReferences& refs,
118                           io::Printer* p);
119   void GenerateReflectionInitializationCode(io::Printer* p);
120 
121   // For other imports, generates their forward-declarations.
122   void GenerateForwardDeclarations(io::Printer* p);
123 
124   // Generates top or bottom of a header file.
125   void GenerateTopHeaderGuard(io::Printer* p, GeneratedFileType file_type);
126   void GenerateBottomHeaderGuard(io::Printer* p, GeneratedFileType file_type);
127 
128   // Generates #include directives.
129   void GenerateLibraryIncludes(io::Printer* p);
130   void GenerateDependencyIncludes(io::Printer* p);
131 
132   // Generate a pragma to pull in metadata using the given info_path (if
133   // non-empty). info_path should be relative to printer's output.
134   void GenerateMetadataPragma(io::Printer* p, absl::string_view info_path);
135 
136   // Generates a couple of different pieces before definitions:
137   void GenerateGlobalStateFunctionDeclarations(io::Printer* p);
138 
139   // Generates types for classes.
140   void GenerateMessageDefinitions(io::Printer* p);
141 
142   void GenerateEnumDefinitions(io::Printer* p);
143 
144   // Generates generic service definitions.
145   void GenerateServiceDefinitions(io::Printer* p);
146 
147   // Generates extension identifiers.
148   void GenerateExtensionIdentifiers(io::Printer* p);
149 
150   // Generates inline function definitions.
151   void GenerateInlineFunctionDefinitions(io::Printer* p);
152 
153   void GenerateProto2NamespaceEnumSpecializations(io::Printer* p);
154 
155   // Sometimes the names we use in a .proto file happen to be defined as
156   // macros on some platforms (e.g., macro/minor used in plugin.proto are
157   // defined as macros in sys/types.h on FreeBSD and a few other platforms).
158   // To make the generated code compile on these platforms, we either have to
159   // undef the macro for these few platforms, or rename the field name for all
160   // platforms. Since these names are part of protobuf public API, renaming is
161   // generally a breaking change so we prefer the #undef approach.
162   void GenerateMacroUndefs(io::Printer* p);
163 
164   // Calculates if we should skip importing a specific dependency.
165   bool ShouldSkipDependencyImports(const FileDescriptor* dep) const;
166 
IsDepWeak(const FileDescriptor * dep)167   bool IsDepWeak(const FileDescriptor* dep) const {
168     if (weak_deps_.count(dep) != 0) {
169       ABSL_CHECK(!options_.opensource_runtime);
170       return true;
171     }
172     return false;
173   }
174 
175   // For testing only.  Returns the descriptors ordered topologically.
176   std::vector<const Descriptor*> MessagesInTopologicalOrder() const;
177   friend class FileGeneratorFriendForTesting;
178 
179   absl::flat_hash_set<const FileDescriptor*> weak_deps_;
180 
181   std::vector<absl::AnyInvocable<void(io::Printer*)>> static_initializers_[2];
182 
183   const FileDescriptor* file_;
184   Options options_;
185 
186   MessageSCCAnalyzer scc_analyzer_;
187 
188   // This member is unused and should be deleted once all old-style variable
189   // maps are gone.
190   // TODO
191   absl::flat_hash_map<absl::string_view, std::string> variables_;
192 
193   // Contains the post-order walk of all the messages (and nested messages)
194   // defined in this file. If you need a pre-order walk just reverse iterate.
195   std::vector<std::unique_ptr<MessageGenerator>> message_generators_;
196   std::vector<int> message_generators_topologically_ordered_;
197   std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
198   std::vector<std::unique_ptr<ServiceGenerator>> service_generators_;
199   std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
200 };
201 
202 }  // namespace cpp
203 }  // namespace compiler
204 }  // namespace protobuf
205 }  // namespace google
206 
207 #include "google/protobuf/port_undef.inc"
208 
209 #endif  // GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
210