Skip to content

Commit 4de48e4

Browse files
committed
scala_inlined_library
Add a new rule to enable compiling scala code, that is not for macro definitions, but would be used in inlining (so ijar support should be disabled for it). You may need strict dependency checks (transitive dependencies not on the classpath) for code that is to be used in inlining. Till now one would need to use scala_macro_library for that, but it was recently switched to include all transitive dependencies on the compiler's classpath, hence strict dependencies are not enforced there. The new rule enables having both: a) code compiled for inlining b) strict dependency checks
1 parent 05ecd67 commit 4de48e4

File tree

9 files changed

+282
-0
lines changed

9 files changed

+282
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This project defines core build rules for [Scala](https://www.scala-lang.org/) t
1919

2020
- [scala_library](./docs/scala_library.md)
2121
- [scala_macro_library](./docs/scala_macro_library.md)
22+
- [scala_inlined_library](./docs/scala_inlined_library.md)
2223
- [scala_binary](./docs/scala_binary.md)
2324
- [scala_test](./docs/scala_test.md)
2425
- [scala_repl](./docs/scala_repl.md)

docs/customizable_phase.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ Currently phase architecture is used by 7 rules:
146146

147147
- scala_library
148148
- scala_macro_library
149+
- scala_inlined_library
149150
- scala_library_for_plugin_bootstrapping
150151
- scala_binary
151152
- scala_test

docs/scala_inline_library.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# scala_inlined_library
2+
3+
```py
4+
scala_inlined_library(
5+
name,
6+
srcs,
7+
deps,
8+
runtime_deps,
9+
exports,
10+
data,
11+
main_class,
12+
resources,
13+
resource_strip_prefix,
14+
scalacopts,
15+
jvm_flags,
16+
scalac_jvm_flags,
17+
javac_jvm_flags,
18+
unused_dependency_checker_mode
19+
)
20+
```
21+
22+
`scala_inlined_library` generates a `.jar` file from `.scala` source files. This rule
23+
has the interface jar (`ijar`) functionality disabled.
24+
This is to enable inlining the compiled code, when it is given as a dependency for another Scala target (`ijar`
25+
does not contain an implementation, so it cannot be used for inlining).
26+
27+
In order to have a Java rule use this jar file, use the `java_import` rule.
28+
29+
<table class="table table-condensed table-bordered table-params">
30+
<colgroup>
31+
<col class="col-param" />
32+
<col class="param-description" />
33+
</colgroup>
34+
<thead>
35+
<tr>
36+
<th colspan="2">Attributes</th>
37+
</tr>
38+
</thead>
39+
<tbody>
40+
<tr>
41+
<td><code>name</code></td>
42+
<td>
43+
<p><code>Name, required</code></p>
44+
<p>A unique name for this target</p>
45+
</td>
46+
</tr>
47+
<td><code>srcs</code></td>
48+
<td>
49+
<p><code>List of labels, required</code></p>
50+
<p>List of Scala <code>.scala</code> source files used to build the
51+
library. These may be .srcjar jar files that contain source code.</p>
52+
</td>
53+
</tr>
54+
<tr>
55+
<td><code>deps</code></td>
56+
<td>
57+
<p><code>List of labels, optional</code></p>
58+
<p>List of other libraries to linked to this library target.
59+
These must be jvm targets (scala_library, java_library, java_import, etc...)</p>
60+
</td>
61+
</tr>
62+
<tr>
63+
<td><code>runtime_deps</code></td>
64+
<td>
65+
<p><code>List of labels, optional</code></p>
66+
<p>List of other libraries to put on the classpath only at runtime. This is rarely needed in Scala.
67+
These must be jvm targets (scala_library, java_library, java_import, etc...)</p>
68+
</td>
69+
</tr>
70+
<tr>
71+
<td><code>exports</code></td>
72+
<td>
73+
<p><code>List of labels, optional</code></p>
74+
<p>List of targets to add to the dependencies of those that depend on this target. Similar
75+
to the `java_library` parameter of the same name. Use this sparingly as it weakens the
76+
precision of the build graph.
77+
These must be jvm targets (scala_library, java_library, java_import, etc...)</p>
78+
</td>
79+
</tr>
80+
<tr>
81+
<td><code>data</code></td>
82+
<td>
83+
<p><code>List of labels, optional</code></p>
84+
<p>List of files needed by this rule at runtime.</p>
85+
</td>
86+
</tr>
87+
<tr>
88+
<td><code>main_class</code></td>
89+
<td>
90+
<p><code>String, optional</code></p>
91+
<p>Name of class with main() method to use as an entry point</p>
92+
<p>
93+
The value of this attribute is a class name, not a source file. The
94+
class must be available at runtime: it may be compiled by this rule
95+
(from <code>srcs</code>) or provided by direct or transitive
96+
dependencies (through <code>deps</code>). If the class is unavailable,
97+
the binary will fail at runtime; there is no build-time check.
98+
</p>
99+
</td>
100+
</tr>
101+
<tr>
102+
<td><code>resources</code></td>
103+
<td>
104+
<p><code>List of labels; optional</code></p>
105+
<p>A list of data files to be included in the JAR.</p>
106+
</td>
107+
</tr>
108+
<tr>
109+
<td><code>resource_strip_prefix</code></td>
110+
<td>
111+
<p><code>String; optional</code></p>
112+
<p>
113+
The path prefix to strip from Java resources. If specified,
114+
this path prefix is stripped from every file in the `resources` attribute.
115+
It is an error for a resource file not to be under this directory.
116+
</p>
117+
</td>
118+
</tr>
119+
<tr>
120+
<td><code>scalacopts</code></td>
121+
<td>
122+
<p><code>List of strings; optional</code></p>
123+
<p>
124+
Extra compiler options for this library to be passed to scalac. Subject to
125+
<a href="https://bazel.build/reference/be/make-variables.html">Make variable
126+
substitution</a> and
127+
<a href="https://bazel.build/reference/be/common-definitions.html#sh-tokenization">Bourne shell tokenization.</a>
128+
</p>
129+
</td>
130+
</tr>
131+
<tr>
132+
<td><code>jvm_flags</code></td>
133+
<td>
134+
<p><code>List of strings; optional; deprecated</code></p>
135+
<p>
136+
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.
137+
</p>
138+
</td>
139+
</tr>
140+
<tr>
141+
<td><code>scalac_jvm_flags</code></td>
142+
<td>
143+
<p><code>List of strings; optional</code></p>
144+
<p>
145+
List of JVM flags to be passed to scalac after the
146+
<code>scalacopts</code>. Subject to
147+
<a href="https://bazel.build/reference/be/make-variables.html">Make variable
148+
substitution</a> and
149+
<a href="https://bazel.build/reference/be/common-definitions.html#sh-tokenization">Bourne shell tokenization.</a>
150+
</p>
151+
</td>
152+
</tr>
153+
<tr>
154+
<td><code>javac_jvm_flags</code></td>
155+
<td>
156+
<p><code>List of strings; optional</code></p>
157+
<p>
158+
List of JVM flags to be passed to javac after the
159+
<code>javacopts</code>. Subject to
160+
<a href="https://bazel.build/reference/be/make-variables.html">Make variable
161+
substitution</a> and
162+
<a href="https://bazel.build/reference/be/common-definitions.html#sh-tokenization">Bourne shell tokenization.</a>
163+
</p>
164+
</td>
165+
</tr>
166+
<tr>
167+
<td><code>unused_dependency_checker_mode</code></td>
168+
<td>
169+
<p><code>String; optional</code></p>
170+
<p>
171+
Enable unused dependency checking (see <a href="https://github.com/bazelbuild/rules_scala#experimental-unused-dependency-checking">Unused dependency checking</a>).
172+
Possible values are: <code>off</code>, <code>warn</code> and <code>error</code>.
173+
</p>
174+
</td>
175+
</tr>
176+
</tbody>
177+
</table>

scala/advanced_usage/scala.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ load(
1313
)
1414
load(
1515
"//scala/private:rules/scala_library.bzl",
16+
_make_scala_inlined_library = "make_scala_inlined_library",
1617
_make_scala_library = "make_scala_library",
1718
_make_scala_library_for_plugin_bootstrapping = "make_scala_library_for_plugin_bootstrapping",
1819
_make_scala_macro_library = "make_scala_macro_library",
@@ -28,6 +29,7 @@ load(
2829

2930
make_scala_binary = _make_scala_binary
3031
make_scala_library = _make_scala_library
32+
make_scala_inlined_library = _make_scala_inlined_library
3133
make_scala_library_for_plugin_bootstrapping = _make_scala_library_for_plugin_bootstrapping
3234
make_scala_macro_library = _make_scala_macro_library
3335
make_scala_repl = _make_scala_repl

scala/private/phases/phase_compile.bzl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ def phase_compile_library(ctx, p):
4343
)
4444
return _phase_compile_default(ctx, p, args)
4545

46+
def phase_compile_inlined_library(ctx, p):
47+
args = struct(
48+
buildijar = False,
49+
srcjars = p.collect_srcjars,
50+
unused_dependency_checker_ignored_targets = [
51+
target.label
52+
for target in p.scalac_provider.default_classpath + ctx.attr.exports +
53+
ctx.attr.unused_dependency_checker_ignored_targets
54+
],
55+
)
56+
return _phase_compile_default(ctx, p, args)
57+
4658
def phase_compile_library_for_plugin_bootstrapping(ctx, p):
4759
args = struct(
4860
buildijar = ctx.attr.build_ijar,

scala/private/phases/phases.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ load(
2121
"//scala/private:phases/phase_compile.bzl",
2222
_phase_compile_binary = "phase_compile_binary",
2323
_phase_compile_common = "phase_compile_common",
24+
_phase_compile_inlined_library = "phase_compile_inlined_library",
2425
_phase_compile_junit_test = "phase_compile_junit_test",
2526
_phase_compile_library = "phase_compile_library",
2627
_phase_compile_library_for_plugin_bootstrapping = "phase_compile_library_for_plugin_bootstrapping",
@@ -135,6 +136,7 @@ phase_collect_jars_common = _phase_collect_jars_common
135136
# compile
136137
phase_compile_binary = _phase_compile_binary
137138
phase_compile_library = _phase_compile_library
139+
phase_compile_inlined_library = _phase_compile_inlined_library
138140
phase_compile_library_for_plugin_bootstrapping = _phase_compile_library_for_plugin_bootstrapping
139141
phase_compile_junit_test = _phase_compile_junit_test
140142
phase_compile_repl = _phase_compile_repl

scala/private/rules/scala_library.bzl

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ load(
2424
"phase_collect_jars_common",
2525
"phase_collect_jars_macro_library",
2626
"phase_collect_srcjars",
27+
"phase_compile_inlined_library",
2728
"phase_compile_library",
2829
"phase_compile_library_for_plugin_bootstrapping",
2930
"phase_coverage_common",
@@ -218,6 +219,68 @@ def make_scala_library_for_plugin_bootstrapping(*extras):
218219

219220
scala_library_for_plugin_bootstrapping = make_scala_library_for_plugin_bootstrapping()
220221

222+
##
223+
# scala_inlined_library
224+
##
225+
226+
def _scala_inlined_library_impl(ctx):
227+
# Build up information from dependency-like attributes
228+
return run_phases(
229+
ctx,
230+
# customizable phases
231+
[
232+
("scalac_provider", phase_scalac_provider),
233+
("scalainfo_provider", phase_scalainfo_provider_non_macro),
234+
("collect_srcjars", phase_collect_srcjars),
235+
("write_manifest", phase_write_manifest),
236+
("dependency", phase_dependency_common),
237+
("collect_jars", phase_collect_jars_common),
238+
("scalacopts", phase_scalacopts),
239+
("semanticdb", phase_semanticdb),
240+
("compile", phase_compile_inlined_library),
241+
("coverage", phase_coverage_library),
242+
("merge_jars", phase_merge_jars),
243+
("runfiles", phase_runfiles_library),
244+
("collect_exports_jars", phase_collect_exports_jars),
245+
("default_info", phase_default_info),
246+
],
247+
)
248+
249+
_scala_inlined_library_attrs = {}
250+
251+
_scala_inlined_library_attrs.update(implicit_deps)
252+
253+
_scala_inlined_library_attrs.update(common_attrs)
254+
255+
_scala_inlined_library_attrs.update(_library_attrs)
256+
257+
_scala_inlined_library_attrs.update(resolve_deps)
258+
259+
_scala_inlined_library_attrs.update(toolchain_transition_attr)
260+
261+
def make_scala_inlined_library(*extras):
262+
return rule(
263+
attrs = _dicts.add(
264+
_scala_inlined_library_attrs,
265+
extras_phases(extras),
266+
*[extra["attrs"] for extra in extras if "attrs" in extra]
267+
),
268+
fragments = ["java"],
269+
outputs = _dicts.add(
270+
common_outputs,
271+
*[extra["outputs"] for extra in extras if "outputs" in extra]
272+
),
273+
toolchains = [
274+
"//scala:toolchain_type",
275+
"@bazel_tools//tools/jdk:toolchain_type",
276+
],
277+
cfg = scala_version_transition,
278+
provides = [JavaInfo],
279+
implementation = _scala_inlined_library_impl,
280+
)
281+
282+
scala_inlined_library = make_scala_inlined_library()
283+
221284
##
222285
# scala_macro_library
223286
##

scala/scala.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ load(
1818
)
1919
load(
2020
"//scala/private:rules/scala_library.bzl",
21+
_scala_inlined_library = "scala_inlined_library",
2122
_scala_library = "scala_library",
2223
_scala_library_for_plugin_bootstrapping = "scala_library_for_plugin_bootstrapping",
2324
_scala_library_suite = "scala_library_suite",
@@ -63,6 +64,7 @@ scala_library = _scala_library
6364
scala_library_for_plugin_bootstrapping = _scala_library_for_plugin_bootstrapping
6465
scala_library_suite = _scala_library_suite
6566
scala_macro_library = _scala_macro_library
67+
scala_inlined_library = _scala_inlined_library
6668
scala_repl = _scala_repl
6769
scala_test = _scala_test
6870
scala_test_suite = _scala_test_suite

test/BUILD

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ load(
66
"//scala:scala.bzl",
77
"scala_binary",
88
"scala_doc",
9+
"scala_inlined_library",
910
"scala_junit_test",
1011
"scala_library",
1112
"scala_library_suite",
@@ -832,3 +833,24 @@ scala_test(
832833
srcs = ["ScalaTestResourcesFromLocalTargetTest.scala"],
833834
resources = [":py_resource_binary"],
834835
)
836+
837+
# scala_inlined_library
838+
839+
# If this target is a scala_library instead, then InlinedExported will fail to compile.
840+
scala_inlined_library(
841+
name = "InlinableExported",
842+
srcs = ["Exported.scala"],
843+
runtime_deps = ["Runtime"],
844+
)
845+
846+
scala_library(
847+
name = "InlinedExported",
848+
srcs = ["OtherLib.scala"],
849+
scalacopts = [
850+
"-opt:l:inline",
851+
"-opt-inline-from:scalarules.test.**",
852+
# We need fatal warnings to ensure that the inlining actually worked.
853+
"-Xfatal-warnings",
854+
],
855+
deps = [":InlinableExported"],
856+
)

0 commit comments

Comments
 (0)