diff options
-rw-r--r-- | BUILD | 15 | ||||
-rw-r--r-- | Makefile | 37 | ||||
-rw-r--r-- | build.yaml | 12 | ||||
-rw-r--r-- | examples/node/greeter_client.js | 22 | ||||
-rw-r--r-- | examples/node/greeter_server.js | 12 | ||||
-rw-r--r-- | examples/node/helloworld_grpc_pb.js | 39 | ||||
-rw-r--r-- | examples/node/helloworld_pb.js | 332 | ||||
-rw-r--r-- | examples/node/package.json | 1 | ||||
-rw-r--r-- | src/compiler/generator_helpers.h | 10 | ||||
-rw-r--r-- | src/compiler/node_generator.cc | 275 | ||||
-rw-r--r-- | src/compiler/node_generator.h | 49 | ||||
-rw-r--r-- | src/compiler/node_generator_helpers.h | 50 | ||||
-rw-r--r-- | src/compiler/node_plugin.cc | 77 | ||||
-rw-r--r-- | tools/run_tests/sources_and_headers.json | 18 | ||||
-rw-r--r-- | vsprojects/grpc_protoc_plugins.sln | 16 | ||||
-rw-r--r-- | vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj | 168 | ||||
-rw-r--r-- | vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj.filters | 18 | ||||
-rw-r--r-- | vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj | 4 | ||||
-rw-r--r-- | vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj.filters | 9 |
19 files changed, 1151 insertions, 13 deletions
@@ -1135,6 +1135,8 @@ cc_library( "src/compiler/csharp_generator.h", "src/compiler/csharp_generator_helpers.h", "src/compiler/generator_helpers.h", + "src/compiler/node_generator.h", + "src/compiler/node_generator_helpers.h", "src/compiler/objective_c_generator.h", "src/compiler/objective_c_generator_helpers.h", "src/compiler/python_generator.h", @@ -1144,6 +1146,7 @@ cc_library( "src/compiler/ruby_generator_string-inl.h", "src/compiler/cpp_generator.cc", "src/compiler/csharp_generator.cc", + "src/compiler/node_generator.cc", "src/compiler/objective_c_generator.cc", "src/compiler/python_generator.cc", "src/compiler/ruby_generator.cc", @@ -1665,6 +1668,18 @@ cc_binary( cc_binary( + name = "grpc_node_plugin", + srcs = [ + "src/compiler/node_plugin.cc", + ], + deps = [ + "//external:protobuf_compiler", + ":grpc_plugin_support", + ], +) + + +cc_binary( name = "grpc_objective_c_plugin", srcs = [ "src/compiler/objective_c_plugin.cc", @@ -779,7 +779,7 @@ endif .SECONDARY = %.pb.h %.pb.cc -PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin +PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(BINDIR)/$(CONFIG)/grpc_node_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: @@ -1012,6 +1012,7 @@ generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin grpc_csharp_plugin: $(BINDIR)/$(CONFIG)/grpc_csharp_plugin +grpc_node_plugin: $(BINDIR)/$(CONFIG)/grpc_node_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 @@ -2239,6 +2240,8 @@ else $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(prefix)/bin/grpc_csharp_plugin $(Q) $(INSTALL) -d $(prefix)/bin + $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_node_plugin $(prefix)/bin/grpc_node_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 @@ -3624,6 +3627,7 @@ endif LIBGRPC_PLUGIN_SUPPORT_SRC = \ src/compiler/cpp_generator.cc \ src/compiler/csharp_generator.cc \ + src/compiler/node_generator.cc \ src/compiler/objective_c_generator.cc \ src/compiler/python_generator.cc \ src/compiler/ruby_generator.cc \ @@ -10485,6 +10489,37 @@ ifneq ($(NO_DEPS),true) endif +GRPC_NODE_PLUGIN_SRC = \ + src/compiler/node_plugin.cc \ + +GRPC_NODE_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_NODE_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_node_plugin: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/grpc_node_plugin: $(PROTOBUF_DEP) $(GRPC_NODE_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a + $(E) "[HOSTLD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_NODE_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_node_plugin + +endif + +$(OBJDIR)/$(CONFIG)/src/compiler/node_plugin.o: $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a + +deps_grpc_node_plugin: $(GRPC_NODE_PLUGIN_OBJS:.o=.dep) + +ifneq ($(NO_DEPS),true) +-include $(GRPC_NODE_PLUGIN_OBJS:.o=.dep) +endif + + GRPC_OBJECTIVE_C_PLUGIN_SRC = \ src/compiler/objective_c_plugin.cc \ diff --git a/build.yaml b/build.yaml index a9a9e6ac9f..a25e2e8cd9 100644 --- a/build.yaml +++ b/build.yaml @@ -927,6 +927,8 @@ libs: - src/compiler/csharp_generator.h - src/compiler/csharp_generator_helpers.h - src/compiler/generator_helpers.h + - src/compiler/node_generator.h + - src/compiler/node_generator_helpers.h - src/compiler/objective_c_generator.h - src/compiler/objective_c_generator_helpers.h - src/compiler/python_generator.h @@ -937,6 +939,7 @@ libs: src: - src/compiler/cpp_generator.cc - src/compiler/csharp_generator.cc + - src/compiler/node_generator.cc - src/compiler/objective_c_generator.cc - src/compiler/python_generator.cc - src/compiler/ruby_generator.cc @@ -2557,6 +2560,15 @@ targets: secure: false vs_config_type: Application vs_project_guid: '{3C813052-A49A-4662-B90A-1ADBEC7EE453}' +- name: grpc_node_plugin + build: protoc + language: c++ + src: + - src/compiler/node_plugin.cc + deps: + - grpc_plugin_support + secure: false + vs_config_type: Application - name: grpc_objective_c_plugin build: protoc language: c++ diff --git a/examples/node/greeter_client.js b/examples/node/greeter_client.js index 2820acbbb7..7125c2fec5 100644 --- a/examples/node/greeter_client.js +++ b/examples/node/greeter_client.js @@ -31,22 +31,30 @@ * */ -var PROTO_PATH = __dirname + '/../protos/helloworld.proto'; - var grpc = require('grpc'); -var hello_proto = grpc.load(PROTO_PATH).helloworld; + +var hello_messages = require('./helloworld_pb'); +var hello_service = require('./helloworld_grpc_pb'); function main() { - var client = new hello_proto.Greeter('localhost:50051', - grpc.credentials.createInsecure()); + var client = new hello_service.GreeterClient('localhost:50051', + grpc.credentials.createInsecure()); var user; if (process.argv.length >= 3) { user = process.argv[2]; } else { user = 'world'; } - client.sayHello({name: user}, function(err, response) { - console.log('Greeting:', response.message); + + var request = new hello_messages.HelloRequest(); + request.setName(user); + + client.sayHello(request, function(err, response) { + if (err) { + debugger; + throw err; + } + console.log('Greeting:', response.getMessage()); }); } diff --git a/examples/node/greeter_server.js b/examples/node/greeter_server.js index e7ad51f600..a4aebf6d09 100644 --- a/examples/node/greeter_server.js +++ b/examples/node/greeter_server.js @@ -31,16 +31,18 @@ * */ -var PROTO_PATH = __dirname + '/../protos/helloworld.proto'; - var grpc = require('grpc'); -var hello_proto = grpc.load(PROTO_PATH).helloworld; + +var hello_messages = require('./helloworld_pb'); +var hello_service = require('./helloworld_grpc_pb'); /** * Implements the SayHello RPC method. */ function sayHello(call, callback) { - callback(null, {message: 'Hello ' + call.request.name}); + var reply = new hello_messages.HelloReply(); + reply.setMessage("Hello " + call.request.getName()); + callback(null, reply); } /** @@ -49,7 +51,7 @@ function sayHello(call, callback) { */ function main() { var server = new grpc.Server(); - server.addProtoService(hello_proto.Greeter.service, {sayHello: sayHello}); + server.addService(hello_service.GreeterService, {sayHello: sayHello}); server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure()); server.start(); } diff --git a/examples/node/helloworld_grpc_pb.js b/examples/node/helloworld_grpc_pb.js new file mode 100644 index 0000000000..3d070d7de0 --- /dev/null +++ b/examples/node/helloworld_grpc_pb.js @@ -0,0 +1,39 @@ +// GENERATED CODE -- DO NOT EDIT! + +var grpc = require('grpc'); +var helloworld_pb = require('./helloworld_pb.js'); + +function serialize_HelloReply(arg) { + if (!(arg instanceof helloworld_pb.HelloReply)) { + throw new Error('Expected argument of type HelloReply'); + } + return new Buffer(arg.serializeBinary()); +} +function deserialize_HelloReply(buffer_arg) { + return helloworld_pb.HelloReply.deserializeBinary(new Uint8Array(buffer_arg)); +} +function serialize_HelloRequest(arg) { + if (!(arg instanceof helloworld_pb.HelloRequest)) { + throw new Error('Expected argument of type HelloRequest'); + } + return new Buffer(arg.serializeBinary()); +} +function deserialize_HelloRequest(buffer_arg) { + return helloworld_pb.HelloRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} + +var GreeterService = exports.GreeterService = { + sayHello: { + path: '/helloworld.Greeter/SayHello', + requestStream: false, + responseStream: false, + requestType: helloworld_pb.HelloRequest, + responseType: helloworld_pb.HelloReply, + requestSerialize: serialize_HelloRequest, + requestDeserialize: deserialize_HelloRequest, + responseSerialize: serialize_HelloReply, + responseDeserialize: deserialize_HelloReply, + }, +}; + +exports.GreeterClient = grpc.makeGenericClientConstructor(GreeterService); diff --git a/examples/node/helloworld_pb.js b/examples/node/helloworld_pb.js new file mode 100644 index 0000000000..6405bd90f1 --- /dev/null +++ b/examples/node/helloworld_pb.js @@ -0,0 +1,332 @@ +/** + * @fileoverview + * @enhanceable + * @public + */ +// GENERATED CODE -- DO NOT EDIT! + +var jspb = require('google-protobuf'); +var goog = jspb; +var global = Function('return this')(); + +goog.exportSymbol('proto.helloworld.HelloReply', null, global); +goog.exportSymbol('proto.helloworld.HelloRequest', null, global); + +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.helloworld.HelloRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.helloworld.HelloRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + proto.helloworld.HelloRequest.displayName = 'proto.helloworld.HelloRequest'; +} + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto suitable for use in Soy templates. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. + * For the list of reserved names please see: + * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Object} + */ +proto.helloworld.HelloRequest.prototype.toObject = function(opt_includeInstance) { + return proto.helloworld.HelloRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Whether to include the JSPB + * instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.helloworld.HelloRequest} msg The msg instance to transform. + * @return {!Object} + */ +proto.helloworld.HelloRequest.toObject = function(includeInstance, msg) { + var f, obj = { + name: msg.getName() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.helloworld.HelloRequest} + */ +proto.helloworld.HelloRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.helloworld.HelloRequest; + return proto.helloworld.HelloRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.helloworld.HelloRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.helloworld.HelloRequest} + */ +proto.helloworld.HelloRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setName(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Class method variant: serializes the given message to binary data + * (in protobuf wire format), writing to the given BinaryWriter. + * @param {!proto.helloworld.HelloRequest} message + * @param {!jspb.BinaryWriter} writer + */ +proto.helloworld.HelloRequest.serializeBinaryToWriter = function(message, writer) { + message.serializeBinaryToWriter(writer); +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.helloworld.HelloRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + this.serializeBinaryToWriter(writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the message to binary data (in protobuf wire format), + * writing to the given BinaryWriter. + * @param {!jspb.BinaryWriter} writer + */ +proto.helloworld.HelloRequest.prototype.serializeBinaryToWriter = function (writer) { + var f = undefined; + f = this.getName(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } +}; + + +/** + * Creates a deep clone of this proto. No data is shared with the original. + * @return {!proto.helloworld.HelloRequest} The clone. + */ +proto.helloworld.HelloRequest.prototype.cloneMessage = function() { + return /** @type {!proto.helloworld.HelloRequest} */ (jspb.Message.cloneMessage(this)); +}; + + +/** + * optional string name = 1; + * @return {string} + */ +proto.helloworld.HelloRequest.prototype.getName = function() { + return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, "")); +}; + + +/** @param {string} value */ +proto.helloworld.HelloRequest.prototype.setName = function(value) { + jspb.Message.setField(this, 1, value); +}; + + + +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.helloworld.HelloReply = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.helloworld.HelloReply, jspb.Message); +if (goog.DEBUG && !COMPILED) { + proto.helloworld.HelloReply.displayName = 'proto.helloworld.HelloReply'; +} + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto suitable for use in Soy templates. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. + * For the list of reserved names please see: + * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Object} + */ +proto.helloworld.HelloReply.prototype.toObject = function(opt_includeInstance) { + return proto.helloworld.HelloReply.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Whether to include the JSPB + * instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.helloworld.HelloReply} msg The msg instance to transform. + * @return {!Object} + */ +proto.helloworld.HelloReply.toObject = function(includeInstance, msg) { + var f, obj = { + message: msg.getMessage() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.helloworld.HelloReply} + */ +proto.helloworld.HelloReply.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.helloworld.HelloReply; + return proto.helloworld.HelloReply.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.helloworld.HelloReply} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.helloworld.HelloReply} + */ +proto.helloworld.HelloReply.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setMessage(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Class method variant: serializes the given message to binary data + * (in protobuf wire format), writing to the given BinaryWriter. + * @param {!proto.helloworld.HelloReply} message + * @param {!jspb.BinaryWriter} writer + */ +proto.helloworld.HelloReply.serializeBinaryToWriter = function(message, writer) { + message.serializeBinaryToWriter(writer); +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.helloworld.HelloReply.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + this.serializeBinaryToWriter(writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the message to binary data (in protobuf wire format), + * writing to the given BinaryWriter. + * @param {!jspb.BinaryWriter} writer + */ +proto.helloworld.HelloReply.prototype.serializeBinaryToWriter = function (writer) { + var f = undefined; + f = this.getMessage(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } +}; + + +/** + * Creates a deep clone of this proto. No data is shared with the original. + * @return {!proto.helloworld.HelloReply} The clone. + */ +proto.helloworld.HelloReply.prototype.cloneMessage = function() { + return /** @type {!proto.helloworld.HelloReply} */ (jspb.Message.cloneMessage(this)); +}; + + +/** + * optional string message = 1; + * @return {string} + */ +proto.helloworld.HelloReply.prototype.getMessage = function() { + return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, "")); +}; + + +/** @param {string} value */ +proto.helloworld.HelloReply.prototype.setMessage = function(value) { + jspb.Message.setField(this, 1, value); +}; + + +goog.object.extend(exports, proto.helloworld); diff --git a/examples/node/package.json b/examples/node/package.json index d135df2464..49ab74d318 100644 --- a/examples/node/package.json +++ b/examples/node/package.json @@ -4,6 +4,7 @@ "dependencies": { "async": "^1.5.2", "grpc": "0.13.0", + "google-protobuf": "*", "lodash": "^4.6.1", "minimist": "^1.2.0" } diff --git a/src/compiler/generator_helpers.h b/src/compiler/generator_helpers.h index e1bb66a875..3ed0500efc 100644 --- a/src/compiler/generator_helpers.h +++ b/src/compiler/generator_helpers.h @@ -52,6 +52,16 @@ inline bool StripSuffix(grpc::string *filename, const grpc::string &suffix) { return false; } +inline bool StripPrefix(grpc::string *name, const grpc::string &prefix) { + if (name->length() >= prefix.length()) { + if (name->substr(0, prefix.size()) == prefix) { + *name = name->substr(prefix.size()); + return true; + } + } + return false; +} + inline grpc::string StripProto(grpc::string filename) { if (!StripSuffix(&filename, ".protodevel")) { StripSuffix(&filename, ".proto"); diff --git a/src/compiler/node_generator.cc b/src/compiler/node_generator.cc new file mode 100644 index 0000000000..7605b64531 --- /dev/null +++ b/src/compiler/node_generator.cc @@ -0,0 +1,275 @@ +/* + * + * Copyright 2016, 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 <map> + +#include "src/compiler/config.h" +#include "src/compiler/generator_helpers.h" +#include "src/compiler/node_generator_helpers.h" + +using grpc::protobuf::FileDescriptor; +using grpc::protobuf::ServiceDescriptor; +using grpc::protobuf::MethodDescriptor; +using grpc::protobuf::Descriptor; +using grpc::protobuf::io::Printer; +using grpc::protobuf::io::StringOutputStream; +using std::map; + +namespace grpc_node_generator { +namespace { + +// Returns the alias we assign to the module of the given .proto filename +// when importing. Copied entirely from +// github:google/protobuf/src/google/protobuf/compiler/js/js_generator.cc#L154 +grpc::string ModuleAlias(const grpc::string filename) { + // This scheme could technically cause problems if a file includes any 2 of: + // foo/bar_baz.proto + // foo_bar_baz.proto + // foo_bar/baz.proto + // + // We'll worry about this problem if/when we actually see it. This name isn't + // exposed to users so we can change it later if we need to. + grpc::string basename = grpc_generator::StripProto(filename); + basename = grpc_generator::StringReplace(basename, "-", "$"); + basename = grpc_generator::StringReplace(basename, "/", "_"); + return basename + "_pb"; +} + +// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript +// message file foo/bar/baz.js +grpc::string GetJSMessageFilename(const grpc::string& filename) { + grpc::string name = filename; + return grpc_generator::StripProto(name) + "_pb.js"; +} + +// Given a filename like foo/bar/baz.proto, returns the root directory +// path ../../ +grpc::string GetRootPath(const grpc::string& filename) { + size_t slashes = std::count(filename.begin(), filename.end(), '/'); + if (slashes == 0) { + return "./"; + } + grpc::string result = ""; + for (size_t i = 0; i < slashes; i++) { + result += "../"; + } + return result; +} + +// Return the relative path to load to_file from the directory containing +// from_file, assuming that both paths are relative to the same directory +grpc::string GetRelativePath(const grpc::string& from_file, + const grpc::string& to_file) { + return GetRootPath(from_file) + to_file; +} + +/* Finds all message types used in all services in the file, and returns them + * as a map of fully qualified message type name to message descriptor */ +map<grpc::string, const Descriptor*> GetAllMessages(const FileDescriptor *file) { + map<grpc::string, const Descriptor*> message_types; + for (int i = 0; i < file->service_count(); i++) { + const ServiceDescriptor* service = file->service(i); + for (int j = 0; j < service->method_count(); j++) { + const MethodDescriptor* method = service->method(i); + const Descriptor* input_type = method->input_type(); + const Descriptor* output_type = method->output_type(); + message_types[input_type->name()] = input_type; + message_types[output_type->name()] = output_type; + } + } + return message_types; +} + +grpc::string MessageIdentifierName(const grpc::string& name) { + return grpc_generator::StringReplace(name, ".", "_"); +} + +grpc::string NodeObjectPath(const Descriptor *descriptor) { + grpc::string module_alias = ModuleAlias(descriptor->file()->name()); + grpc::string name = descriptor->name(); + grpc_generator::StripPrefix(&name, descriptor->file()->package() + "."); + return module_alias + "." + name; +} + +// Prints out the message serializer and deserializer functions +void PrintMessageTransformer(const Descriptor *descriptor, Printer *out) { + map<grpc::string, grpc::string> template_vars; + template_vars["identifier_name"] = MessageIdentifierName(descriptor->name()); + template_vars["name"] = descriptor->name(); + template_vars["node_name"] = NodeObjectPath(descriptor); + // Print the serializer + out->Print(template_vars, "function serialize_$identifier_name$(arg) {\n"); + out->Indent(); + out->Print(template_vars, "if (!(arg instanceof $node_name$)) {\n"); + out->Indent(); + out->Print(template_vars, + "throw new Error('Expected argument of type $name$');\n"); + out->Outdent(); + out->Print("}\n"); + out->Print("return new Buffer(arg.serializeBinary());\n"); + out->Outdent(); + out->Print("}\n"); + + // Print the deserializer + out->Print(template_vars, + "function deserialize_$identifier_name$(buffer_arg) {\n"); + out->Indent(); + out->Print( + template_vars, + "return $node_name$.deserializeBinary(new Uint8Array(buffer_arg));\n"); + out->Outdent(); + out->Print("}\n"); +} + +void PrintMethod(const MethodDescriptor *method, Printer *out) { + const Descriptor *input_type = method->input_type(); + const Descriptor *output_type = method->output_type(); + map<grpc::string, grpc::string> vars; + vars["service_name"] = method->service()->full_name(); + vars["name"] = method->name(); + vars["input_type"] = NodeObjectPath(input_type); + vars["input_type_id"] = MessageIdentifierName(input_type->name()); + vars["output_type"] = NodeObjectPath(output_type); + vars["output_type_id"] = MessageIdentifierName(output_type->name()); + vars["client_stream"] = method->client_streaming() ? "true" : "false"; + vars["server_stream"] = method->server_streaming() ? "true" : "false"; + out->Print("{\n"); + out->Indent(); + out->Print(vars, "path: '/$service_name$/$name$',\n"); + out->Print(vars, "requestStream: $client_stream$,\n"); + out->Print(vars, "responseStream: $server_stream$,\n"); + out->Print(vars, "requestType: $input_type$,\n"); + out->Print(vars, "responseType: $output_type$,\n"); + out->Print(vars, "requestSerialize: serialize_$input_type_id$,\n"); + out->Print(vars, "requestDeserialize: deserialize_$input_type_id$,\n"); + out->Print(vars, "responseSerialize: serialize_$output_type_id$,\n"); + out->Print(vars, "responseDeserialize: deserialize_$output_type_id$,\n"); + out->Outdent(); + out->Print("}"); +} + +// Prints out the service descriptor object +void PrintService(const ServiceDescriptor *service, Printer *out) { + map<grpc::string, grpc::string> template_vars; + template_vars["name"] = service->name(); + out->Print(template_vars, "var $name$Service = exports.$name$Service = {\n"); + out->Indent(); + for (int i = 0; i < service->method_count(); i++) { + grpc::string method_name = grpc_generator::LowercaseFirstLetter( + service->method(i)->name()); + out->Print("$method_name$: ", + "method_name", method_name); + PrintMethod(service->method(i), out); + out->Print(",\n"); + } + out->Outdent(); + out->Print("};\n\n"); + out->Print(template_vars, "exports.$name$Client = " + "grpc.makeGenericClientConstructor($name$Service);\n"); +} + +} + +grpc::string GetImports(const FileDescriptor *file) { + grpc::string output; + { + StringOutputStream output_stream(&output); + Printer out(&output_stream, '$'); + + if (file->service_count() == 0) { + return output; + } + + out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n"); + + out.Print("var grpc = require('grpc');\n"); + if (file->message_type_count() > 0) { + grpc::string file_path = GetRelativePath(file->name(), + GetJSMessageFilename( + file->name())); + out.Print("var $module_alias$ = require('$file_path$');\n", + "module_alias", ModuleAlias(file->name()), + "file_path", file_path); + } + + for (int i = 0; i < file->dependency_count(); i++) { + grpc::string file_path = GetRelativePath( + file->name(), GetJSMessageFilename(file->dependency(i)->name())); + out.Print("var $module_alias$ = require('$file_path$');\n", + "module_alias", ModuleAlias(file->dependency(i)->name()), + "file_path", file_path); + } + out.Print("\n"); + } + return output; +} + +grpc::string GetTransformers(const FileDescriptor *file) { + grpc::string output; + { + StringOutputStream output_stream(&output); + Printer out(&output_stream, '$'); + + if (file->service_count() == 0) { + return output; + } + + map<grpc::string, const Descriptor*> messages = GetAllMessages(file); + for (std::map<grpc::string, const Descriptor*>::iterator it = + messages.begin(); + it != messages.end(); it++) { + PrintMessageTransformer(it->second, &out); + } + out.Print("\n"); + } + return output; +} + +grpc::string GetServices(const FileDescriptor *file) { + grpc::string output; + { + StringOutputStream output_stream(&output); + Printer out(&output_stream, '$'); + + if (file->service_count() == 0) { + return output; + } + + for (int i = 0; i < file->service_count(); i++) { + PrintService(file->service(i), &out); + } + } + return output; +} + +} // namespace grpc_node_generator diff --git a/src/compiler/node_generator.h b/src/compiler/node_generator.h new file mode 100644 index 0000000000..249a0d011f --- /dev/null +++ b/src/compiler/node_generator.h @@ -0,0 +1,49 @@ +/* + * + * Copyright 2016, 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_NODE_GENERATOR_H +#define GRPC_INTERNAL_COMPILER_NODE_GENERATOR_H + +#include "src/compiler/config.h" + +namespace grpc_node_generator { + +grpc::string GetImports(const grpc::protobuf::FileDescriptor *file); + +grpc::string GetTransformers(const grpc::protobuf::FileDescriptor *file); + +grpc::string GetServices(const grpc::protobuf::FileDescriptor *file); + +} // namespace grpc_node_generator + +#endif // GRPC_INTERNAL_COMPILER_NODE_GENERATOR_H diff --git a/src/compiler/node_generator_helpers.h b/src/compiler/node_generator_helpers.h new file mode 100644 index 0000000000..f41a2bcf59 --- /dev/null +++ b/src/compiler/node_generator_helpers.h @@ -0,0 +1,50 @@ +/* + * + * Copyright 2016, 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_NODE_GENERATOR_HELPERS_H +#define GRPC_INTERNAL_COMPILER_NODE_GENERATOR_HELPERS_H + +#include <algorithm> + +#include "src/compiler/config.h" +#include "src/compiler/generator_helpers.h" + +namespace grpc_node_generator { + +inline grpc::string GetJSServiceFilename(const grpc::string& filename) { + return grpc_generator::StripProto(filename) + "_grpc_pb.js"; +} + +} // namespace grpc_node_generator + +#endif // GRPC_INTERNAL_COMPILER_NODE_GENERATOR_HELPERS_H diff --git a/src/compiler/node_plugin.cc b/src/compiler/node_plugin.cc new file mode 100644 index 0000000000..ac5ced3558 --- /dev/null +++ b/src/compiler/node_plugin.cc @@ -0,0 +1,77 @@ +/* + * + * 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 Node gRPC service interface out of Protobuf IDL. + +#include <memory> + +#include "src/compiler/config.h" +#include "src/compiler/node_generator.h" +#include "src/compiler/node_generator_helpers.h" + +using grpc_node_generator::GetImports; +using grpc_node_generator::GetJSServiceFilename; +using grpc_node_generator::GetServices; +using grpc_node_generator::GetTransformers; + +class NodeGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { + public: + NodeGrpcGenerator() {} + ~NodeGrpcGenerator() {} + + bool Generate(const grpc::protobuf::FileDescriptor *file, + const grpc::string ¶meter, + grpc::protobuf::compiler::GeneratorContext *context, + grpc::string *error) const { + grpc::string code = GetImports(file) + + GetTransformers(file) + + GetServices(file); + if (code.size() == 0) { + return true; + } + + // Get output file name + grpc::string file_name = GetJSServiceFilename(file->name()); + + std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output( + context->Open(file_name)); + grpc::protobuf::io::CodedOutputStream coded_out(output.get()); + coded_out.WriteRaw(code.data(), code.size()); + return true; + } +}; + +int main(int argc, char *argv[]) { + NodeGrpcGenerator generator; + return grpc::protobuf::compiler::PluginMain(argc, argv, &generator); +} diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 7978f12d53..a0d1f81b5e 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -2160,6 +2160,19 @@ ], "headers": [], "language": "c++", + "name": "grpc_node_plugin", + "src": [ + "src/compiler/node_plugin.cc" + ], + "third_party": false, + "type": "target" + }, + { + "deps": [ + "grpc_plugin_support" + ], + "headers": [], + "language": "c++", "name": "grpc_objective_c_plugin", "src": [ "src/compiler/objective_c_plugin.cc" @@ -4325,6 +4338,8 @@ "src/compiler/csharp_generator.h", "src/compiler/csharp_generator_helpers.h", "src/compiler/generator_helpers.h", + "src/compiler/node_generator.h", + "src/compiler/node_generator_helpers.h", "src/compiler/objective_c_generator.h", "src/compiler/objective_c_generator_helpers.h", "src/compiler/python_generator.h", @@ -4344,6 +4359,9 @@ "src/compiler/csharp_generator.h", "src/compiler/csharp_generator_helpers.h", "src/compiler/generator_helpers.h", + "src/compiler/node_generator.cc", + "src/compiler/node_generator.h", + "src/compiler/node_generator_helpers.h", "src/compiler/objective_c_generator.cc", "src/compiler/objective_c_generator.h", "src/compiler/objective_c_generator_helpers.h", diff --git a/vsprojects/grpc_protoc_plugins.sln b/vsprojects/grpc_protoc_plugins.sln index ef1cbb8e57..ace295daea 100644 --- a/vsprojects/grpc_protoc_plugins.sln +++ b/vsprojects/grpc_protoc_plugins.sln @@ -24,6 +24,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_csharp_plugin", "vcxpr {B6E81D84-2ACB-41B8-8781-493A944C7817} = {B6E81D84-2ACB-41B8-8781-493A944C7817} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_node_plugin", "vcxproj\.\grpc_node_plugin\grpc_node_plugin.vcxproj", "{57ABD9A2-CE8E-CCA7-5171-35C4534F3595}" + ProjectSection(myProperties) = preProject + lib = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {B6E81D84-2ACB-41B8-8781-493A944C7817} = {B6E81D84-2ACB-41B8-8781-493A944C7817} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_objective_c_plugin", "vcxproj\.\grpc_objective_c_plugin\grpc_objective_c_plugin.vcxproj", "{19564640-CEE6-4921-ABA5-676ED79A36F6}" ProjectSection(myProperties) = preProject lib = "False" @@ -80,6 +88,14 @@ Global {3C813052-A49A-4662-B90A-1ADBEC7EE453}.Debug|x64.Build.0 = Debug|x64 {3C813052-A49A-4662-B90A-1ADBEC7EE453}.Release|Win32.Build.0 = Release|Win32 {3C813052-A49A-4662-B90A-1ADBEC7EE453}.Release|x64.Build.0 = Release|x64 + {57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Debug|Win32.ActiveCfg = Debug|Win32 + {57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Debug|x64.ActiveCfg = Debug|x64 + {57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Release|Win32.ActiveCfg = Release|Win32 + {57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Release|x64.ActiveCfg = Release|x64 + {57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Debug|Win32.Build.0 = Debug|Win32 + {57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Debug|x64.Build.0 = Debug|x64 + {57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Release|Win32.Build.0 = Release|Win32 + {57ABD9A2-CE8E-CCA7-5171-35C4534F3595}.Release|x64.Build.0 = Release|x64 {19564640-CEE6-4921-ABA5-676ED79A36F6}.Debug|Win32.ActiveCfg = Debug|Win32 {19564640-CEE6-4921-ABA5-676ED79A36F6}.Debug|x64.ActiveCfg = Debug|x64 {19564640-CEE6-4921-ABA5-676ED79A36F6}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj b/vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj new file mode 100644 index 0000000000..faf93fd136 --- /dev/null +++ b/vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj @@ -0,0 +1,168 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{57ABD9A2-CE8E-CCA7-5171-35C4534F3595}</ProjectGuid> + <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected> + <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration"> + <PlatformToolset>v100</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration"> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration"> + <PlatformToolset>v120</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration"> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(SolutionDir)\..\vsprojects\global.props" /> + <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" /> + <Import Project="$(SolutionDir)\..\vsprojects\protoc.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)'=='Debug'"> + <TargetName>grpc_node_plugin</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Release'"> + <TargetName>grpc_node_plugin</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> + <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> + <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> + <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> + <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> + <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> + <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> + <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> + <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + + <ItemGroup> + <ClCompile Include="$(SolutionDir)\..\src\compiler\node_plugin.cc"> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_plugin_support\grpc_plugin_support.vcxproj"> + <Project>{B6E81D84-2ACB-41B8-8781-493A944C7817}</Project> + </ProjectReference> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> + <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> + <PropertyGroup> + <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> + </PropertyGroup> + </Target> +</Project> + diff --git a/vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj.filters b/vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj.filters new file mode 100644 index 0000000000..28b197f6f3 --- /dev/null +++ b/vsprojects/vcxproj/grpc_node_plugin/grpc_node_plugin.vcxproj.filters @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClCompile Include="$(SolutionDir)\..\src\compiler\node_plugin.cc"> + <Filter>src\compiler</Filter> + </ClCompile> + </ItemGroup> + + <ItemGroup> + <Filter Include="src"> + <UniqueIdentifier>{089d5d6b-d438-dc98-b30f-bd608e3bbb78}</UniqueIdentifier> + </Filter> + <Filter Include="src\compiler"> + <UniqueIdentifier>{1cc34440-c001-7578-c4d3-78f5d98fb602}</UniqueIdentifier> + </Filter> + </ItemGroup> +</Project> + diff --git a/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj b/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj index 4c80226cba..a81d31768d 100644 --- a/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj +++ b/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj @@ -160,6 +160,8 @@ <ClInclude Include="$(SolutionDir)\..\src\compiler\csharp_generator.h" /> <ClInclude Include="$(SolutionDir)\..\src\compiler\csharp_generator_helpers.h" /> <ClInclude Include="$(SolutionDir)\..\src\compiler\generator_helpers.h" /> + <ClInclude Include="$(SolutionDir)\..\src\compiler\node_generator.h" /> + <ClInclude Include="$(SolutionDir)\..\src\compiler\node_generator_helpers.h" /> <ClInclude Include="$(SolutionDir)\..\src\compiler\objective_c_generator.h" /> <ClInclude Include="$(SolutionDir)\..\src\compiler\objective_c_generator_helpers.h" /> <ClInclude Include="$(SolutionDir)\..\src\compiler\python_generator.h" /> @@ -173,6 +175,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\compiler\csharp_generator.cc"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\compiler\node_generator.cc"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\compiler\objective_c_generator.cc"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\compiler\python_generator.cc"> diff --git a/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj.filters b/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj.filters index fc125d911e..b3d2dc2f3d 100644 --- a/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj.filters @@ -7,6 +7,9 @@ <ClCompile Include="$(SolutionDir)\..\src\compiler\csharp_generator.cc"> <Filter>src\compiler</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\compiler\node_generator.cc"> + <Filter>src\compiler</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\compiler\objective_c_generator.cc"> <Filter>src\compiler</Filter> </ClCompile> @@ -50,6 +53,12 @@ <ClInclude Include="$(SolutionDir)\..\src\compiler\generator_helpers.h"> <Filter>src\compiler</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\compiler\node_generator.h"> + <Filter>src\compiler</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\compiler\node_generator_helpers.h"> + <Filter>src\compiler</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\compiler\objective_c_generator.h"> <Filter>src\compiler</Filter> </ClInclude> |