diff options
author | 2016-02-18 11:07:02 +0000 | |
---|---|---|
committer | 2016-02-18 11:57:07 +0000 | |
commit | 5c5b0b881a55f70b81e386d344555c7a98647842 (patch) | |
tree | 4e416ca0a9fd14bc6530832e5c7dfbca7a827f57 /tools | |
parent | 21f0972619ccd56964f7f5354a1f31702cf1e3f7 (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.md | 29 | ||||
-rw-r--r-- | tools/build_defs/scala/scala.bzl | 68 | ||||
-rw-r--r-- | tools/build_defs/scala/test/BUILD | 12 | ||||
-rw-r--r-- | tools/build_defs/scala/test/Exported.scala | 11 | ||||
-rw-r--r-- | tools/build_defs/scala/test/HelloLib.scala | 1 | ||||
-rw-r--r-- | tools/build_defs/scala/test/OtherLib.scala | 4 | ||||
-rw-r--r-- | tools/build_defs/scala/test/Runtime.scala | 5 |
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" +} |