diff --git a/README.md b/README.md index 8c10303ae..e35ca409c 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ This project defines core build rules for [Scala](https://www.scala-lang.org/) t - [scala_library](./docs/scala_library.md) - [scala_macro_library](./docs/scala_macro_library.md) +- [scala_inlined_library](./docs/scala_inlined_library.md) - [scala_binary](./docs/scala_binary.md) - [scala_test](./docs/scala_test.md) - [scala_repl](./docs/scala_repl.md) diff --git a/docs/customizable_phase.md b/docs/customizable_phase.md index ee9233f53..17e937935 100644 --- a/docs/customizable_phase.md +++ b/docs/customizable_phase.md @@ -146,6 +146,7 @@ Currently phase architecture is used by 7 rules: - scala_library - scala_macro_library +- scala_inlined_library - scala_library_for_plugin_bootstrapping - scala_binary - scala_test diff --git a/docs/scala_inline_library.md b/docs/scala_inline_library.md new file mode 100644 index 000000000..56267b4ff --- /dev/null +++ b/docs/scala_inline_library.md @@ -0,0 +1,177 @@ +# scala_inlined_library + +```py +scala_inlined_library( + name, + srcs, + deps, + runtime_deps, + exports, + data, + main_class, + resources, + resource_strip_prefix, + scalacopts, + jvm_flags, + scalac_jvm_flags, + javac_jvm_flags, + unused_dependency_checker_mode +) +``` + +`scala_inlined_library` generates a `.jar` file from `.scala` source files. This rule +has the interface jar (`ijar`) functionality disabled. +This is to enable inlining the compiled code, when it is given as a dependency for another Scala target (`ijar` +does not contain an implementation, so it cannot be used for inlining). + +In order to have a Java rule use this jar file, use the `java_import` rule. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Attributes
name +

Name, required

+

A unique name for this target

+
srcs +

List of labels, required

+

List of Scala .scala source files used to build the + library. These may be .srcjar jar files that contain source code.

+
deps +

List of labels, optional

+

List of other libraries to linked to this library target. + These must be jvm targets (scala_library, java_library, java_import, etc...)

+
runtime_deps +

List of labels, optional

+

List of other libraries to put on the classpath only at runtime. This is rarely needed in Scala. + These must be jvm targets (scala_library, java_library, java_import, etc...)

+
exports +

List of labels, optional

+

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. + These must be jvm targets (scala_library, java_library, java_import, etc...)

+
data +

List of labels, optional

+

List of files needed by this rule at runtime.

+
main_class +

String, optional

+

Name of class with main() method to use as an entry point

+

+ The value of this attribute is a class name, not a source file. The + class must be available at runtime: it may be compiled by this rule + (from srcs) or provided by direct or transitive + dependencies (through deps). If the class is unavailable, + the binary will fail at runtime; there is no build-time check. +

+
resources +

List of labels; optional

+

A list of data files to be included in the JAR.

+
resource_strip_prefix +

String; optional

+

+ The path prefix to strip from Java resources. If specified, + this path prefix is stripped from every file in the `resources` attribute. + It is an error for a resource file not to be under this directory. +

+
scalacopts +

List of strings; optional

+

+ Extra compiler options for this library to be passed to scalac. Subject to + Make variable + substitution and + Bourne shell tokenization. +

+
jvm_flags +

List of strings; optional; deprecated

+

+ Deprecated, superseded by scalac_jvm_flags and javac_jvm_flags. Is not used and is kept as backwards compatibility for the near future. Effectively jvm_flags is now an executable target attribute only. +

+
scalac_jvm_flags +

List of strings; optional

+

+ List of JVM flags to be passed to scalac after the + scalacopts. Subject to + Make variable + substitution and + Bourne shell tokenization. +

+
javac_jvm_flags +

List of strings; optional

+

+ List of JVM flags to be passed to javac after the + javacopts. Subject to + Make variable + substitution and + Bourne shell tokenization. +

+
unused_dependency_checker_mode +

String; optional

+

+ Enable unused dependency checking (see Unused dependency checking). + Possible values are: off, warn and error. +

+
diff --git a/scala/advanced_usage/scala.bzl b/scala/advanced_usage/scala.bzl index b632cd0a8..a3a2956bf 100644 --- a/scala/advanced_usage/scala.bzl +++ b/scala/advanced_usage/scala.bzl @@ -13,6 +13,7 @@ load( ) load( "//scala/private:rules/scala_library.bzl", + _make_scala_inlined_library = "make_scala_inlined_library", _make_scala_library = "make_scala_library", _make_scala_library_for_plugin_bootstrapping = "make_scala_library_for_plugin_bootstrapping", _make_scala_macro_library = "make_scala_macro_library", @@ -28,6 +29,7 @@ load( make_scala_binary = _make_scala_binary make_scala_library = _make_scala_library +make_scala_inlined_library = _make_scala_inlined_library make_scala_library_for_plugin_bootstrapping = _make_scala_library_for_plugin_bootstrapping make_scala_macro_library = _make_scala_macro_library make_scala_repl = _make_scala_repl diff --git a/scala/private/phases/phase_compile.bzl b/scala/private/phases/phase_compile.bzl index d923a2663..931e6b401 100644 --- a/scala/private/phases/phase_compile.bzl +++ b/scala/private/phases/phase_compile.bzl @@ -43,6 +43,18 @@ def phase_compile_library(ctx, p): ) return _phase_compile_default(ctx, p, args) +def phase_compile_inlined_library(ctx, p): + args = struct( + buildijar = False, + srcjars = p.collect_srcjars, + unused_dependency_checker_ignored_targets = [ + target.label + for target in p.scalac_provider.default_classpath + ctx.attr.exports + + ctx.attr.unused_dependency_checker_ignored_targets + ], + ) + return _phase_compile_default(ctx, p, args) + def phase_compile_library_for_plugin_bootstrapping(ctx, p): args = struct( buildijar = ctx.attr.build_ijar, diff --git a/scala/private/phases/phases.bzl b/scala/private/phases/phases.bzl index d4f1062dd..3cd92fc50 100644 --- a/scala/private/phases/phases.bzl +++ b/scala/private/phases/phases.bzl @@ -21,6 +21,7 @@ load( "//scala/private:phases/phase_compile.bzl", _phase_compile_binary = "phase_compile_binary", _phase_compile_common = "phase_compile_common", + _phase_compile_inlined_library = "phase_compile_inlined_library", _phase_compile_junit_test = "phase_compile_junit_test", _phase_compile_library = "phase_compile_library", _phase_compile_library_for_plugin_bootstrapping = "phase_compile_library_for_plugin_bootstrapping", @@ -135,6 +136,7 @@ phase_collect_jars_common = _phase_collect_jars_common # compile phase_compile_binary = _phase_compile_binary phase_compile_library = _phase_compile_library +phase_compile_inlined_library = _phase_compile_inlined_library phase_compile_library_for_plugin_bootstrapping = _phase_compile_library_for_plugin_bootstrapping phase_compile_junit_test = _phase_compile_junit_test phase_compile_repl = _phase_compile_repl diff --git a/scala/private/rules/scala_library.bzl b/scala/private/rules/scala_library.bzl index eb2122095..7f17caa6e 100644 --- a/scala/private/rules/scala_library.bzl +++ b/scala/private/rules/scala_library.bzl @@ -24,6 +24,7 @@ load( "phase_collect_jars_common", "phase_collect_jars_macro_library", "phase_collect_srcjars", + "phase_compile_inlined_library", "phase_compile_library", "phase_compile_library_for_plugin_bootstrapping", "phase_coverage_common", @@ -218,6 +219,68 @@ def make_scala_library_for_plugin_bootstrapping(*extras): scala_library_for_plugin_bootstrapping = make_scala_library_for_plugin_bootstrapping() +## +# scala_inlined_library +## + +def _scala_inlined_library_impl(ctx): + # Build up information from dependency-like attributes + return run_phases( + ctx, + # customizable phases + [ + ("scalac_provider", phase_scalac_provider), + ("scalainfo_provider", phase_scalainfo_provider_non_macro), + ("collect_srcjars", phase_collect_srcjars), + ("write_manifest", phase_write_manifest), + ("dependency", phase_dependency_common), + ("collect_jars", phase_collect_jars_common), + ("scalacopts", phase_scalacopts), + ("semanticdb", phase_semanticdb), + ("compile", phase_compile_inlined_library), + ("coverage", phase_coverage_library), + ("merge_jars", phase_merge_jars), + ("runfiles", phase_runfiles_library), + ("collect_exports_jars", phase_collect_exports_jars), + ("default_info", phase_default_info), + ], + ) + +_scala_inlined_library_attrs = {} + +_scala_inlined_library_attrs.update(implicit_deps) + +_scala_inlined_library_attrs.update(common_attrs) + +_scala_inlined_library_attrs.update(_library_attrs) + +_scala_inlined_library_attrs.update(resolve_deps) + +_scala_inlined_library_attrs.update(toolchain_transition_attr) + +def make_scala_inlined_library(*extras): + return rule( + attrs = _dicts.add( + _scala_inlined_library_attrs, + extras_phases(extras), + *[extra["attrs"] for extra in extras if "attrs" in extra] + ), + fragments = ["java"], + outputs = _dicts.add( + common_outputs, + *[extra["outputs"] for extra in extras if "outputs" in extra] + ), + toolchains = [ + "//scala:toolchain_type", + "@bazel_tools//tools/jdk:toolchain_type", + ], + cfg = scala_version_transition, + provides = [JavaInfo], + implementation = _scala_inlined_library_impl, + ) + +scala_inlined_library = make_scala_inlined_library() + ## # scala_macro_library ## diff --git a/scala/scala.bzl b/scala/scala.bzl index 162ff3b60..2f4341b58 100644 --- a/scala/scala.bzl +++ b/scala/scala.bzl @@ -18,6 +18,7 @@ load( ) load( "//scala/private:rules/scala_library.bzl", + _scala_inlined_library = "scala_inlined_library", _scala_library = "scala_library", _scala_library_for_plugin_bootstrapping = "scala_library_for_plugin_bootstrapping", _scala_library_suite = "scala_library_suite", @@ -63,6 +64,7 @@ scala_library = _scala_library scala_library_for_plugin_bootstrapping = _scala_library_for_plugin_bootstrapping scala_library_suite = _scala_library_suite scala_macro_library = _scala_macro_library +scala_inlined_library = _scala_inlined_library scala_repl = _scala_repl scala_test = _scala_test scala_test_suite = _scala_test_suite diff --git a/test/BUILD b/test/BUILD index 08220d003..d55b5b5e1 100644 --- a/test/BUILD +++ b/test/BUILD @@ -6,6 +6,7 @@ load( "//scala:scala.bzl", "scala_binary", "scala_doc", + "scala_inlined_library", "scala_junit_test", "scala_library", "scala_library_suite", @@ -832,3 +833,24 @@ scala_test( srcs = ["ScalaTestResourcesFromLocalTargetTest.scala"], resources = [":py_resource_binary"], ) + +# scala_inlined_library + +# If this target is a scala_library instead, then InlinedExported will fail to compile. +scala_inlined_library( + name = "InlinableExported", + srcs = ["Exported.scala"], + runtime_deps = ["Runtime"], +) + +scala_library( + name = "InlinedExported", + srcs = ["OtherLib.scala"], + scalacopts = [ + "-opt:l:inline", + "-opt-inline-from:scalarules.test.**", + # We need fatal warnings to ensure that the inlining actually worked. + "-Xfatal-warnings", + ], + deps = [":InlinableExported"], +)