Browse Source

Merge pull request #883 from pherl/cc_bazel

Extract protoc action into .bzl for cc.
Jisi Liu 10 years ago
parent
commit
beeb3aa74c
2 changed files with 151 additions and 25 deletions
  1. 24 25
      BUILD
  2. 127 0
      protobuf.bzl

+ 24 - 25
BUILD

@@ -18,6 +18,8 @@ COPTS = [
 # Bazel should provide portable link_opts for pthread.
 LINK_OPTS = ["-lpthread"]
 
+load("protobuf", "cc_proto_library")
+
 cc_library(
     name = "protobuf_lite",
     srcs = [
@@ -140,6 +142,14 @@ WELL_KNOWN_PROTOS = [
     "google/protobuf/wrappers.proto",
 ]
 
+cc_proto_library(
+    name = "cc_wkt_protos",
+    srcs = ["src/" + s for s in WELL_KNOWN_PROTOS],
+    internal_bootstrap_hack = 1,
+    include = "src",
+    cc_libs = [":protobuf"],
+)
+
 ################################################################################
 # Protocol Buffers Compiler
 ################################################################################
@@ -258,23 +268,22 @@ cc_binary(
 ################################################################################
 genrule(
     name = "generate_java_descriptor_proto",
-    tools = [":protoc"],
-    srcs = [ "src/google/protobuf/descriptor.proto", ],
-    outs = [ "com/google/protobuf/DescriptorProtos.java" ],
+    srcs = ["src/google/protobuf/descriptor.proto"],
+    outs = ["com/google/protobuf/DescriptorProtos.java"],
     cmd = "$(location :protoc) --java_out=$(@D)/../../.. $<",
+    tools = [":protoc"],
 )
 
 java_library(
     name = "java_proto",
-    visibility = ["//visibility:public"],
     srcs = glob([
-        "java/src/main/java/com/google/protobuf/*.java"
+        "java/src/main/java/com/google/protobuf/*.java",
     ]) + [
-      ":generate_java_descriptor_proto",
-    ]
+        ":generate_java_descriptor_proto",
+    ],
+    visibility = ["//visibility:public"],
 )
 
-
 ################################################################################
 # Tests
 ################################################################################
@@ -328,22 +337,11 @@ TEST_PROTOS = [
     "google/protobuf/util/json_format_proto3.proto",
 ]
 
-PROTOS = LITE_TEST_PROTOS + TEST_PROTOS
-
-INPUTS = PROTOS + WELL_KNOWN_PROTOS
-
-OUTPUTS = ["src/" + x[:-5] + "pb.h" for x in PROTOS] + \
-          ["src/" + x[:-5] + "pb.cc" for x in PROTOS]
-
-genrule(
-    name = "gen_test_protos",
-    srcs = ["src/" + x for x in INPUTS],
-    outs = OUTPUTS,
-    cmd =
-        "$(location :protoc) --cpp_out=$(@D)/src" +
-        "".join([" -I" + x + "=$(location src/" + x + ")" for x in INPUTS]) +
-        "".join([" $(location src/" + x + ")" for x in PROTOS]),
-    tools = [":protoc"],
+cc_proto_library(
+    name = "cc_test_protos",
+    srcs = ["src/" + s for s in (LITE_TEST_PROTOS + TEST_PROTOS)],
+    include = "src",
+    deps = [":cc_wkt_protos"],
 )
 
 COMMON_TEST_SRCS = [
@@ -372,7 +370,7 @@ cc_binary(
 
 cc_test(
     name = "protobuf_test",
-    srcs = OUTPUTS + COMMON_TEST_SRCS + [
+    srcs = COMMON_TEST_SRCS + [
         # AUTOGEN(test_srcs)
         "src/google/protobuf/any_test.cc",
         "src/google/protobuf/arena_unittest.cc",
@@ -449,6 +447,7 @@ cc_test(
     deps = [
         ":protobuf",
         ":protoc_lib",
+        ":cc_test_protos",
         "//external:gtest_main",
     ],
 )

+ 127 - 0
protobuf.bzl

@@ -0,0 +1,127 @@
+# -*- mode: python; -*- PYTHON-PREPROCESSING-REQUIRED
+
+def _gen_dir(ctx):
+  if not ctx.attr.include:
+    return ctx.label.package
+  if not ctx.label.package:
+    return ctx.attr.include
+  return ctx.label.package + '/' + ctx.attr.include
+
+def _cc_outs(srcs):
+  return [s[:-len(".proto")] +  ".pb.h" for s in srcs] + \
+         [s[:-len(".proto")] + ".pb.cc" for s in srcs]
+
+def _py_outs(srcs):
+  return [s[:-len(".proto")] + "_pb2.py" for s in srcs]
+
+def _proto_gen_impl(ctx):
+  """General implementation for generating protos"""
+  srcs = ctx.files.srcs
+  deps = []
+  deps += ctx.files.srcs
+  gen_dir = _gen_dir(ctx)
+  import_flags = ["-I" + gen_dir]
+  for dep in ctx.attr.deps:
+    import_flags += dep.proto.import_flags
+    deps += dep.proto.deps
+
+  args = []
+  if ctx.attr.gen_cc:
+    args += ["--cpp_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
+  if ctx.attr.gen_py:
+    args += ["--python_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
+
+  if args:
+    ctx.action(
+        inputs=srcs + deps,
+        outputs=ctx.outputs.outs,
+        arguments=args + import_flags + [s.path for s in srcs],
+        executable=ctx.executable.protoc,
+    )
+
+  return struct(
+      proto=struct(
+          srcs=srcs,
+          import_flags=import_flags,
+          deps=deps,
+      ),
+  )
+
+_proto_gen = rule(
+    attrs = {
+        "srcs": attr.label_list(allow_files = True),
+        "deps": attr.label_list(providers = ["proto"]),
+        "include": attr.string(),
+        "protoc": attr.label(
+            executable = True,
+            single_file = True,
+            mandatory = True,
+        ),
+        "gen_cc": attr.bool(),
+        "gen_py": attr.bool(),
+        "outs": attr.output_list(),
+    },
+    output_to_genfiles = True,
+    implementation = _proto_gen_impl,
+)
+
+def cc_proto_library(
+        name,
+        srcs=[],
+        deps=[],
+        cc_libs=[],
+        include="",
+        protoc=":protoc",
+        internal_bootstrap_hack=False,
+        **kargs):
+  """Bazel rule to create a C++ protobuf library from proto source files
+
+  Args:
+    name: the name of the cc_proto_library.
+    srcs: the .proto files of the cc_proto_library.
+    deps: a list of dependency labels; must be cc_proto_library.
+    cc_libs: a list of other cc_library targets depended by the generated
+        cc_library.
+    include: a string indicating the include path of the .proto files.
+    protoc: the label of the protocol compiler to generate the sources.
+    internal_bootstrap_hack: a flag indicate the cc_proto_library is used only
+        for bootstraping. When it is set to True, no files will be generated.
+        The rule will simply be a provider for .proto files, so that other
+        cc_proto_library can depend on it.
+    **kargs: other keyword arguments that are passed to cc_library.
+
+  """
+
+  if internal_bootstrap_hack:
+    # For pre-checked-in generated files, we add the internal_bootstrap_hack
+    # which will skip the codegen action.
+    _proto_gen(
+        name=name + "_genproto",
+        srcs=srcs,
+        deps=[s + "_genproto" for s in deps],
+        include=include,
+        protoc=protoc,
+    )
+    # An empty cc_library to make rule dependency consistent.
+    native.cc_library(
+        name=name,
+        **kargs)
+    return
+
+  outs = _cc_outs(srcs)
+  _proto_gen(
+      name=name + "_genproto",
+      srcs=srcs,
+      deps=[s + "_genproto" for s in deps],
+      include=include,
+      protoc=protoc,
+      gen_cc=1,
+      outs=outs,
+  )
+
+  native.cc_library(
+      name=name,
+      srcs=outs,
+      deps=cc_libs + deps,
+      includes=[include],
+      **kargs)