From d3efd0a1ecce86405ac5eee2121fdb767e65fdb4 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 7 Apr 2015 11:40:29 -0700 Subject: [PATCH 1/2] Created Objective C stub code generators --- src/compiler/generator_helpers.h | 21 ++ src/compiler/objective_c_generator.cc | 234 +++++++++++++++++++ src/compiler/objective_c_generator.h | 48 ++++ src/compiler/objective_c_generator_helpers.h | 58 +++++ src/compiler/objective_c_plugin.cc | 95 ++++++++ 5 files changed, 456 insertions(+) create mode 100644 src/compiler/objective_c_generator.cc create mode 100644 src/compiler/objective_c_generator.h create mode 100644 src/compiler/objective_c_generator_helpers.h create mode 100644 src/compiler/objective_c_plugin.cc diff --git a/src/compiler/generator_helpers.h b/src/compiler/generator_helpers.h index 30857891c77..2a3366ac659 100644 --- a/src/compiler/generator_helpers.h +++ b/src/compiler/generator_helpers.h @@ -95,6 +95,27 @@ inline std::vector tokenize(const grpc::string &input, } } +inline grpc::string CapitalizeFirstLetter(grpc::string str) { + if (s.empty()) { + return s; + } + s[0] = ::toupper(s[0]); + return s; +} + +inline grpc::string LowerUnderscoreToUpperCamel(grpc::string str) { + std::vector tokens = tokenize(str, "_"); + grpc::string result = ""; + for (unsigned int i = 0; i < tokens.size(); i++) { + result += CapitalizeFirstLetter(tokens[i]); + } + return result; +} + +inline grpc::string FileNameInUpperCamel(const grpc::protobuf::FileDescriptor *file) { + return LowerUnderscoreToUpperCamel(StripProto(file->name())); +} + } // namespace grpc_generator #endif // GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc new file mode 100644 index 00000000000..41ffabe8987 --- /dev/null +++ b/src/compiler/objective_c_generator.cc @@ -0,0 +1,234 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include "src/compiler/objective_c_generator.h" +#include "src/compiler/objective_c_generator_helpers.h" + +#include "src/compiler/config.h" + +#include + +namespace grpc_objective_c_generator { +namespace { + +void PrintSimpleBlockSignature(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + (*vars)["method_name"] = method->name(); + (*vars)["request_type"] = PrefixedName(method->input_type()); + (*vars)["response_type"] = PrefixedName(method->output_type()); + + if (method->server_streaming()) { + printer->Print("// When the response stream finishes, the handler is " + "called with nil for both arguments.\n\n"); + } else { + printer->Print("// The handler is only called once.\n\n"); + } + printer->Print(vars, "- (id)$method_name$WithRequest:" + "($request_type$)request completionHandler:(void(^)" + "($response_type$ *, NSError *))handler"); +} + +void PrintSimpleDelegateSignature(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + (*vars)["method_name"] = method->name(); + (*vars)["request_type"] = PrefixedName(method->input_type()); + + printer->Print(vars, "- (id)$method_name$WithRequest:" + "($request_type$)request delegate:(id)delegate"); +} + +void PrintAdvancedSignature(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + (*vars)["method_name"] = method->name(); + printer->Print(vars, "- (GRXSource *)$method_name$WithRequest:" + "(id)request"); +} + +grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service + const grpc::string message_header) { + grpc::string output; + grpc::protobuf::io::StringOutputStream output_stream(&output); + grpc::protobuf::io::Printer printer(&output_stream, '$'); + std::map vars; + printer.Print("#import \"PBgRPCClient.h\"\n"); + printer.Print("#import \"PBStub.h\"\n"); + vars["message_header"] = message_header; + printer.Print(&vars, "#import \"$message_header$\"\n\n"); + printer.Print("@protocol GRXSource\n"); + printer.Print("@class GRXSource\n\n"); + vars["service_name"] = service->name(); + printer.Print("@protocol $service_name$Stub \n\n"); + printer.Print("#pragma mark Simple block handlers\n\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintSimpleBlockSignature(&printer, service->method(i), &vars); + printer.Print(";\n"); + } + printer.Print("\n"); + printer.Print("#pragma mark Simple delegate handlers.\n\n"); + printer.Print("# TODO(jcanizales): Use high-level snippets to remove this duplication."); + for (int i = 0; i < service->method_count(); i++) { + PrintSimpleDelegateSignature(&printer, service->method(i), &vars); + printer.Print(";\n"); + } + printer.Print("\n"); + printer.Print("#pragma mark Advanced handlers.\n\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintAdvancedSignature(&printer, service->method(i), &vars); + printer.Print(";\n"); + } + printer.Print("\n"); + printer.Print("@end\n\n"); + printer.Print("// Basic stub that only does marshalling and parsing\n"); + printer.Print(&vars, "@interface $service_name$Stub :" + " PBStub<$service_name$Stub>\n"); + printer.Print("- (instancetype)initWithHost:(NSString *)host;\n"); + printer.Print("@end\n"); + return output; +} + +void PrintSourceMethodSimpleBlock(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + PrintSimpleBlockSignature(printer, method, vars); + + (*vars)["method_name"] = method->name(); + printer->Print(" {\n"); + printer->Indent(); + printer->Print(vars, "return [[self $method_name$WithRequest:request] " + "connectHandler:^(id value, NSError *error) {\n"); + printer->Indent(); + printer->Print("handler(value, error);\n"); + printer->Outdent(); + printer->Print("}];\n"); + printer->Outdent(); + printer->Print("}\n"); +} + +void PrintSourceMethodSimpleDelegate(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + PrintSimpleDelegateSignature(printer, method, vars); + + (*vars)["method_name"] = method->name(); + printer->Print(" {\n"); + printer->Indent(); + printer->Print(vars, "return [[self $method_name$WithRequest:request]" + "connectToSink:delegate];\n"); + printer->Outdent(); + printer->Print("}\n"); +} + +void PrintSourceMethodAdvanced(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + PrintAdvancedSignature(printer, method, vars); + + (*vars)["method_name"] = method->name(); + printer->Print(" {\n"); + printer->Indent(); + printer->Print(vars, "return [self $method_name$WithRequest:request " + "client:[self newClient]];\n"); + printer->Outdent(); + printer->Print("}\n"); +} + +void PrintSourceMethodHandler(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + (*vars)["method_name"] = method->name(); + (*vars)["response_type"] = PrefixedName(method->output_type()); + (*vars)["caps_name"] = grpc_generator::CapitalizeFirstLetter(method->name()); + + printer->Print(vars, "- (GRXSource *)$method_name$WithRequest:" + "(id)request client:(PBgRPCClient *)client {\n"); + printer->Indent(); + printer->Print(vars, + "return [self responseWithMethod:$@\"$caps_name\"\n"); + printer->Print(vars, + " class:[$response_type$ class]\n"); + printer->Print(" request:request\n"); + printer->Print(" client:client];\n"); + printer->Outdent(); + printer->Print("}\n"); +} + +grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service) { + grpc::string output; + grpc::protobuf::io::StringOutputStream output_stream(&output); + grpc::protobuf::io::Printer printer(&output_stream, '$'); + std::map vars; + vars["service_name"] = service->name(); + printer.Print(&vars, "#import \"$service_name$Stub.pb.h\"\n"); + printer.Print("#import \"PBGeneratedMessage+GRXSource.h\"\n\n"); + vars["full_name"] = service->full_name(); + printer.Print(&vars, + "static NSString *const kInterface = @\"$full_name$\";\n"); + printer.Print("@implementation $service_name$Stub\n\n"); + printer.Print("- (instancetype)initWithHost:(NSString *)host {\n"); + printer.Indent(); + printer.Print("if ((self = [super initWithHost:host " + "interface:kInterface])) {\n"); + printer.Print("}\n"); + printer.Print("return self;\n"); + printer.Outdent(); + printer.Print("}\n\n"); + printer.Print("#pragma mark Simple block handlers.\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintSourceMethodSimpleBlock(&printer, service->method(i), &vars); + } + printer.Print("\n"); + printer.Print("#pragma mark Simple delegate handlers.\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintSourceMethodSimpleDelegate(&printer, service->method(i), &vars); + } + printer.Print("\n"); + printer.Print("#pragma mark Advanced handlers.\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintSourceMethodAdvanced(&printer, service->method(i), &vars); + } + printer.Print("\n"); + printer.Print("#pragma mark Handlers for subclasses " + "(stub wrappers) to override.\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintSourceMethodHandler(&printer, service->method(i), &vars); + } + printer.Print("@end\n"); + return output; +} + +} // namespace grpc_objective_c_generator diff --git a/src/compiler/objective_c_generator.h b/src/compiler/objective_c_generator.h new file mode 100644 index 00000000000..bea63f51e5c --- /dev/null +++ b/src/compiler/objective_c_generator.h @@ -0,0 +1,48 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H +#define GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H + +#include "src/compiler/config.h" + +namespace grpc_objective_c_generator { + +grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service + const grpc::string message_header); + +grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service); + +} // namespace grpc_objective_c_generator + +#endif // GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H diff --git a/src/compiler/objective_c_generator_helpers.h b/src/compiler/objective_c_generator_helpers.h new file mode 100644 index 00000000000..0c2ece823cf --- /dev/null +++ b/src/compiler/objective_c_generator_helpers.h @@ -0,0 +1,58 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H +#define GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H + +#include +#include "src/compiler/config.h" +#include "src/compiler/generator_helpers.h" + +namespace grpc_objective_c_generator { + +const grpc::string prefix = "PBG"; + +inline grpc::string MessageHeaderName(const grpc::protobuf::FileDescriptor *file) { + return FileNameInUpperCase(file) + ".pb.h"; +} + +inline grpc::string StubFileName(grpc::string service_name) { + return prefix + service_name + "Stub"; +} + +inline grpc::string PrefixedName(grpc::string name) { + return prefix + name; +} + +} +#endif // GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H diff --git a/src/compiler/objective_c_plugin.cc b/src/compiler/objective_c_plugin.cc new file mode 100644 index 00000000000..4d4146b5c40 --- /dev/null +++ b/src/compiler/objective_c_plugin.cc @@ -0,0 +1,95 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Generates Objective C gRPC service interface out of Protobuf IDL. + +#include + +#include "src/compiler/config.h" +#include "src/compiler/objective_c_generator.h" +#include "src/compiler/objective_c_generator_helpers.h" + +class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { + public: + ObjectiveCGrpcGenerator() {} + virtual ~ObjectiveCGrpcGenerator() {} + + virtual bool Generate(const grpc::protobuf::FileDescriptor *file, + const grpc::string ¶meter, + grpc::protobuf::compiler::GeneratorContext *context, + grpc::string *error) const { + + if (file->service_count() == 0) { + // No services. Do nothing. + return true; + } + + for (int i = 0; i < file->service_count(); i++) { + const grpc::protobuf::ServiceDescriptor *service = file->service(i); + grpc::sring file_name = grpc_objective_c_generator::StubFileName( + service->name()); + + // Generate .pb.h + grpc::string header_code = grpc_objective_c_generator::GetHeader(service); + std::unique_ptr header_output( + context->Open(file_name + ".pb.h")); + grpc::protobuf::io::CodedOutputStream header_coded_out(output.get()); + header_coded_out.WriteRaw(header_code.data(), header_code.size()); + + // Generate .pb.m + grpc::string source_code = grpc_objective_c_generator::GetSource(service); + std::unique_ptr source_output( + context->Open(file_name + ".pb.m")); + grpc::protobuf::io::CodedOutputStream source_coded_out(output.get()); + source_coded_out.WriteRaw(source_code.data(), source_code.size()); + } + + return true; + } + + private: + // Insert the given code into the given file at the given insertion point. + void Insert(grpc::protobuf::compiler::GeneratorContext *context, + const grpc::string &filename, const grpc::string &insertion_point, + const grpc::string &code) const { + std::unique_ptr output( + context->OpenForInsert(filename, insertion_point)); + grpc::protobuf::io::CodedOutputStream coded_out(output.get()); + coded_out.WriteRaw(code.data(), code.size()); + } +}; + +int main(int argc, char *argv[]) { + ObjectiveCGrpcGenerator generator; + return grpc::protobuf::compiler::PluginMain(argc, argv, &generator); +} From ac0002adb8c8baa9382576c8075fda6b7cd02dab Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 7 Apr 2015 12:49:14 -0700 Subject: [PATCH 2/2] Made Objective C plugin build without error --- Makefile | 37 +++++- build.json | 15 +++ src/compiler/generator_helpers.h | 2 +- src/compiler/objective_c_generator.cc | 116 ++++++++++--------- src/compiler/objective_c_generator.h | 2 +- src/compiler/objective_c_generator_helpers.h | 2 +- src/compiler/objective_c_plugin.cc | 11 +- 7 files changed, 120 insertions(+), 65 deletions(-) diff --git a/Makefile b/Makefile index 4e99231a1c9..22235b7ded3 100644 --- a/Makefile +++ b/Makefile @@ -456,7 +456,7 @@ endif .SECONDARY = %.pb.h %.pb.cc -PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin +PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin ifeq ($(DEP_MISSING),) all: static shared plugins dep_error: @@ -632,6 +632,7 @@ end2end_test: $(BINDIR)/$(CONFIG)/end2end_test generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin +grpc_objective_c_plugin: $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin interop_client: $(BINDIR)/$(CONFIG)/interop_client @@ -2266,6 +2267,8 @@ else $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(prefix)/bin/grpc_cpp_plugin $(Q) $(INSTALL) -d $(prefix)/bin + $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(prefix)/bin/grpc_objective_c_plugin + $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_python_plugin $(prefix)/bin/grpc_python_plugin $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_ruby_plugin $(prefix)/bin/grpc_ruby_plugin @@ -3615,6 +3618,7 @@ $(OBJDIR)/$(CONFIG)/src/cpp/util/time.o: LIBGRPC_PLUGIN_SUPPORT_SRC = \ src/compiler/cpp_generator.cc \ + src/compiler/objective_c_generator.cc \ src/compiler/python_generator.cc \ src/compiler/ruby_generator.cc \ @@ -3649,6 +3653,7 @@ ifneq ($(NO_DEPS),true) endif $(OBJDIR)/$(CONFIG)/src/compiler/cpp_generator.o: +$(OBJDIR)/$(CONFIG)/src/compiler/objective_c_generator.o: $(OBJDIR)/$(CONFIG)/src/compiler/python_generator.o: $(OBJDIR)/$(CONFIG)/src/compiler/ruby_generator.o: @@ -8331,6 +8336,36 @@ ifneq ($(NO_DEPS),true) endif +GRPC_OBJECTIVE_C_PLUGIN_SRC = \ + src/compiler/objective_c_plugin.cc \ + +GRPC_OBJECTIVE_C_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_OBJECTIVE_C_PLUGIN_SRC)))) + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/grpc_objective_c_plugin: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/grpc_objective_c_plugin: $(PROTOBUF_DEP) $(GRPC_OBJECTIVE_C_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a + $(E) "[HOSTLD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_OBJECTIVE_C_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin + +endif + +$(OBJDIR)/$(CONFIG)/src/compiler/objective_c_plugin.o: $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a + +deps_grpc_objective_c_plugin: $(GRPC_OBJECTIVE_C_PLUGIN_OBJS:.o=.dep) + +ifneq ($(NO_DEPS),true) +-include $(GRPC_OBJECTIVE_C_PLUGIN_OBJS:.o=.dep) +endif + + GRPC_PYTHON_PLUGIN_SRC = \ src/compiler/python_plugin.cc \ diff --git a/build.json b/build.json index 06adfee9f7b..890a5385a9e 100644 --- a/build.json +++ b/build.json @@ -514,6 +514,8 @@ "src/compiler/cpp_generator.h", "src/compiler/cpp_generator_helpers.h", "src/compiler/generator_helpers.h", + "src/compiler/objective_c_generator.h", + "src/compiler/objective_c_generator_helpers.h", "src/compiler/python_generator.h", "src/compiler/ruby_generator.h", "src/compiler/ruby_generator_helpers-inl.h", @@ -522,6 +524,7 @@ ], "src": [ "src/compiler/cpp_generator.cc", + "src/compiler/objective_c_generator.cc", "src/compiler/python_generator.cc", "src/compiler/ruby_generator.cc" ], @@ -1817,6 +1820,18 @@ ], "secure": "no" }, + { + "name": "grpc_objective_c_plugin", + "build": "protoc", + "language": "c++", + "src": [ + "src/compiler/objective_c_plugin.cc" + ], + "deps": [ + "grpc_plugin_support" + ], + "secure": "no" + }, { "name": "grpc_python_plugin", "build": "protoc", diff --git a/src/compiler/generator_helpers.h b/src/compiler/generator_helpers.h index 2a3366ac659..374e1374cf4 100644 --- a/src/compiler/generator_helpers.h +++ b/src/compiler/generator_helpers.h @@ -95,7 +95,7 @@ inline std::vector tokenize(const grpc::string &input, } } -inline grpc::string CapitalizeFirstLetter(grpc::string str) { +inline grpc::string CapitalizeFirstLetter(grpc::string s) { if (s.empty()) { return s; } diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc index 41ffabe8987..c68c9c37c21 100644 --- a/src/compiler/objective_c_generator.cc +++ b/src/compiler/objective_c_generator.cc @@ -47,8 +47,8 @@ void PrintSimpleBlockSignature(grpc::protobuf::io::Printer *printer, const grpc::protobuf::MethodDescriptor *method, std::map *vars) { (*vars)["method_name"] = method->name(); - (*vars)["request_type"] = PrefixedName(method->input_type()); - (*vars)["response_type"] = PrefixedName(method->output_type()); + (*vars)["request_type"] = PrefixedName(method->input_type()->name()); + (*vars)["response_type"] = PrefixedName(method->output_type()->name()); if (method->server_streaming()) { printer->Print("// When the response stream finishes, the handler is " @@ -56,7 +56,7 @@ void PrintSimpleBlockSignature(grpc::protobuf::io::Printer *printer, } else { printer->Print("// The handler is only called once.\n\n"); } - printer->Print(vars, "- (id)$method_name$WithRequest:" + printer->Print(*vars, "- (id)$method_name$WithRequest:" "($request_type$)request completionHandler:(void(^)" "($response_type$ *, NSError *))handler"); } @@ -65,9 +65,9 @@ void PrintSimpleDelegateSignature(grpc::protobuf::io::Printer *printer, const grpc::protobuf::MethodDescriptor *method, std::map *vars) { (*vars)["method_name"] = method->name(); - (*vars)["request_type"] = PrefixedName(method->input_type()); + (*vars)["request_type"] = PrefixedName(method->input_type()->name()); - printer->Print(vars, "- (id)$method_name$WithRequest:" + printer->Print(*vars, "- (id)$method_name$WithRequest:" "($request_type$)request delegate:(id)delegate"); } @@ -75,52 +75,10 @@ void PrintAdvancedSignature(grpc::protobuf::io::Printer *printer, const grpc::protobuf::MethodDescriptor *method, std::map *vars) { (*vars)["method_name"] = method->name(); - printer->Print(vars, "- (GRXSource *)$method_name$WithRequest:" + printer->Print(*vars, "- (GRXSource *)$method_name$WithRequest:" "(id)request"); } -grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service - const grpc::string message_header) { - grpc::string output; - grpc::protobuf::io::StringOutputStream output_stream(&output); - grpc::protobuf::io::Printer printer(&output_stream, '$'); - std::map vars; - printer.Print("#import \"PBgRPCClient.h\"\n"); - printer.Print("#import \"PBStub.h\"\n"); - vars["message_header"] = message_header; - printer.Print(&vars, "#import \"$message_header$\"\n\n"); - printer.Print("@protocol GRXSource\n"); - printer.Print("@class GRXSource\n\n"); - vars["service_name"] = service->name(); - printer.Print("@protocol $service_name$Stub \n\n"); - printer.Print("#pragma mark Simple block handlers\n\n"); - for (int i = 0; i < service->method_count(); i++) { - PrintSimpleBlockSignature(&printer, service->method(i), &vars); - printer.Print(";\n"); - } - printer.Print("\n"); - printer.Print("#pragma mark Simple delegate handlers.\n\n"); - printer.Print("# TODO(jcanizales): Use high-level snippets to remove this duplication."); - for (int i = 0; i < service->method_count(); i++) { - PrintSimpleDelegateSignature(&printer, service->method(i), &vars); - printer.Print(";\n"); - } - printer.Print("\n"); - printer.Print("#pragma mark Advanced handlers.\n\n"); - for (int i = 0; i < service->method_count(); i++) { - PrintAdvancedSignature(&printer, service->method(i), &vars); - printer.Print(";\n"); - } - printer.Print("\n"); - printer.Print("@end\n\n"); - printer.Print("// Basic stub that only does marshalling and parsing\n"); - printer.Print(&vars, "@interface $service_name$Stub :" - " PBStub<$service_name$Stub>\n"); - printer.Print("- (instancetype)initWithHost:(NSString *)host;\n"); - printer.Print("@end\n"); - return output; -} - void PrintSourceMethodSimpleBlock(grpc::protobuf::io::Printer *printer, const grpc::protobuf::MethodDescriptor *method, std::map *vars) { @@ -129,7 +87,7 @@ void PrintSourceMethodSimpleBlock(grpc::protobuf::io::Printer *printer, (*vars)["method_name"] = method->name(); printer->Print(" {\n"); printer->Indent(); - printer->Print(vars, "return [[self $method_name$WithRequest:request] " + printer->Print(*vars, "return [[self $method_name$WithRequest:request] " "connectHandler:^(id value, NSError *error) {\n"); printer->Indent(); printer->Print("handler(value, error);\n"); @@ -147,7 +105,7 @@ void PrintSourceMethodSimpleDelegate(grpc::protobuf::io::Printer *printer, (*vars)["method_name"] = method->name(); printer->Print(" {\n"); printer->Indent(); - printer->Print(vars, "return [[self $method_name$WithRequest:request]" + printer->Print(*vars, "return [[self $method_name$WithRequest:request]" "connectToSink:delegate];\n"); printer->Outdent(); printer->Print("}\n"); @@ -161,7 +119,7 @@ void PrintSourceMethodAdvanced(grpc::protobuf::io::Printer *printer, (*vars)["method_name"] = method->name(); printer->Print(" {\n"); printer->Indent(); - printer->Print(vars, "return [self $method_name$WithRequest:request " + printer->Print(*vars, "return [self $method_name$WithRequest:request " "client:[self newClient]];\n"); printer->Outdent(); printer->Print("}\n"); @@ -171,15 +129,15 @@ void PrintSourceMethodHandler(grpc::protobuf::io::Printer *printer, const grpc::protobuf::MethodDescriptor *method, std::map *vars) { (*vars)["method_name"] = method->name(); - (*vars)["response_type"] = PrefixedName(method->output_type()); + (*vars)["response_type"] = PrefixedName(method->output_type()->name()); (*vars)["caps_name"] = grpc_generator::CapitalizeFirstLetter(method->name()); - printer->Print(vars, "- (GRXSource *)$method_name$WithRequest:" + printer->Print(*vars, "- (GRXSource *)$method_name$WithRequest:" "(id)request client:(PBgRPCClient *)client {\n"); printer->Indent(); - printer->Print(vars, + printer->Print(*vars, "return [self responseWithMethod:$@\"$caps_name\"\n"); - printer->Print(vars, + printer->Print(*vars, " class:[$response_type$ class]\n"); printer->Print(" request:request\n"); printer->Print(" client:client];\n"); @@ -187,16 +145,60 @@ void PrintSourceMethodHandler(grpc::protobuf::io::Printer *printer, printer->Print("}\n"); } +} + +grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service, + const grpc::string message_header) { + grpc::string output; + grpc::protobuf::io::StringOutputStream output_stream(&output); + grpc::protobuf::io::Printer printer(&output_stream, '$'); + std::map vars; + printer.Print("#import \"PBgRPCClient.h\"\n"); + printer.Print("#import \"PBStub.h\"\n"); + vars["message_header"] = message_header; + printer.Print(vars, "#import \"$message_header$\"\n\n"); + printer.Print("@protocol GRXSource\n"); + printer.Print("@class GRXSource\n\n"); + vars["service_name"] = service->name(); + printer.Print("@protocol $service_name$Stub \n\n"); + printer.Print("#pragma mark Simple block handlers\n\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintSimpleBlockSignature(&printer, service->method(i), &vars); + printer.Print(";\n"); + } + printer.Print("\n"); + printer.Print("#pragma mark Simple delegate handlers.\n\n"); + printer.Print("# TODO(jcanizales): Use high-level snippets to remove this duplication."); + for (int i = 0; i < service->method_count(); i++) { + PrintSimpleDelegateSignature(&printer, service->method(i), &vars); + printer.Print(";\n"); + } + printer.Print("\n"); + printer.Print("#pragma mark Advanced handlers.\n\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintAdvancedSignature(&printer, service->method(i), &vars); + printer.Print(";\n"); + } + printer.Print("\n"); + printer.Print("@end\n\n"); + printer.Print("// Basic stub that only does marshalling and parsing\n"); + printer.Print(vars, "@interface $service_name$Stub :" + " PBStub<$service_name$Stub>\n"); + printer.Print("- (instancetype)initWithHost:(NSString *)host;\n"); + printer.Print("@end\n"); + return output; +} + grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service) { grpc::string output; grpc::protobuf::io::StringOutputStream output_stream(&output); grpc::protobuf::io::Printer printer(&output_stream, '$'); std::map vars; vars["service_name"] = service->name(); - printer.Print(&vars, "#import \"$service_name$Stub.pb.h\"\n"); + printer.Print(vars, "#import \"$service_name$Stub.pb.h\"\n"); printer.Print("#import \"PBGeneratedMessage+GRXSource.h\"\n\n"); vars["full_name"] = service->full_name(); - printer.Print(&vars, + printer.Print(vars, "static NSString *const kInterface = @\"$full_name$\";\n"); printer.Print("@implementation $service_name$Stub\n\n"); printer.Print("- (instancetype)initWithHost:(NSString *)host {\n"); diff --git a/src/compiler/objective_c_generator.h b/src/compiler/objective_c_generator.h index bea63f51e5c..93c730b34e4 100644 --- a/src/compiler/objective_c_generator.h +++ b/src/compiler/objective_c_generator.h @@ -38,7 +38,7 @@ namespace grpc_objective_c_generator { -grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service +grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service, const grpc::string message_header); grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service); diff --git a/src/compiler/objective_c_generator_helpers.h b/src/compiler/objective_c_generator_helpers.h index 0c2ece823cf..6a7c13991fd 100644 --- a/src/compiler/objective_c_generator_helpers.h +++ b/src/compiler/objective_c_generator_helpers.h @@ -43,7 +43,7 @@ namespace grpc_objective_c_generator { const grpc::string prefix = "PBG"; inline grpc::string MessageHeaderName(const grpc::protobuf::FileDescriptor *file) { - return FileNameInUpperCase(file) + ".pb.h"; + return grpc_generator::FileNameInUpperCamel(file) + ".pb.h"; } inline grpc::string StubFileName(grpc::string service_name) { diff --git a/src/compiler/objective_c_plugin.cc b/src/compiler/objective_c_plugin.cc index 4d4146b5c40..eebce0cd20d 100644 --- a/src/compiler/objective_c_plugin.cc +++ b/src/compiler/objective_c_plugin.cc @@ -56,21 +56,24 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { for (int i = 0; i < file->service_count(); i++) { const grpc::protobuf::ServiceDescriptor *service = file->service(i); - grpc::sring file_name = grpc_objective_c_generator::StubFileName( + grpc::string file_name = grpc_objective_c_generator::StubFileName( service->name()); // Generate .pb.h - grpc::string header_code = grpc_objective_c_generator::GetHeader(service); + grpc::string header_code = grpc_objective_c_generator::GetHeader( + service, grpc_objective_c_generator::MessageHeaderName(file)); std::unique_ptr header_output( context->Open(file_name + ".pb.h")); - grpc::protobuf::io::CodedOutputStream header_coded_out(output.get()); + grpc::protobuf::io::CodedOutputStream header_coded_out( + header_output.get()); header_coded_out.WriteRaw(header_code.data(), header_code.size()); // Generate .pb.m grpc::string source_code = grpc_objective_c_generator::GetSource(service); std::unique_ptr source_output( context->Open(file_name + ".pb.m")); - grpc::protobuf::io::CodedOutputStream source_coded_out(output.get()); + grpc::protobuf::io::CodedOutputStream source_coded_out( + source_output.get()); source_coded_out.WriteRaw(source_code.data(), source_code.size()); }