Browse Source

Add support for generation sources into a framework.

- Add a protoc objc option (generate_for_named_framework) to set the name of
  the framework all generated sources will be in.
- Tweak some comments/naming to make it clear what is the Protobuf framework
  vs. the framework for generated code.
- Update the objc README to document the new generation option to protoc.

This is working towards https://github.com/google/protobuf/issues/1457.
Thomas Van Lenten 9 years ago
parent
commit
a2a3399a6f

+ 15 - 2
objectivec/README.md

@@ -123,8 +123,8 @@ never included when the message is encoded.
 
 The Objective C classes/enums can be used from Swift code.
 
-Objective C Generator Options
------------------------------
+Objective C Generator Proto File Options
+----------------------------------------
 
 **objc_class_prefix=\<prefix\>** (no default)
 
@@ -133,6 +133,19 @@ be collisions. This option provides a prefix that will be added to the Enums
 and Objects (for messages) generated from the proto. Convention is to base
 the prefix on the package the proto is in.
 
+Objective C Generator `protoc` Options
+--------------------------------------
+
+When generating Objective C code, `protoc` supports a `--objc_opt` argument; the
+argument is comma-delimited name/value pairs (_key=value,key2=value2_). The
+_keys_ are used to change the behavior during generation. The currently
+supported keys are:
+
+  * `generate_for_framework_named`: The `value` used for this key will be used
+    when generating the `#import` statements in the generated code.  Instead
+    of being plain `#import "some/path/file.pbobjc.h"` lines, they will be
+    framework based, i.e. - `#import <VALUE/file.pbobjc.h>`.
+
 Contributing
 ------------
 

+ 35 - 7
src/google/protobuf/compiler/objectivec/objectivec_file.cc

@@ -54,14 +54,16 @@ namespace {
 
 class ImportWriter {
  public:
-  ImportWriter() {}
+  ImportWriter(const Options& options) : options_(options) {}
 
   void AddFile(const FileGenerator* file);
   void Print(io::Printer *printer) const;
 
  private:
+  const Options options_;
   vector<string> protobuf_framework_imports_;
   vector<string> protobuf_non_framework_imports_;
+  vector<string> other_framework_imports_;
   vector<string> other_imports_;
 };
 
@@ -72,6 +74,10 @@ void ImportWriter::AddFile(const FileGenerator* file) {
     protobuf_framework_imports_.push_back(
         FilePathBasename(file_descriptor) + extension);
     protobuf_non_framework_imports_.push_back(file->Path() + extension);
+  } else if (!options_.generate_for_named_framework.empty()) {
+    other_framework_imports_.push_back(
+        options_.generate_for_named_framework + "/" +
+        FilePathBasename(file_descriptor) + extension);
   } else {
     other_imports_.push_back(file->Path() + extension);
   }
@@ -81,6 +87,8 @@ void ImportWriter::Print(io::Printer *printer) const {
   assert(protobuf_non_framework_imports_.size() ==
          protobuf_framework_imports_.size());
 
+  bool add_blank_line = false;
+
   if (protobuf_framework_imports_.size() > 0) {
     const string framework_name(ProtobufLibraryFrameworkName);
     const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));
@@ -106,12 +114,29 @@ void ImportWriter::Print(io::Printer *printer) const {
     printer->Print(
         "#endif\n");
 
-    if (other_imports_.size() > 0) {
+    add_blank_line = true;
+  }
+
+  if (other_framework_imports_.size() > 0) {
+    if (add_blank_line) {
       printer->Print("\n");
     }
+
+    for (vector<string>::const_iterator iter = other_framework_imports_.begin();
+         iter != other_framework_imports_.end(); ++iter) {
+      printer->Print(
+          " #import <$header$>\n",
+          "header", *iter);
+    }
+
+    add_blank_line = true;
   }
 
   if (other_imports_.size() > 0) {
+    if (add_blank_line) {
+      printer->Print("\n");
+    }
+
     for (vector<string>::const_iterator iter = other_imports_.begin();
          iter != other_imports_.end(); ++iter) {
       printer->Print(
@@ -156,7 +181,7 @@ FileGenerator::~FileGenerator() {
 }
 
 void FileGenerator::GenerateHeader(io::Printer *printer) {
-  PrintFilePreamble(printer, "GPBProtocolBuffers.h");
+  PrintFileRuntimePreamble(printer, "GPBProtocolBuffers.h");
 
   // Add some verification that the generated code matches the source the
   // code is being compiled with.
@@ -170,7 +195,7 @@ void FileGenerator::GenerateHeader(io::Printer *printer) {
 
   // #import any headers for "public imports" in the proto file.
   {
-    ImportWriter import_writer;
+    ImportWriter import_writer(options_);
     const vector<FileGenerator *> &dependency_generators = DependencyGenerators();
     for (vector<FileGenerator *>::const_iterator iter =
              dependency_generators.begin();
@@ -273,10 +298,10 @@ void FileGenerator::GenerateHeader(io::Printer *printer) {
 
 void FileGenerator::GenerateSource(io::Printer *printer) {
   // #import the runtime support.
-  PrintFilePreamble(printer, "GPBProtocolBuffers_RuntimeSupport.h");
+  PrintFileRuntimePreamble(printer, "GPBProtocolBuffers_RuntimeSupport.h");
 
   {
-    ImportWriter import_writer;
+    ImportWriter import_writer(options_);
 
     // #import the header for this proto file.
     import_writer.AddFile(this);
@@ -471,7 +496,10 @@ const vector<FileGenerator *> &FileGenerator::DependencyGenerators() {
   return dependency_generators_;
 }
 
-void FileGenerator::PrintFilePreamble(
+// Helper to print the import of the runtime support at the top of generated
+// files. This currently only supports the runtime coming from a framework
+// as defined by the official CocoaPod.
+void FileGenerator::PrintFileRuntimePreamble(
     io::Printer* printer, const string& header_to_import) const {
   printer->Print(
       "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"

+ 1 - 1
src/google/protobuf/compiler/objectivec/objectivec_file.h

@@ -88,7 +88,7 @@ class FileGenerator {
   const Options options_;
 
   const vector<FileGenerator*>& DependencyGenerators();
-  void PrintFilePreamble(
+  void PrintFileRuntimePreamble(
       io::Printer* printer, const string& header_to_import) const;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);

+ 2 - 0
src/google/protobuf/compiler/objectivec/objectivec_generator.cc

@@ -59,6 +59,8 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
   for (int i = 0; i < options.size(); i++) {
     if (options[i].first == "expected_prefixes_path") {
       generation_options.expected_prefixes_path = options[i].second;
+    } else if (options[i].first == "generate_for_named_framework") {
+      generation_options.generate_for_named_framework = options[i].second;
     } else {
       *error = "error: Unknown generator option: " + options[i].first;
       return false;

+ 1 - 0
src/google/protobuf/compiler/objectivec/objectivec_helpers.h

@@ -46,6 +46,7 @@ namespace objectivec {
 struct Options {
   Options();
   string expected_prefixes_path;
+  string generate_for_named_framework;
 };
 
 // Escape C++ trigraphs by escaping question marks to "\?".