Skip to content

Commit 043ba58

Browse files
jhnjittaiz
authored andcommitted
Support for selecting scala version (#544)
* WIP compile using worker supplied from provider * Provider[ScalaWorker] contains (will contain) everything needed to run a specific version of the scala compiler * Manually create ScalaWorker for 2.11/2.12 * Add scalareflect + scalacompiler to [ScalaWorker] * Run scala_repl using compiler from [ScalaWorker] * All rules using [ScalaWorker] * run scala_binary, scala_macro_library, scala_test, scala_junit_test using [ScalaWorker] * Tests now working with 2.12 * Create [ScalaWorker] using new_scala_repository * Generate build file for scalac_2_12 in repository_rule * Use filegroup for scalac worker files * Specify scala version and label in new_scala_repository * Download scala version specified as parameter * Set label for ScalaWorker as @{name}//:{name} * Run formatter * Run scalatest for both 2.11/2.12 * Add initial [ScalaWorker] for both 2.11/2.12 * import scalatest + scalactic for 2.12 * Add 2.12 versions of scalatest_runner and scalatest_reporter * Manually specify scalatest_reporter for scala_test rule * Update scalatest to 3.0.5 + remove defaults from ScalaWorker - rename scalac -> scalac_2_11 * Symlink scalac_worker sources to repo_rule workspace * Resolve scalatest_reporter version in rule - Pass both 2.11/2.12 versions as implicit attrs - Add "major_version" to [ScalaWorker] * Use new_scala_repository for default 2.11/2.12 * scala_repositories takes scala versions as parameters * improve naming * Use single scala version * Fix runfiles not being generated * Support multiple scala versions for tut and scrooge * Format .bzl and BUILD files * Tests passing with 2.11 * Make scala_proto work with 2.12 * Support specs2 for both 2.11/2.12 - remove unused attr major_version from ScalacProvider * Don't pass scalatest dependencies through provider * Pass _scalac through _implicit_deps * Remove temp test directory * Remove debugging println * Cleanup * Run formatter * Use inputs from resolve_command * Combine scalatest+scalactic to single target * Add utils - extract_major_version_underscore() - default_scala_version() - run formatter * Increase scala_mvn_artifact usage, add shas * Add default_major_scala_version() * Add scala_jar_shas dict - Specify only one version of scalatest/scalactic... getting the shas from scala_jar_shas * Fix aspect test * Use scala_maven_import_external for all imports specs2, tut, scrooge, protob * Add util_core to scrooge, fix aspect test * Supply shas to scala_library,compiler and reflect - User can add shas for custom scala versions - run formatter * namespace scala_default * Scala default version to 2.11.12 - correct spelling error * Lookup scala_extra_jar_shas[major_version] once, renaming * tut server_urls as parameter * Pass ScalacProvider as paramater * Replace pass classpaths instead of jars - Stop using ScalacProvider.scala_library etc. - Use ScalacProvider.default_compile_classpath etc. * linting * Lookup scala_jar_shas[major_version] only once * Run version specific tests in their own workspace - Copy version_specific_test_dir to its own folder - Add WORKSPACE file with scala version to be tested - Removed tests that don't need to be run for multiple versions * remove more non version-specific tests * Remove version from scala labels fix tests - Add deps required for third_party and tut tests * Use default_runtime_classpath for macros, fix aspect test * Run more tests in test_version.sh * Update naming, default_compile_classpath -> base_compile_classpath * Use base_classpath instead of base_compile.. + base_runtime... Using different base classpaths for compile/runtime requires changes in common.bzl: collect_jars() Use the same base_classpath for both to limit the scope of this PR * Add scala_reflect to default_classpath * scala_version and shas as on tuple paramter - Combine two parameters into one tuple to force the user the specify shas * Reduce amount of version specific junit tests * Run version specific tests * Run linter * Remove dynamic creation of scala_default ScalacProvider - Avoid having to symlink java sources for scalac_worker - Allows us to only have one scala version at a time * PR comments, clearer naming * Use ctx.attr._scala_provider instead of ..attr.scalalib, run linter * Address comments, clean up WORKSPACE.template * Remove unused code * Add section about different scala versions to the readme
1 parent 329543d commit 043ba58

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+2000
-237
lines changed

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,25 @@ test --strategy=Scalac=worker
6161
```
6262
to your command line, or to enable by default for building/testing add it to your .bazelrc.
6363

64+
## Selecting Scala version
65+
66+
Rules scala supports all minor versions of Scala 2.11/2.12. By default `Scala 2.11.12` is used and to use another
67+
version you need to
68+
specify it when calling `scala_repositories`. `scala_repositories` takes a tuple `(scala_version, scala_version_jar_shas)`
69+
as a parameter where `scala_version` is the scala version and `scala_version_jar_shas` is a `dict` with
70+
`sha256` hashes for the maven artifacts `scala_library`, `scala_reflect` and `scala_compiler`:
71+
```python
72+
scala_repositories(("2.12.6", {
73+
"scala_compiler": "3e892546b72ab547cb77de4d840bcfd05c853e73390fed7370a8f19acb0735a0",
74+
"scala_library": "0b3d6fd42958ee98715ba2ec5fe221f4ca1e694d7c981b0ae0cd68e97baf6dce",
75+
"scala_reflect": "6ba385b450a6311a15c918cf8688b9af9327c6104f0ecbd35933cfcd3095fe04"
76+
}))
77+
```
78+
If you're using any of the rules `twitter_scrooge`, `tut_repositories`, `scala_proto_repositories`
79+
or `specs2_junit_repositories` you also need to specify `scala_version` for them. See `./test_version/WORKSPACE.template`
80+
for an example workspace using another scala version.
81+
82+
6483
## Bazel compatible versions
6584

6685
| bazel | rules_scala gitsha |

WORKSPACE

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,35 @@ load("//specs2:specs2_junit.bzl", "specs2_junit_repositories")
2424

2525
specs2_junit_repositories()
2626

27-
load("//scala:scala_cross_version.bzl", "scala_mvn_artifact")
27+
load("//scala:scala_cross_version.bzl", "scala_mvn_artifact", "default_scala_major_version")
2828

2929
# test adding a scala jar:
3030
maven_jar(
3131
name = "com_twitter__scalding_date",
32-
artifact = scala_mvn_artifact("com.twitter:scalding-date:0.17.0"),
32+
artifact = scala_mvn_artifact(
33+
"com.twitter:scalding-date:0.17.0",
34+
default_scala_major_version(),
35+
),
3336
sha1 = "420fb0c4f737a24b851c4316ee0362095710caa5",
3437
)
3538

3639
# For testing that we don't include sources jars to the classpath
3740
maven_jar(
3841
name = "org_typelevel__cats_core",
39-
artifact = scala_mvn_artifact("org.typelevel:cats-core:0.9.0"),
42+
artifact = scala_mvn_artifact(
43+
"org.typelevel:cats-core:0.9.0",
44+
default_scala_major_version(),
45+
),
4046
sha1 = "b2f8629c6ec834d8b6321288c9fe77823f1e1314",
4147
)
4248

4349
# test of a plugin
4450
maven_jar(
4551
name = "org_psywerx_hairyfotr__linter",
46-
artifact = scala_mvn_artifact("org.psywerx.hairyfotr:linter:0.1.13"),
52+
artifact = scala_mvn_artifact(
53+
"org.psywerx.hairyfotr:linter:0.1.13",
54+
default_scala_major_version(),
55+
),
4756
sha1 = "e5b3e2753d0817b622c32aedcb888bcf39e275b4",
4857
)
4958

scala/BUILD

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
load(
2+
"@io_bazel_rules_scala//scala:providers.bzl",
3+
_declare_scalac_provider = "declare_scalac_provider",
4+
)
15
load("//scala:scala_toolchain.bzl", "scala_toolchain")
26

37
toolchain_type(
@@ -23,3 +27,22 @@ java_import(
2327
jars = ["@bazel_tools//tools/jdk:TestRunner_deploy.jar"],
2428
visibility = ["//visibility:public"],
2529
)
30+
31+
_declare_scalac_provider(
32+
name = "scala_default",
33+
default_classpath = [
34+
"@io_bazel_rules_scala_scala_library",
35+
"@io_bazel_rules_scala_scala_reflect",
36+
],
37+
default_macro_classpath = [
38+
"@io_bazel_rules_scala_scala_library",
39+
"@io_bazel_rules_scala_scala_reflect",
40+
],
41+
default_repl_classpath = [
42+
"@io_bazel_rules_scala_scala_library",
43+
"@io_bazel_rules_scala_scala_reflect",
44+
"@io_bazel_rules_scala_scala_compiler",
45+
],
46+
scalac = "@io_bazel_rules_scala//src/java/io/bazel/rulesscala/scalac",
47+
visibility = ["//visibility:public"],
48+
)

scala/private/rule_impls.bzl

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313
# limitations under the License.
1414
"""Rules for supporting the Scala language."""
1515
load("@io_bazel_rules_scala//scala:scala_toolchain.bzl", "scala_toolchain")
16-
load("@io_bazel_rules_scala//scala:providers.bzl", "create_scala_provider")
16+
load(
17+
"@io_bazel_rules_scala//scala:providers.bzl",
18+
"create_scala_provider",
19+
_ScalacProvider = "ScalacProvider")
1720
load(
1821
":common.bzl",
1922
"add_labels_of_jars_to",
@@ -132,7 +135,7 @@ def compile_scala(ctx, target_label, output, manifest, statsfile, sources,
132135
cjars, all_srcjars, transitive_compile_jars, plugins,
133136
resource_strip_prefix, resources, resource_jars, labels,
134137
in_scalacopts, print_compile_time, expect_java_output,
135-
scalac_jvm_flags):
138+
scalac_jvm_flags, scalac_provider):
136139
# look for any plugins:
137140
plugins = _collect_plugin_paths(plugins)
138141
dependency_analyzer_plugin_jars = []
@@ -223,15 +226,20 @@ StatsfileOutput: {statsfile_output}
223226
ctx.actions.write(
224227
output = argfile, content = scalac_args + optional_scalac_args)
225228

229+
scalac_inputs, _, scalac_input_manifests = ctx.resolve_command(
230+
tools = [scalac_provider.scalac])
231+
226232
outs = [output, statsfile]
227-
ins = (compiler_classpath_jars.to_list() + all_srcjars.to_list() +
228-
list(sources) + plugins_list + dependency_analyzer_plugin_jars +
229-
classpath_resources + resources + resource_jars + [manifest, argfile])
233+
ins = (
234+
compiler_classpath_jars.to_list() + all_srcjars.to_list() + list(sources)
235+
+ plugins_list + dependency_analyzer_plugin_jars + classpath_resources +
236+
resources + resource_jars + [manifest, argfile] + scalac_inputs)
230237

231238
ctx.actions.run(
232239
inputs = ins,
233240
outputs = outs,
234-
executable = ctx.executable._scalac,
241+
executable = scalac_provider.scalac.files_to_run.executable,
242+
input_manifests = scalac_input_manifests,
235243
mnemonic = "Scalac",
236244
progress_message = "scala %s" % target_label,
237245
execution_requirements = {"supports-workers": "1"},
@@ -263,7 +271,8 @@ def try_to_compile_java_jar(ctx, scala_output, all_srcjars, java_srcs,
263271
providers_of_dependencies = collect_java_providers_of(ctx.attr.deps)
264272
providers_of_dependencies += collect_java_providers_of(
265273
implicit_junit_deps_needed_for_java_compilation)
266-
providers_of_dependencies += collect_java_providers_of([ctx.attr._scalalib])
274+
providers_of_dependencies += collect_java_providers_of(
275+
ctx.attr._scala_provider[_ScalacProvider].default_classpath)
267276
scala_sources_java_provider = _interim_java_provider_for_java_compilation(
268277
scala_output)
269278
providers_of_dependencies += [scala_sources_java_provider]
@@ -323,13 +332,13 @@ def _compile_or_empty(ctx, manifest, jars, srcjars, buildijar,
323332
sources = [
324333
f for f in ctx.files.srcs if f.basename.endswith(_scala_extension)
325334
] + java_srcs
326-
compile_scala(ctx, ctx.label, ctx.outputs.jar, manifest,
327-
ctx.outputs.statsfile, sources, jars, all_srcjars,
328-
transitive_compile_jars, ctx.attr.plugins,
329-
ctx.attr.resource_strip_prefix, ctx.files.resources,
330-
ctx.files.resource_jars, jars2labels, ctx.attr.scalacopts,
331-
ctx.attr.print_compile_time, ctx.attr.expect_java_output,
332-
ctx.attr.scalac_jvm_flags)
335+
compile_scala(
336+
ctx, ctx.label, ctx.outputs.jar, manifest, ctx.outputs.statsfile,
337+
sources, jars, all_srcjars, transitive_compile_jars, ctx.attr.plugins,
338+
ctx.attr.resource_strip_prefix, ctx.files.resources,
339+
ctx.files.resource_jars, jars2labels, ctx.attr.scalacopts,
340+
ctx.attr.print_compile_time, ctx.attr.expect_java_output,
341+
ctx.attr.scalac_jvm_flags, ctx.attr._scala_provider[_ScalacProvider])
333342

334343
# build ijar if needed
335344
if buildijar:
@@ -474,15 +483,16 @@ def is_dependency_analyzer_off(ctx):
474483
# Extract very common code out from dependency analysis into single place
475484
# automatically adds dependency on scala-library and scala-reflect
476485
# collects jars from deps, runtime jars from runtime_deps, and
477-
def _collect_jars_from_common_ctx(ctx, extra_deps = [],
486+
def _collect_jars_from_common_ctx(ctx,
487+
base_classpath,
488+
extra_deps = [],
478489
extra_runtime_deps = []):
479490

480491
dependency_analyzer_is_off = is_dependency_analyzer_off(ctx)
481492

482-
# Get jars from deps
483-
auto_deps = [ctx.attr._scalalib, ctx.attr._scalareflect]
484-
deps_jars = collect_jars(ctx.attr.deps + auto_deps + extra_deps,
493+
deps_jars = collect_jars(ctx.attr.deps + extra_deps + base_classpath,
485494
dependency_analyzer_is_off)
495+
486496
(cjars, transitive_rjars, jars2labels,
487497
transitive_compile_jars) = (deps_jars.compile_jars,
488498
deps_jars.transitive_runtime_jars,
@@ -499,13 +509,14 @@ def _collect_jars_from_common_ctx(ctx, extra_deps = [],
499509
jars2labels = jars2labels,
500510
transitive_compile_jars = transitive_compile_jars)
501511

502-
def _lib(ctx, non_macro_lib):
512+
def _lib(ctx, base_classpath, non_macro_lib):
503513
# Build up information from dependency-like attributes
504514

505515
# This will be used to pick up srcjars from non-scala library
506516
# targets (like thrift code generation)
507517
srcjars = collect_srcjars(ctx.attr.deps)
508-
jars = _collect_jars_from_common_ctx(ctx)
518+
519+
jars = _collect_jars_from_common_ctx(ctx, base_classpath)
509520
(cjars, transitive_rjars) = (jars.compile_jars, jars.transitive_runtime_jars)
510521

511522
write_manifest(ctx)
@@ -551,10 +562,13 @@ def _lib(ctx, non_macro_lib):
551562
)
552563

553564
def scala_library_impl(ctx):
554-
return _lib(ctx, True)
565+
scalac_provider = ctx.attr._scala_provider[_ScalacProvider]
566+
return _lib(ctx, scalac_provider.default_classpath, True)
555567

556568
def scala_macro_library_impl(ctx):
557-
return _lib(ctx, False) # don't build the ijar for macros
569+
scalac_provider = ctx.attr._scala_provider[_ScalacProvider]
570+
return _lib(ctx, scalac_provider.default_macro_classpath,
571+
False) # don't build the ijar for macros
558572

559573
# Common code shared by all scala binary implementations.
560574
def _scala_binary_common(ctx,
@@ -600,7 +614,8 @@ def _scala_binary_common(ctx,
600614
runfiles = runfiles)
601615

602616
def scala_binary_impl(ctx):
603-
jars = _collect_jars_from_common_ctx(ctx)
617+
scalac_provider = ctx.attr._scala_provider[_ScalacProvider]
618+
jars = _collect_jars_from_common_ctx(ctx, scalac_provider.default_classpath)
604619
(cjars, transitive_rjars) = (jars.compile_jars, jars.transitive_runtime_jars)
605620

606621
wrapper = _write_java_wrapper(ctx, "", "")
@@ -616,9 +631,12 @@ def scala_binary_impl(ctx):
616631
return out
617632

618633
def scala_repl_impl(ctx):
634+
scalac_provider = ctx.attr._scala_provider[_ScalacProvider]
619635
# need scala-compiler for MainGenericRunner below
620636
jars = _collect_jars_from_common_ctx(
621-
ctx, extra_runtime_deps = [ctx.attr._scalacompiler])
637+
ctx,
638+
scalac_provider.default_repl_classpath,
639+
)
622640
(cjars, transitive_rjars) = (jars.compile_jars, jars.transitive_runtime_jars)
623641

624642
args = " ".join(ctx.attr.scalacopts)
@@ -666,8 +684,11 @@ def _scala_test_flags(ctx):
666684
def scala_test_impl(ctx):
667685
if len(ctx.attr.suites) != 0:
668686
print("suites attribute is deprecated. All scalatest test suites are run")
687+
688+
scalac_provider = ctx.attr._scala_provider[_ScalacProvider]
669689
jars = _collect_jars_from_common_ctx(
670690
ctx,
691+
scalac_provider.default_classpath,
671692
extra_runtime_deps = [
672693
ctx.attr._scalatest_reporter, ctx.attr._scalatest_runner
673694
],
@@ -731,8 +752,10 @@ def scala_junit_test_impl(ctx):
731752
fail(
732753
"Setting at least one of the attributes ('prefixes','suffixes') is required"
733754
)
755+
scalac_provider = ctx.attr._scala_provider[_ScalacProvider]
734756
jars = _collect_jars_from_common_ctx(
735757
ctx,
758+
scalac_provider.default_classpath,
736759
extra_deps = [
737760
ctx.attr._junit, ctx.attr._hamcrest, ctx.attr.suite_label,
738761
ctx.attr._bazel_test_runner

scala/providers.bzl

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,35 @@ def create_scala_provider(ijar, class_jar, compile_jars,
2424
transitive_runtime_jars = transitive_runtime_jars,
2525
transitive_exports = [] #needed by intellij plugin
2626
)
27+
28+
ScalacProvider = provider(
29+
doc = "ScalaProvider",
30+
fields = [
31+
"scalac",
32+
"default_classpath",
33+
"default_macro_classpath",
34+
"default_repl_classpath",
35+
])
36+
37+
def _declare_scalac_provider(ctx):
38+
return [
39+
ScalacProvider(
40+
scalac = ctx.attr.scalac,
41+
default_classpath = ctx.attr.default_classpath,
42+
default_repl_classpath = ctx.attr.default_repl_classpath,
43+
default_macro_classpath = ctx.attr.default_macro_classpath,
44+
)
45+
]
46+
47+
declare_scalac_provider = rule(
48+
implementation = _declare_scalac_provider,
49+
attrs = {
50+
"scalac": attr.label(
51+
executable = True,
52+
cfg = "host",
53+
allow_files = True,
54+
mandatory = True),
55+
"default_classpath": attr.label_list(allow_files = True),
56+
"default_repl_classpath": attr.label_list(allow_files = True),
57+
"default_macro_classpath": attr.label_list(allow_files = True),
58+
})

0 commit comments

Comments
 (0)