Browse Source

Merge pull request #3981 from fahhem/patch-3

Handle srcs in generated files by cd'ing in and out
Adam Cozzette 7 years ago
parent
commit
2c30fa71e7
2 changed files with 107 additions and 32 deletions
  1. 29 0
      BUILD
  2. 78 32
      protobuf.bzl

+ 29 - 0
BUILD

@@ -940,3 +940,32 @@ objc_library(
     non_arc_srcs = OBJC_SRCS,
     visibility = ["//visibility:public"],
 )
+
+################################################################################
+# Test generated proto support
+################################################################################
+
+genrule(
+    name = "generated_protos",
+    srcs = ["src/google/protobuf/unittest_import.proto"],
+    outs = ["unittest_gen.proto"],
+    cmd = "cat $(SRCS) | sed 's|google/|src/google/|' >  $(OUTS)"
+)
+
+proto_library(
+    name = "generated_protos_proto",
+    srcs = [
+        "unittest_gen.proto",
+        "src/google/protobuf/unittest_import_public.proto",
+    ],
+)
+
+py_proto_library(
+    name = "generated_protos_py",
+    srcs = [
+        "unittest_gen.proto",
+        "src/google/protobuf/unittest_import_public.proto",
+    ],
+    default_runtime = "",
+    protoc = ":protoc",
+)

+ 78 - 32
protobuf.bzl

@@ -74,7 +74,7 @@ def _proto_gen_impl(ctx):
   deps = []
   deps += ctx.files.srcs
   source_dir = _SourceDir(ctx)
-  gen_dir = _GenDir(ctx)
+  gen_dir = _GenDir(ctx).rstrip('/')
   if source_dir:
     import_flags = ["-I" + source_dir, "-I" + gen_dir]
   else:
@@ -84,37 +84,83 @@ def _proto_gen_impl(ctx):
     import_flags += dep.proto.import_flags
     deps += dep.proto.deps
 
-  args = []
-  if ctx.attr.gen_cc:
-    args += ["--cpp_out=" + gen_dir]
-  if ctx.attr.gen_py:
-    args += ["--python_out=" + gen_dir]
-
-  inputs = srcs + deps
-  if ctx.executable.plugin:
-    plugin = ctx.executable.plugin
-    lang = ctx.attr.plugin_language
-    if not lang and plugin.basename.startswith('protoc-gen-'):
-      lang = plugin.basename[len('protoc-gen-'):]
-    if not lang:
-      fail("cannot infer the target language of plugin", "plugin_language")
-
-    outdir = gen_dir
-    if ctx.attr.plugin_options:
-      outdir = ",".join(ctx.attr.plugin_options) + ":" + outdir
-    args += ["--plugin=protoc-gen-%s=%s" % (lang, plugin.path)]
-    args += ["--%s_out=%s" % (lang, outdir)]
-    inputs += [plugin]
-
-  if args:
-    ctx.action(
-        inputs=inputs,
-        outputs=ctx.outputs.outs,
-        arguments=args + import_flags + [s.path for s in srcs],
-        executable=ctx.executable.protoc,
-        mnemonic="ProtoCompile",
-        use_default_shell_env=True,
-    )
+  if not ctx.attr.gen_cc and not ctx.attr.gen_py and not ctx.executable.plugin:
+    return struct(
+        proto=struct(
+            srcs=srcs,
+            import_flags=import_flags,
+            deps=deps,
+        ),  
+    )   
+
+  for src in srcs:
+    args = []
+
+    in_gen_dir = src.root.path == gen_dir
+    if in_gen_dir:
+      import_flags_real = []
+      for f in depset(import_flags):
+        path = f.replace('-I', '') 
+        import_flags_real.append('-I$(realpath -s %s)' % path)
+
+    outs = []
+    use_grpc_plugin = (ctx.attr.plugin_language == "grpc" and ctx.attr.plugin)
+    path_tpl = "$(realpath %s)" if in_gen_dir else "%s"
+    if ctx.attr.gen_cc:
+      args += [("--cpp_out=" + path_tpl) % gen_dir]
+      outs.extend(_CcOuts([src.basename], use_grpc_plugin=use_grpc_plugin))
+    if ctx.attr.gen_py:
+      args += [("--python_out=" + path_tpl) % gen_dir]
+      outs.extend(_PyOuts([src.basename], use_grpc_plugin=use_grpc_plugin))
+
+    outs = [ctx.actions.declare_file(out, sibling=src) for out in outs]
+    inputs = [src] + deps
+    if ctx.executable.plugin:
+      plugin = ctx.executable.plugin
+      lang = ctx.attr.plugin_language
+      if not lang and plugin.basename.startswith('protoc-gen-'):
+        lang = plugin.basename[len('protoc-gen-'):]
+      if not lang:
+        fail("cannot infer the target language of plugin", "plugin_language")
+
+      outdir = "." if in_gen_dir else gen_dir
+
+      if ctx.attr.plugin_options:
+        outdir = ",".join(ctx.attr.plugin_options) + ":" + outdir
+      args += [("--plugin=protoc-gen-%s=" + path_tpl) % (lang, plugin.path)]
+      args += ["--%s_out=%s" % (lang, outdir)]
+      inputs += [plugin]
+
+    if not in_gen_dir:
+      ctx.action(
+          inputs=inputs,
+          outputs=outs,
+          arguments=args + import_flags + [src.path],
+          executable=ctx.executable.protoc,
+          mnemonic="ProtoCompile",
+          use_default_shell_env=True,
+      )
+    else:
+      for out in outs:
+        orig_command = " ".join(
+            ["$(realpath %s)" % ctx.executable.protoc.path] + args +
+            import_flags_real + ["-I.", src.basename])
+        command = ";".join([
+            'CMD="%s"' % orig_command,
+            "cd %s" % src.dirname,
+            "${CMD}",
+            "cd -",
+        ])
+        generated_out = '/'.join([gen_dir,  out.basename])
+        if generated_out != out.path:
+            command += ";mv %s %s" % (generated_out, out.path)
+        ctx.action(
+            inputs=inputs + [ctx.executable.protoc],
+            outputs=[out],
+            command=command,
+            mnemonic="ProtoCompile",
+            use_default_shell_env=True,
+        )
 
   return struct(
       proto=struct(