aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf')
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.cc171
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.h5
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.cc54
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.h17
4 files changed, 199 insertions, 48 deletions
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
index ed4fc6a3..ccf5fbb4 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
@@ -50,6 +50,80 @@ const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30001;
namespace compiler {
namespace objectivec {
+namespace {
+
+class ImportWriter {
+ public:
+ ImportWriter() {}
+
+ void AddFile(const FileGenerator* file);
+ void Print(io::Printer *printer) const;
+
+ private:
+ vector<string> protobuf_framework_imports_;
+ vector<string> protobuf_non_framework_imports_;
+ vector<string> other_imports_;
+};
+
+void ImportWriter::AddFile(const FileGenerator* file) {
+ const FileDescriptor* file_descriptor = file->Descriptor();
+ const string extension(".pbobjc.h");
+ if (IsProtobufLibraryBundledProtoFile(file_descriptor)) {
+ protobuf_framework_imports_.push_back(
+ FilePathBasename(file_descriptor) + extension);
+ protobuf_non_framework_imports_.push_back(file->Path() + extension);
+ } else {
+ other_imports_.push_back(file->Path() + extension);
+ }
+}
+
+void ImportWriter::Print(io::Printer *printer) const {
+ assert(protobuf_non_framework_imports_.size() ==
+ protobuf_framework_imports_.size());
+
+ if (protobuf_framework_imports_.size() > 0) {
+ const string framework_name(ProtobufLibraryFrameworkName);
+ const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));
+
+ printer->Print(
+ "#if $cpp_symbol$\n",
+ "cpp_symbol", cpp_symbol);
+ for (vector<string>::const_iterator iter = protobuf_framework_imports_.begin();
+ iter != protobuf_framework_imports_.end(); ++iter) {
+ printer->Print(
+ " #import <$framework_name$/$header$>\n",
+ "framework_name", framework_name,
+ "header", *iter);
+ }
+ printer->Print(
+ "#else\n");
+ for (vector<string>::const_iterator iter = protobuf_non_framework_imports_.begin();
+ iter != protobuf_non_framework_imports_.end(); ++iter) {
+ printer->Print(
+ " #import \"$header$\"\n",
+ "header", *iter);
+ }
+ printer->Print(
+ "#endif\n");
+
+ if (other_imports_.size() > 0) {
+ printer->Print("\n");
+ }
+ }
+
+ if (other_imports_.size() > 0) {
+ for (vector<string>::const_iterator iter = other_imports_.begin();
+ iter != other_imports_.end(); ++iter) {
+ printer->Print(
+ " #import \"$header$\"\n",
+ "header", *iter);
+ }
+ }
+}
+
+} // namespace
+
+
FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options)
: file_(file),
root_class_name_(FileClassName(file)),
@@ -82,15 +156,7 @@ FileGenerator::~FileGenerator() {
}
void FileGenerator::GenerateHeader(io::Printer *printer) {
- printer->Print(
- "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "// source: $filename$\n"
- "\n",
- "filename", file_->name());
-
- printer->Print(
- "#import \"GPBProtocolBuffers.h\"\n"
- "\n");
+ PrintFilePreamble(printer, "GPBProtocolBuffers.h");
// Add some verification that the generated code matches the source the
// code is being compiled with.
@@ -102,14 +168,18 @@ void FileGenerator::GenerateHeader(io::Printer *printer) {
"protoc_gen_objc_version",
SimpleItoa(GOOGLE_PROTOBUF_OBJC_GEN_VERSION));
- const vector<FileGenerator *> &dependency_generators = DependencyGenerators();
- for (vector<FileGenerator *>::const_iterator iter =
- dependency_generators.begin();
- iter != dependency_generators.end(); ++iter) {
- if ((*iter)->IsPublicDependency()) {
- printer->Print("#import \"$header$.pbobjc.h\"\n",
- "header", (*iter)->Path());
+ // #import any headers for "public imports" in the proto file.
+ {
+ ImportWriter import_writer;
+ const vector<FileGenerator *> &dependency_generators = DependencyGenerators();
+ for (vector<FileGenerator *>::const_iterator iter =
+ dependency_generators.begin();
+ iter != dependency_generators.end(); ++iter) {
+ if ((*iter)->IsPublicDependency()) {
+ import_writer.AddFile(*iter);
+ }
}
+ import_writer.Print(printer);
}
printer->Print(
@@ -198,27 +268,30 @@ void FileGenerator::GenerateHeader(io::Printer *printer) {
}
void FileGenerator::GenerateSource(io::Printer *printer) {
- printer->Print(
- "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "// source: $filename$\n"
- "\n",
- "filename", file_->name());
+ // #import the runtime support.
+ PrintFilePreamble(printer, "GPBProtocolBuffers_RuntimeSupport.h");
- string header_file = Path() + ".pbobjc.h";
- printer->Print(
- "#import \"GPBProtocolBuffers_RuntimeSupport.h\"\n"
- "#import \"$header_file$\"\n",
- "header_file", header_file);
- const vector<FileGenerator *> &dependency_generators =
- DependencyGenerators();
- for (vector<FileGenerator *>::const_iterator iter =
- dependency_generators.begin();
- iter != dependency_generators.end(); ++iter) {
- if (!(*iter)->IsPublicDependency()) {
- printer->Print("#import \"$header$.pbobjc.h\"\n",
- "header", (*iter)->Path());
+ {
+ ImportWriter import_writer;
+
+ // #import the header for this proto file.
+ import_writer.AddFile(this);
+
+ // #import the headers for anything that a plain dependency of this proto
+ // file (that means they were just an include, not a "public" include).
+ const vector<FileGenerator *> &dependency_generators =
+ DependencyGenerators();
+ for (vector<FileGenerator *>::const_iterator iter =
+ dependency_generators.begin();
+ iter != dependency_generators.end(); ++iter) {
+ if (!(*iter)->IsPublicDependency()) {
+ import_writer.AddFile(*iter);
+ }
}
+
+ import_writer.Print(printer);
}
+
printer->Print(
"// @@protoc_insertion_point(imports)\n"
"\n"
@@ -356,8 +429,6 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
"// @@protoc_insertion_point(global_scope)\n");
}
-const string FileGenerator::Path() const { return FilePath(file_); }
-
const vector<FileGenerator *> &FileGenerator::DependencyGenerators() {
if (file_->dependency_count() != dependency_generators_.size()) {
set<string> public_import_names;
@@ -376,6 +447,34 @@ const vector<FileGenerator *> &FileGenerator::DependencyGenerators() {
return dependency_generators_;
}
+void FileGenerator::PrintFilePreamble(
+ io::Printer* printer, const string& header_to_import) const {
+ printer->Print(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
+ "\n",
+ "filename", file_->name());
+
+ const string framework_name(ProtobufLibraryFrameworkName);
+ const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));
+ printer->Print(
+ "// This CPP symbol can be defined to use imports that match up to the framework\n"
+ "// imports needed when using CocoaPods.\n"
+ "#if !defined($cpp_symbol$)\n"
+ " #define $cpp_symbol$ 0\n"
+ "#endif\n"
+ "\n"
+ "#if $cpp_symbol$\n"
+ " #import <$framework_name$/$header$>\n"
+ "#else\n"
+ " #import \"$header$\"\n"
+ "#endif\n"
+ "\n",
+ "cpp_symbol", cpp_symbol,
+ "header", header_to_import,
+ "framework_name", framework_name);
+}
+
} // namespace objectivec
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h
index 4c0fcd3f..7326c901 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h
@@ -62,7 +62,8 @@ class FileGenerator {
void GenerateHeader(io::Printer* printer);
const string& RootClassName() const { return root_class_name_; }
- const string Path() const;
+ const string Path() const { return FilePath(file_); }
+ const FileDescriptor* Descriptor() const { return file_; }
bool IsPublicDependency() const { return is_public_dep_; }
@@ -87,6 +88,8 @@ class FileGenerator {
const Options options_;
const vector<FileGenerator*>& DependencyGenerators();
+ void PrintFilePreamble(
+ io::Printer* printer, const string& header_to_import) const;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
};
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
index 196b39dd..65bf8348 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -293,13 +293,6 @@ string BaseFileName(const FileDescriptor* file) {
return basename;
}
-string FileName(const FileDescriptor* file) {
- string path = FilePath(file);
- string basename;
- PathSplit(path, NULL, &basename);
- return basename;
-}
-
string FilePath(const FileDescriptor* file) {
string output;
string basename;
@@ -317,6 +310,19 @@ string FilePath(const FileDescriptor* file) {
return output;
}
+string FilePathBasename(const FileDescriptor* file) {
+ string output;
+ string basename;
+ string directory;
+ PathSplit(file->name(), &directory, &basename);
+ basename = StripProto(basename);
+
+ // CamelCase to be more ObjC friendly.
+ output = UnderscoresToCamelCase(basename, true);
+
+ return output;
+}
+
string FileClassPrefix(const FileDescriptor* file) {
// Default is empty string, no need to check has_objc_class_prefix.
string result = file->options().objc_class_prefix();
@@ -831,6 +837,40 @@ string BuildCommentsString(const SourceLocation& location) {
return final_comments;
}
+// Making these a generator option for folks that don't use CocoaPods, but do
+// want to put the library in a framework is an interesting question. The
+// problem is it means changing sources shipped with the library to actually
+// use a different value; so it isn't as simple as a option.
+const char* const ProtobufLibraryFrameworkName = "Protobuf";
+
+string ProtobufFrameworkImportSymbol(const string& framework_name) {
+ // GPB_USE_[framework_name]_FRAMEWORK_IMPORTS
+ string result = string("GPB_USE_");
+ result += ToUpper(framework_name);
+ result += "_FRAMEWORK_IMPORTS";
+ return result;
+}
+
+bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file) {
+ // We don't check the name prefix or proto package because some files
+ // (descriptor.proto), aren't shipped generated by the library, so this
+ // seems to be the safest way to only catch the ones shipped.
+ const string name = file->name();
+ if (name == "google/protobuf/any.proto" ||
+ name == "google/protobuf/api.proto" ||
+ name == "google/protobuf/duration.proto" ||
+ name == "google/protobuf/empty.proto" ||
+ name == "google/protobuf/field_mask.proto" ||
+ name == "google/protobuf/source_context.proto" ||
+ name == "google/protobuf/struct.proto" ||
+ name == "google/protobuf/timestamp.proto" ||
+ name == "google/protobuf/type.proto" ||
+ name == "google/protobuf/wrappers.proto") {
+ return true;
+ }
+ return false;
+}
+
namespace {
// Internal helper class that parses the expected package to prefix mappings
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
index 3f56d94b..5898d692 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -62,15 +62,14 @@ bool IsRetainedName(const string& name);
// handling under ARC.
bool IsInitName(const string& name);
-// Gets the name of the file we're going to generate (sans the .pb.h
-// extension). This does not include the path to that file.
-string FileName(const FileDescriptor* file);
-
// Gets the path of the file we're going to generate (sans the .pb.h
// extension). The path will be dependent on the objectivec package
// declared in the proto package.
string FilePath(const FileDescriptor* file);
+// Just like FilePath(), but without the directory part.
+string FilePathBasename(const FileDescriptor* file);
+
// Gets the name of the root class we'll generate in the file. This class
// is not meant for external consumption, but instead contains helpers that
// the rest of the classes need
@@ -169,6 +168,16 @@ string BuildFlagsString(const vector<string>& strings);
// Builds a HeaderDoc style comment out of the comments in the .proto file.
string BuildCommentsString(const SourceLocation& location);
+// The name the commonly used by the library when built as a framework.
+// This lines up to the name used in the CocoaPod.
+extern const char* const ProtobufLibraryFrameworkName;
+// Returns the CPP symbol name to use as the gate for framework style imports
+// for the given framework name to use.
+string ProtobufFrameworkImportSymbol(const string& framework_name);
+
+// Checks if the file is one of the proto's bundled with the library.
+bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file);
+
// Checks the prefix for a given file and outputs any warnings needed, if
// there are flat out errors, then out_error is filled in and the result is
// false.