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.
pull/1683/head
Thomas Van Lenten 9 years ago
parent 71f4a9c6f3
commit a2a3399a6f
  1. 17
      objectivec/README.md
  2. 42
      src/google/protobuf/compiler/objectivec/objectivec_file.cc
  3. 2
      src/google/protobuf/compiler/objectivec/objectivec_file.h
  4. 2
      src/google/protobuf/compiler/objectivec/objectivec_generator.cc
  5. 1
      src/google/protobuf/compiler/objectivec/objectivec_helpers.h

@ -123,8 +123,8 @@ never included when the message is encoded.
The Objective C classes/enums can be used from Swift code. 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) **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 and Objects (for messages) generated from the proto. Convention is to base
the prefix on the package the proto is in. 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 Contributing
------------ ------------

@ -54,14 +54,16 @@ namespace {
class ImportWriter { class ImportWriter {
public: public:
ImportWriter() {} ImportWriter(const Options& options) : options_(options) {}
void AddFile(const FileGenerator* file); void AddFile(const FileGenerator* file);
void Print(io::Printer *printer) const; void Print(io::Printer *printer) const;
private: private:
const Options options_;
vector<string> protobuf_framework_imports_; vector<string> protobuf_framework_imports_;
vector<string> protobuf_non_framework_imports_; vector<string> protobuf_non_framework_imports_;
vector<string> other_framework_imports_;
vector<string> other_imports_; vector<string> other_imports_;
}; };
@ -72,6 +74,10 @@ void ImportWriter::AddFile(const FileGenerator* file) {
protobuf_framework_imports_.push_back( protobuf_framework_imports_.push_back(
FilePathBasename(file_descriptor) + extension); FilePathBasename(file_descriptor) + extension);
protobuf_non_framework_imports_.push_back(file->Path() + 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 { } else {
other_imports_.push_back(file->Path() + extension); other_imports_.push_back(file->Path() + extension);
} }
@ -81,6 +87,8 @@ void ImportWriter::Print(io::Printer *printer) const {
assert(protobuf_non_framework_imports_.size() == assert(protobuf_non_framework_imports_.size() ==
protobuf_framework_imports_.size()); protobuf_framework_imports_.size());
bool add_blank_line = false;
if (protobuf_framework_imports_.size() > 0) { if (protobuf_framework_imports_.size() > 0) {
const string framework_name(ProtobufLibraryFrameworkName); const string framework_name(ProtobufLibraryFrameworkName);
const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name)); const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));
@ -106,12 +114,29 @@ void ImportWriter::Print(io::Printer *printer) const {
printer->Print( printer->Print(
"#endif\n"); "#endif\n");
if (other_imports_.size() > 0) { add_blank_line = true;
}
if (other_framework_imports_.size() > 0) {
if (add_blank_line) {
printer->Print("\n"); 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 (other_imports_.size() > 0) {
if (add_blank_line) {
printer->Print("\n");
}
for (vector<string>::const_iterator iter = other_imports_.begin(); for (vector<string>::const_iterator iter = other_imports_.begin();
iter != other_imports_.end(); ++iter) { iter != other_imports_.end(); ++iter) {
printer->Print( printer->Print(
@ -156,7 +181,7 @@ FileGenerator::~FileGenerator() {
} }
void FileGenerator::GenerateHeader(io::Printer *printer) { 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 // Add some verification that the generated code matches the source the
// code is being compiled with. // 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. // #import any headers for "public imports" in the proto file.
{ {
ImportWriter import_writer; ImportWriter import_writer(options_);
const vector<FileGenerator *> &dependency_generators = DependencyGenerators(); const vector<FileGenerator *> &dependency_generators = DependencyGenerators();
for (vector<FileGenerator *>::const_iterator iter = for (vector<FileGenerator *>::const_iterator iter =
dependency_generators.begin(); dependency_generators.begin();
@ -273,10 +298,10 @@ void FileGenerator::GenerateHeader(io::Printer *printer) {
void FileGenerator::GenerateSource(io::Printer *printer) { void FileGenerator::GenerateSource(io::Printer *printer) {
// #import the runtime support. // #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 the header for this proto file.
import_writer.AddFile(this); import_writer.AddFile(this);
@ -471,7 +496,10 @@ const vector<FileGenerator *> &FileGenerator::DependencyGenerators() {
return dependency_generators_; 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 { io::Printer* printer, const string& header_to_import) const {
printer->Print( printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n" "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"

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

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

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

Loading…
Cancel
Save