Extract protoc action into .bzl for cc.

This is needed to support python bazel build.
diff --git a/BUILD b/BUILD
index 1aca02c..a060f06 100644
--- a/BUILD
+++ b/BUILD
@@ -18,6 +18,8 @@
 # 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 @@
     "google/protobuf/wrappers.proto",
 ]
 
+cc_proto_library(
+    name = "cc_wkt_protos",
+    srcs = ["src/" + s for s in WELL_KNOWN_PROTOS],
+    internal_bootstrap_hack = 1,
+    prefix = "src",
+    deps = ":protobuf",
+)
+
 ################################################################################
 # Protocol Buffers Compiler
 ################################################################################
@@ -258,23 +268,22 @@
 ################################################################################
 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 @@
     "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)],
+    prefix = "src",
+    proto_deps = [":cc_wkt_protos"],
 )
 
 COMMON_TEST_SRCS = [
@@ -372,7 +370,7 @@
 
 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 @@
     deps = [
         ":protobuf",
         ":protoc_lib",
+        ":cc_test_protos",
         "//external:gtest_main",
     ],
 )
diff --git a/protobuf.bzl b/protobuf.bzl
new file mode 100644
index 0000000..63ef95f
--- /dev/null
+++ b/protobuf.bzl
@@ -0,0 +1,107 @@
+# -*- mode: python; -*- PYTHON-PREPROCESSING-REQUIRED
+
+
+def _gen_dir(ctx):
+  if not ctx.attr.prefix:
+    return ctx.label.package
+  if not ctx.label.package:
+    return ctx.attr.prefix
+  return ctx.label.package + '/' + ctx.attr.prefix
+
+def CcOuts(srcs):
+  return [s[:-len(".proto")] +  ".pb.h" for s in srcs] + \
+         [s[:-len(".proto")] +  ".pb.cc" for s in srcs]
+
+def PyOuts(srcs):
+  return [s[:-len(".proto")] +  "_pb2.py" for s in srcs]
+
+def _proto_srcs_impl(ctx):
+  """General implementation for calculating proto srcs"""
+  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_srcs = rule(
+    implementation = _proto_srcs_impl,
+    output_to_genfiles = True,
+    attrs = {
+      "srcs": attr.label_list(allow_files=True),
+      "deps": attr.label_list(providers=["proto"]),
+      "prefix": attr.string(),
+      "protoc": attr.label(executable=True, single_file=True, mandatory=True),
+      "gen_cc": attr.bool(),
+      "gen_py": attr.bool(),
+      "outs": attr.output_list()
+    }
+)
+
+def cc_proto_library(
+    name,
+    srcs=[],
+    protoc=":protoc",
+    internal_bootstrap_hack=False,
+    prefix="",
+    proto_deps=[],
+    deps=[],
+    **kargs):
+
+  if internal_bootstrap_hack:
+    # For pre-checked-in generated files, we add the internal_bootstrap_hack
+    # which will skip the codegen action.
+    _proto_srcs(
+        name = name + "_genproto",
+        srcs = srcs,
+        deps = [s + "_genproto" for s in proto_deps],
+        prefix = prefix,
+        protoc = protoc,
+    )
+    # An empty cc_library to make rule dependency consistent.
+    native.cc_library(
+        name = name,
+        **kargs)
+    return
+
+  outs = CcOuts(srcs)
+  _proto_srcs(
+      name = name + "_genproto",
+      srcs = srcs,
+      deps = [s + "_genproto" for s in proto_deps],
+      prefix = prefix,
+      protoc = protoc,
+      gen_cc = 1,
+      outs = outs,
+  )
+
+  native.cc_library(
+      name = name,
+      srcs = outs,
+      deps = deps + proto_deps,
+      includes = [prefix],
+      **kargs)