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