aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
authorGravatar Oscar Boykin <oscar.boykin@gmail.com>2016-02-18 11:07:02 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2016-02-18 11:57:07 +0000
commit5c5b0b881a55f70b81e386d344555c7a98647842 (patch)
tree4e416ca0a9fd14bc6530832e5c7dfbca7a827f57 /tools
parent21f0972619ccd56964f7f5354a1f31702cf1e3f7 (diff)
Adds export and runtime_deps support to scala rule
This brings the scala rules a step closer to feature parity with java. -- Change-Id: I21e6929a36f5084a29b230f1b91307dd5b012d4c Reviewed-on: https://github.com/bazelbuild/bazel/pull/916 MOS_MIGRATED_REVID=114947019
Diffstat (limited to 'tools')
-rw-r--r--tools/build_defs/scala/README.md29
-rw-r--r--tools/build_defs/scala/scala.bzl68
-rw-r--r--tools/build_defs/scala/test/BUILD12
-rw-r--r--tools/build_defs/scala/test/Exported.scala11
-rw-r--r--tools/build_defs/scala/test/HelloLib.scala1
-rw-r--r--tools/build_defs/scala/test/OtherLib.scala4
-rw-r--r--tools/build_defs/scala/test/Runtime.scala5
7 files changed, 99 insertions, 31 deletions
diff --git a/tools/build_defs/scala/README.md b/tools/build_defs/scala/README.md
index 2589548217..20b40eadfe 100644
--- a/tools/build_defs/scala/README.md
+++ b/tools/build_defs/scala/README.md
@@ -28,8 +28,8 @@ scala_repositories()
## scala\_library / scala\_macro_library
```python
-scala_library(name, srcs, deps, data, main_class, resources, scalacopts, jvm_flags)
-scala_macro_library(name, srcs, deps, data, main_class, resources, scalacopts, jvm_flags)
+scala_library(name, srcs, deps, runtime_deps, exports, data, main_class, resources, scalacopts, jvm_flags)
+scala_macro_library(name, srcs, deps, runtime_deps, exports, data, main_class, resources, scalacopts, jvm_flags)
```
`scala_library` generates a `.jar` file from `.scala` source files. This rule
@@ -76,6 +76,22 @@ In order to make a java rule use this jar file, use the `java_import` rule.
</td>
</tr>
<tr>
+ <td><code>runtime_deps</code></td>
+ <td>
+ <p><code>List of labels, optional</code></p>
+ <p>List of other libraries to put on the classpath only at runtime. This is rarely needed in Scala.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>exports</code></td>
+ <td>
+ <p><code>List of labels, optional</code></p>
+ <p>List of targets to add to the dependencies of those that depend on this target. Similar
+ to the `java_library` parameter of the same name. Use this sparingly as it weakens the
+ precision of the build graph.</p>
+ </td>
+ </tr>
+ <tr>
<td><code>data</code></td>
<td>
<p><code>List of labels, optional</code></p>
@@ -135,7 +151,7 @@ In order to make a java rule use this jar file, use the `java_import` rule.
## scala_binary
```python
-scala_binary(name, srcs, deps, data, main_class, resources, scalacopts, jvm_flags)
+scala_binary(name, srcs, deps, runtime_deps, data, main_class, resources, scalacopts, jvm_flags)
```
`scala_binary` generates a Scala executable. It may depend on `scala_library`, `scala_macro_library`
@@ -176,6 +192,13 @@ A `scala_binary` requires a `main_class` attribute.
</td>
</tr>
<tr>
+ <td><code>runtime_deps</code></td>
+ <td>
+ <p><code>List of labels, optional</code></p>
+ <p>List of other libraries to put on the classpath only at runtime. This is rarely needed in Scala.</p>
+ </td>
+ </tr>
+ <tr>
<td><code>data</code></td>
<td>
<p><code>List of labels, optional</code></p>
diff --git a/tools/build_defs/scala/scala.bzl b/tools/build_defs/scala/scala.bzl
index 6e2946b959..2bfc5782a4 100644
--- a/tools/build_defs/scala/scala.bzl
+++ b/tools/build_defs/scala/scala.bzl
@@ -117,14 +117,17 @@ cd $0.runfiles
output=ctx.outputs.executable,
content=content)
-def _collect_comp_run_jars(ctx):
- compile_jars = set() # not transitive
- runtime_jars = set() # this is transitive
- for target in ctx.attr.deps:
+def _collect_jars(targets):
+ """Compute the runtime and compile-time dependencies from the given targets"""
+ compile_jars = set() # not transitive
+ runtime_jars = set() # this is transitive
+ for target in targets:
found = False
if hasattr(target, "scala"):
compile_jars += [target.scala.outputs.ijar]
+ compile_jars += target.scala.transitive_compile_exports
runtime_jars += target.scala.transitive_runtime_deps
+ runtime_jars += target.scala.transitive_runtime_exports
found = True
if hasattr(target, "java"):
# see JavaSkylarkApiProvider.java, this is just the compile-time deps
@@ -137,32 +140,30 @@ def _collect_comp_run_jars(ctx):
# support http_file pointed at a jar. http_jar uses ijar, which breaks scala macros
runtime_jars += target.files
compile_jars += target.files
- return (compile_jars, runtime_jars)
+ return struct(compiletime = compile_jars, runtime = runtime_jars)
-def _scala_library_impl(ctx):
- (cjars, rjars) = _collect_comp_run_jars(ctx)
+def _lib(ctx, use_ijar):
+ jars = _collect_jars(ctx.attr.deps)
+ (cjars, rjars) = (jars.compiletime, jars.runtime)
_write_manifest(ctx)
- _compile(ctx, cjars, True)
+ _compile(ctx, cjars, use_ijar)
rjars += [ctx.outputs.jar]
- scalaattr = struct(outputs = struct(ijar=ctx.outputs.ijar, class_jar=ctx.outputs.jar),
- transitive_runtime_deps = rjars)
- runfiles = ctx.runfiles(
- files = list(rjars),
- collect_data = True)
- return struct(
- scala = scalaattr,
- runfiles=runfiles)
+ rjars += _collect_jars(ctx.attr.runtime_deps).runtime
-def _scala_macro_library_impl(ctx):
- (cjars, rjars) = _collect_comp_run_jars(ctx)
- _write_manifest(ctx)
- _compile(ctx, cjars, False)
+ ijar = None
+ if use_ijar:
+ ijar = ctx.outputs.ijar
+ else:
+ # macro code needs to be available at compile-time, so set ijar == jar
+ ijar = ctx.outputs.jar
- rjars += [ctx.outputs.jar]
- # macro code needs to be available at compiletime, so set ijar == jar
- scalaattr = struct(outputs = struct(ijar=ctx.outputs.jar, class_jar=ctx.outputs.jar),
- transitive_runtime_deps = rjars)
+ texp = _collect_jars(ctx.attr.exports)
+ scalaattr = struct(outputs = struct(ijar=ijar, class_jar=ctx.outputs.jar),
+ transitive_runtime_deps = rjars,
+ transitive_compile_exports = texp.compiletime,
+ transitive_runtime_exports = texp.runtime
+ )
runfiles = ctx.runfiles(
files = list(rjars),
collect_data = True)
@@ -170,10 +171,16 @@ def _scala_macro_library_impl(ctx):
scala = scalaattr,
runfiles=runfiles)
+def _scala_library_impl(ctx):
+ return _lib(ctx, True)
+
+def _scala_macro_library_impl(ctx):
+ return _lib(ctx, False) # don't build the ijar for macros
+
# Common code shared by all scala binary implementations.
def _scala_binary_common(ctx, cjars, rjars):
_write_manifest(ctx)
- _compile(ctx, cjars, False)
+ _compile(ctx, cjars, False) # no need to build an ijar for an executable
runfiles = ctx.runfiles(
files = list(rjars) + [ctx.outputs.executable] + [ctx.file._java] + ctx.files._jdk,
@@ -183,16 +190,20 @@ def _scala_binary_common(ctx, cjars, rjars):
runfiles=runfiles)
def _scala_binary_impl(ctx):
- (cjars, rjars) = _collect_comp_run_jars(ctx)
+ jars = _collect_jars(ctx.attr.deps)
+ (cjars, rjars) = (jars.compiletime, jars.runtime)
cjars += [ctx.file._scalareflect]
rjars += [ctx.outputs.jar, ctx.file._scalalib, ctx.file._scalareflect]
+ rjars += _collect_jars(ctx.attr.runtime_deps).runtime
_write_launcher(ctx, rjars)
return _scala_binary_common(ctx, cjars, rjars)
def _scala_test_impl(ctx):
- (cjars, rjars) = _collect_comp_run_jars(ctx)
+ jars = _collect_jars(ctx.attr.deps)
+ (cjars, rjars) = (jars.compiletime, jars.runtime)
cjars += [ctx.file._scalareflect, ctx.file._scalatest, ctx.file._scalaxml]
rjars += [ctx.outputs.jar, ctx.file._scalalib, ctx.file._scalareflect, ctx.file._scalatest, ctx.file._scalaxml]
+ rjars += _collect_jars(ctx.attr.runtime_deps).runtime
_write_test_launcher(ctx, rjars)
return _scala_binary_common(ctx, cjars, rjars)
@@ -213,6 +224,7 @@ _common_attrs = {
allow_files=_scala_filetype,
non_empty=True),
"deps": attr.label_list(),
+ "runtime_deps": attr.label_list(),
"data": attr.label_list(allow_files=True, cfg=DATA_CFG),
"resources": attr.label_list(allow_files=True),
"scalacopts":attr.string_list(),
@@ -223,6 +235,7 @@ scala_library = rule(
implementation=_scala_library_impl,
attrs={
"main_class": attr.string(),
+ "exports": attr.label_list(allow_files=False),
} + _implicit_deps + _common_attrs,
outputs={
"jar": "%{name}_deploy.jar",
@@ -235,6 +248,7 @@ scala_macro_library = rule(
implementation=_scala_macro_library_impl,
attrs={
"main_class": attr.string(),
+ "exports": attr.label_list(allow_files=False),
"_scala-reflect": attr.label(default=Label("@scala//:lib/scala-reflect.jar"), single_file=True, allow_files=True),
} + _implicit_deps + _common_attrs,
outputs={
diff --git a/tools/build_defs/scala/test/BUILD b/tools/build_defs/scala/test/BUILD
index cd9ad27bc3..4ef5e95ba7 100644
--- a/tools/build_defs/scala/test/BUILD
+++ b/tools/build_defs/scala/test/BUILD
@@ -49,6 +49,18 @@ scala_test(
scala_library(
name = "OtherLib",
srcs = ["OtherLib.scala"],
+ exports = ["Exported"], # test of exported target
+)
+
+scala_library(
+ name = "Exported",
+ srcs = ["Exported.scala"],
+ runtime_deps = ["Runtime"],
+)
+
+scala_library(
+ name = "Runtime",
+ srcs = ["Runtime.scala"],
)
java_library(
diff --git a/tools/build_defs/scala/test/Exported.scala b/tools/build_defs/scala/test/Exported.scala
new file mode 100644
index 0000000000..82264ec5de
--- /dev/null
+++ b/tools/build_defs/scala/test/Exported.scala
@@ -0,0 +1,11 @@
+package scala.test
+
+object Exported {
+ def message: String = {
+ // terrible, don't do this in real code:
+ val msg = Class.forName("scala.test.Runtime")
+ .newInstance
+ .toString
+ "you all, everybody. " + msg
+ }
+}
diff --git a/tools/build_defs/scala/test/HelloLib.scala b/tools/build_defs/scala/test/HelloLib.scala
index a1fef111da..974c8b7298 100644
--- a/tools/build_defs/scala/test/HelloLib.scala
+++ b/tools/build_defs/scala/test/HelloLib.scala
@@ -4,6 +4,7 @@ object HelloLib {
def printMessage(arg: String) {
println(getOtherLibMessage(arg))
println(getOtherJavaLibMessage(arg))
+ println(Exported.message)
}
def getOtherLibMessage(arg: String) : String = {
diff --git a/tools/build_defs/scala/test/OtherLib.scala b/tools/build_defs/scala/test/OtherLib.scala
index f696242d40..2f69f68a7b 100644
--- a/tools/build_defs/scala/test/OtherLib.scala
+++ b/tools/build_defs/scala/test/OtherLib.scala
@@ -3,6 +3,8 @@ package scala.test
// It is just to show how a Scala library can depend on another Scala library.
object OtherLib {
def getMessage(): String = {
- return "scala!"
+ // This won't compile because Exported is exported, not a dep:
+ // Exported.message
+ "scala!"
}
}
diff --git a/tools/build_defs/scala/test/Runtime.scala b/tools/build_defs/scala/test/Runtime.scala
new file mode 100644
index 0000000000..e64c06d82b
--- /dev/null
+++ b/tools/build_defs/scala/test/Runtime.scala
@@ -0,0 +1,5 @@
+package scala.test
+
+class Runtime {
+ override def toString = "I am Runtime"
+}