Skip to content

Commit 0bac7fe

Browse files
azymnisjohnynek
authored andcommitted
Make sure that scala proto files are generated correctly for external proto dependencies (#294)
* Make sure to extract workspace root for proto files * Update tests and docs * Append deps to the end * Targets run properly * Fix comments and fail if needed * One more comment * Update readme
1 parent 7573390 commit 0bac7fe

File tree

6 files changed

+81
-48
lines changed

6 files changed

+81
-48
lines changed

README.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<li><a href="#scala_library">scala_library/scala_macro_library</a></li>
88
<li><a href="#scala_binary">scala_binary</a></li>
99
<li><a href="#scala_test">scala_test</a></li>
10+
<li><a href="#scalapb_proto_library">scalapb_proto_library</a></li>
1011
</ul>
1112
</div>
1213

@@ -467,10 +468,20 @@ thrift_library(name, srcs, deps, absolute_prefix, absolute_prefixes)
467468
</tbody>
468469
</table>
469470

471+
<a name="scalapb_proto_library"></a>
470472
## scalapb_proto_library
471473

474+
You first need to add the following to your WORKSPACE file:
475+
476+
```python
477+
load("@io_bazel_rules_scala//scala_proto:scala_proto.bzl", "scala_proto_repositories")
478+
scala_proto_repositories()
479+
```
480+
481+
Then you can import `scalapb_proto_library` in any BUILD file like this:
482+
472483
```python
473-
load("//scala_proto:scala_proto.bzl", "scalapb_proto_library")
484+
load("@io_bazel_rules_scala//scala_proto:scala_proto.bzl", "scalapb_proto_library")
474485
scalapb_proto_library(name, deps, with_grpc, with_java, with_flat_package, with_single_line_to_string)
475486
```
476487

@@ -498,7 +509,7 @@ generated by the [ScalaPB compiler](https://github.com/scalapb/ScalaPB).
498509
<td><code>deps</code></td>
499510
<td>
500511
<p><code>List of labels, required</code></p>
501-
<p>List of proto dependencies that this target depends on. Must be of type <code>proto_library</code></p>
512+
<p>List of dependencies for this target. Must either be of type <code>proto_library</code> or <code>java_proto_library</code> (allowed only if <code>with_java</code> is enabled) </p>
502513
</td>
503514
</tr>
504515
<tr>
@@ -512,7 +523,7 @@ generated by the [ScalaPB compiler](https://github.com/scalapb/ScalaPB).
512523
<td><code>with_java</code></td>
513524
<td>
514525
<p><code>boolean; optional (default False)</code></p>
515-
<p>Enables generation of converters to and from java protobuf bindings</p>
526+
<p>Enables generation of converters to and from java protobuf bindings. If you set this to <code>True</code> make sure that you pass the corresponding <code>java_proto_library</code> target in <code>deps</code></p>
516527
</td>
517528
</tr>
518529
<tr>

scala/scala.bzl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ def _collect_jars_when_dependency_analyzer_is_on(dep_targets):
513513
jars2labels = jars2labels,
514514
transitive_compile_jars = transitive_compile_jars)
515515

516-
def _collect_jars(dep_targets, dependency_analyzer_is_off = True):
516+
def collect_jars(dep_targets, dependency_analyzer_is_off = True):
517517
"""Compute the runtime and compile-time dependencies from the given targets""" # noqa
518518

519519
if dependency_analyzer_is_off:
@@ -541,10 +541,10 @@ def _collect_jars_from_common_ctx(ctx, extra_deps = [], extra_runtime_deps = [])
541541

542542
# Get jars from deps
543543
auto_deps = [ctx.attr._scalalib, ctx.attr._scalareflect]
544-
deps_jars = _collect_jars(ctx.attr.deps + auto_deps + extra_deps, dependency_analyzer_is_off)
544+
deps_jars = collect_jars(ctx.attr.deps + auto_deps + extra_deps, dependency_analyzer_is_off)
545545
(cjars, transitive_rjars, jars2labels, transitive_compile_jars) = (deps_jars.compile_jars, deps_jars.transitive_runtime_jars, deps_jars.jars2labels, deps_jars.transitive_compile_jars)
546546

547-
runtime_dep_jars = _collect_jars(ctx.attr.runtime_deps + extra_runtime_deps, dependency_analyzer_is_off)
547+
runtime_dep_jars = collect_jars(ctx.attr.runtime_deps + extra_runtime_deps, dependency_analyzer_is_off)
548548
transitive_rjars += runtime_dep_jars.transitive_runtime_jars
549549

550550
if not dependency_analyzer_is_off:
@@ -555,7 +555,7 @@ def _collect_jars_from_common_ctx(ctx, extra_deps = [], extra_runtime_deps = [])
555555
def _format_full_jars_for_intellij_plugin(full_jars):
556556
return [struct (class_jar = jar, ijar = None) for jar in full_jars]
557557

558-
def _create_java_provider(ctx, scalaattr, transitive_compile_time_jars):
558+
def create_java_provider(ctx, scalaattr, transitive_compile_time_jars):
559559
# This is needed because Bazel >=0.6.0 requires ctx.actions and a Java
560560
# toolchain. Fortunately, the same change that added this requirement also
561561
# added this field to the Java provider so we can use it to test which
@@ -609,7 +609,7 @@ def _lib(ctx, non_macro_lib):
609609
# Add information from exports (is key that AFTER all build actions/runfiles analysis)
610610
# Since after, will not show up in deploy_jar or old jars runfiles
611611
# Notice that compile_jars is intentionally transitive for exports
612-
exports_jars = _collect_jars(ctx.attr.exports)
612+
exports_jars = collect_jars(ctx.attr.exports)
613613
next_cjars += exports_jars.compile_jars
614614
transitive_rjars += exports_jars.transitive_runtime_jars
615615

@@ -630,7 +630,7 @@ def _lib(ctx, non_macro_lib):
630630
transitive_exports = [] #needed by intellij plugin
631631
)
632632

633-
java_provider = _create_java_provider(ctx, scalaattr, jars.transitive_compile_jars)
633+
java_provider = create_java_provider(ctx, scalaattr, jars.transitive_compile_jars)
634634

635635
return struct(
636636
files = depset([ctx.outputs.jar]), # Here is the default output
@@ -694,7 +694,7 @@ def _scala_binary_common(ctx, cjars, rjars, transitive_compile_time_jars, jars2l
694694
transitive_exports = [] #needed by intellij plugin
695695
)
696696

697-
java_provider = _create_java_provider(ctx, scalaattr, transitive_compile_time_jars)
697+
java_provider = create_java_provider(ctx, scalaattr, transitive_compile_time_jars)
698698

699699
return struct(
700700
files=depset([ctx.outputs.executable]),
@@ -771,7 +771,7 @@ def _scala_test_impl(ctx):
771771
jars.transitive_compile_jars, jars.jars2labels)
772772
# _scalatest is an http_jar, so its compile jar is run through ijar
773773
# however, contains macros, so need to handle separately
774-
scalatest_jars = _collect_jars([ctx.attr._scalatest]).transitive_runtime_jars
774+
scalatest_jars = collect_jars([ctx.attr._scalatest]).transitive_runtime_jars
775775
cjars += scalatest_jars
776776
transitive_rjars += scalatest_jars
777777

scala_proto/scala_proto.bzl

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
load("//scala:scala.bzl",
2-
"scala_library")
2+
"scala_library",
3+
"collect_jars",
4+
"create_java_provider")
35

46
def scala_proto_repositories():
57
native.maven_server(
@@ -308,12 +310,26 @@ def scala_proto_repositories():
308310
)
309311

310312
def _colon_paths(data):
311-
return ':'.join([f.path for f in data])
313+
return ':'.join(["{root},{path}".format(root=f.owner.workspace_root, path=f.path) for f in data])
312314

313315
def _gen_proto_srcjar_impl(ctx):
314316
acc_imports = depset()
317+
318+
proto_deps, java_proto_lib_deps = [], []
315319
for target in ctx.attr.deps:
316-
acc_imports += target.proto.transitive_sources
320+
if hasattr(target, 'proto'):
321+
proto_deps.append(target)
322+
acc_imports += target.proto.transitive_sources
323+
else:
324+
java_proto_lib_deps.append(target)
325+
326+
if not ctx.attr.with_java and len(java_proto_lib_deps) > 0:
327+
fail("cannot have java_proto_library dependencies with with_java is False")
328+
329+
if ctx.attr.with_java and len(java_proto_lib_deps) == 0:
330+
fail("must have a java_proto_library dependency if with_java is True")
331+
332+
deps_jars = collect_jars(java_proto_lib_deps)
317333

318334
# Command line args to worker cannot be empty so using padding
319335
flags = ["-"]
@@ -345,7 +361,15 @@ def _gen_proto_srcjar_impl(ctx):
345361
srcjarsattr = struct(
346362
srcjar = ctx.outputs.srcjar,
347363
)
364+
scalaattr = struct(
365+
outputs = None,
366+
compile_jars = deps_jars.compile_jars,
367+
transitive_runtime_jars = deps_jars.transitive_runtime_jars,
368+
)
369+
java_provider = create_java_provider(ctx, scalaattr, depset())
348370
return struct(
371+
scala = scalaattr,
372+
providers = [java_provider],
349373
srcjars=srcjarsattr,
350374
extra_information=[struct(
351375
srcjars=srcjarsattr,
@@ -357,7 +381,7 @@ scalapb_proto_srcjar = rule(
357381
attrs={
358382
"deps": attr.label_list(
359383
mandatory=True,
360-
allow_rules=["proto_library"]
384+
allow_rules=["proto_library", "java_proto_library"]
361385
),
362386
"with_grpc": attr.bool(default=False),
363387
"with_java": attr.bool(default=False),
@@ -414,7 +438,7 @@ Example:
414438
415439
Args:
416440
name: A unique name for this rule
417-
deps: Proto library targets that this rule depends on (must be of type proto_library)
441+
deps: Proto library or java proto library (if with_java is True) targets that this rule depends on
418442
with_grpc: Enables generation of grpc service bindings for services defined in deps
419443
with_java: Enables generation of converters to and from java protobuf bindings
420444
with_flat_package: When true, ScalaPB will not append the protofile base name to the package name
@@ -446,19 +470,9 @@ def scalapb_proto_library(
446470

447471
external_deps = list(SCALAPB_DEPS + GRPC_DEPS if (with_grpc) else SCALAPB_DEPS)
448472

449-
if with_java:
450-
java_proto_lib = name + "_java_lib"
451-
native.java_proto_library(
452-
name = java_proto_lib,
453-
deps = deps,
454-
visibility = visibility,
455-
)
456-
external_deps.append(java_proto_lib)
457-
458473
scala_library(
459474
name = name,
460-
srcs = [srcjar],
461-
deps = external_deps,
475+
deps = [srcjar] + external_deps,
462476
exports = external_deps,
463477
visibility = visibility,
464478
)

src/scala/scripts/ScalaPBGenerator.scala

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,25 @@ class ScalaPBGenerator extends Processor {
3939

4040
def processRequest(args: java.util.List[String]) {
4141
val jarOutput = args.get(0)
42-
val protoFiles = args.get(1).split(':').toList
42+
val parsedProtoFiles = args.get(1).split(':').toList.map { rootAndFile =>
43+
val parsed = rootAndFile.split(',')
44+
val root = parsed(0)
45+
val file = if (root.isEmpty) {
46+
parsed(1)
47+
} else {
48+
parsed(1).substring(root.length + 1)
49+
}
50+
(file, Paths.get(root, file).toString)
51+
}
52+
// This will map the absolute path of a given proto file
53+
// to a relative path that does not contain the repo prefix.
54+
// This is to match the expected behavior of
55+
// proto_library and java_proto_library where proto files
56+
// can import other proto files using only the relative path
57+
val imports = parsedProtoFiles.map { case (relPath, absolutePath) =>
58+
s"-I${relPath}=${absolutePath}"
59+
}
60+
val protoFiles = parsedProtoFiles.map(_._2)
4361
val flagOpt = args.get(2) match {
4462
case "-" => None
4563
case s => Some(s.drop(2))
@@ -48,7 +66,7 @@ class ScalaPBGenerator extends Processor {
4866
val tmp = Paths.get(Option(System.getProperty("java.io.tmpdir")).getOrElse("/tmp"))
4967
val scalaPBOutput = Files.createTempDirectory(tmp, "bazelscalapb")
5068
val flagPrefix = flagOpt.map(_ + ":").getOrElse("")
51-
val scalaPBArgs = s"--scala_out=${flagPrefix}${scalaPBOutput}" :: protoFiles
69+
val scalaPBArgs = s"--scala_out=${flagPrefix}${scalaPBOutput}" :: (imports ++ protoFiles)
5270
val config = ScalaPBC.processArgs(scalaPBArgs.toArray)
5371
val code = ProtocBridge.runWithGenerators(
5472
protoc = a => com.github.os72.protocjar.Protoc.runProtoc(config.version +: a.toArray),

test/proto/BUILD

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,14 @@ scalapb_proto_library(
2828
visibility = ["//visibility:public"],
2929
)
3030

31+
java_proto_library(
32+
name = "test_proto_java_lib",
33+
deps = [":test2", "//test/proto2:test"],
34+
)
35+
3136
scalapb_proto_library(
3237
name = "test_proto_java_conversions",
33-
deps = [":test2", "//test/proto2:test"],
38+
deps = [":test2", "//test/proto2:test", ":test_proto_java_lib"],
3439
with_java = True,
3540
with_flat_package = True,
3641
visibility = ["//visibility:public"],

twitter_scrooge/twitter_scrooge.bzl

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ load("//scala:scala.bzl",
44
"scala_mvn_artifact",
55
"scala_library",
66
"write_manifest",
7-
"collect_srcjars")
7+
"collect_srcjars",
8+
"collect_jars")
89

910
def twitter_scrooge():
1011
native.maven_server(
@@ -177,7 +178,7 @@ def _gen_scrooge_srcjar_impl(ctx):
177178
arguments=["--jvm_flag=%s" % flag for flag in ctx.attr.jvm_flags] + ["@" + argfile.path],
178179
)
179180

180-
deps_jars = _collect_jars(ctx.attr.deps)
181+
deps_jars = collect_jars(ctx.attr.deps)
181182

182183
scalaattr = struct(
183184
outputs = None,
@@ -201,22 +202,6 @@ def _gen_scrooge_srcjar_impl(ctx):
201202
)],
202203
)
203204

204-
# TODO(twigg): Use the one in scala.bzl?
205-
def _collect_jars(targets):
206-
compile_jars = depset()
207-
transitive_runtime_jars = depset()
208-
209-
for target in targets:
210-
if java_common.provider in target:
211-
java_provider = target[java_common.provider]
212-
compile_jars += java_provider.compile_jars
213-
transitive_runtime_jars += java_provider.transitive_runtime_jars
214-
215-
return struct(
216-
compile_jars = compile_jars,
217-
transitive_runtime_jars = transitive_runtime_jars,
218-
)
219-
220205
scrooge_scala_srcjar = rule(
221206
_gen_scrooge_srcjar_impl,
222207
attrs={

0 commit comments

Comments
 (0)