Skip to content

Commit

Permalink
Windows support - scala_test (#718)
Browse files Browse the repository at this point in the history
* Fix scala_test rule for Windows

* Fix scala_test rule for Windows - fixes too long paths issue

* Fix scala_test rule for Windows - fixes jar.exe rlocation issue

* Fix scala_test rule for Windows - fixes slash/backslash issue in scalac processor

* Fix ScalacProcessor tmp cleanup on Windows

* Fix too long classpath issue on Windows

* Add native windows launcher

* Fix UnusedDependencyChecker Windows issue

* Fix scrooge_support problems on Windows

* Windows CI - #683

* Windows support - code review fixes
  • Loading branch information
majcherm-da authored and johnynek committed May 8, 2019
1 parent b5daa06 commit 78104d8
Show file tree
Hide file tree
Showing 17 changed files with 529 additions and 49 deletions.
9 changes: 4 additions & 5 deletions .bazelrc.travis
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
# This is from Bazel's former travis setup, to avoid blowing up the RAM usage.
startup --host_jvm_args=-Xmx2500m
startup --host_jvm_args=-Xms2500m
startup --host_jvm_args=-Xmx3072m
startup --host_jvm_args=-Xms1024m
# startup --batch # we actually start many bazels in the test script, we don't want batch
test --ram_utilization_factor=10

# Just making sure that we don't OOM with parallel builds
build --local_resources 2048,.5,1.0
build --local_resources 3072,.5,1.0

# This is so we understand failures better
build --verbose_failures
Expand All @@ -17,7 +16,7 @@ build --verbose_failures
# runs stuff in a container, and since Travis already runs its script
# in a container (unless you require sudo in your .travis.yml) this
# fails to run tests.
build --strategy=Scalac=worker --strategy=ScroogeRule=worker --worker_max_instances=3
build --strategy=Scalac=worker --strategy=ScroogeRule=worker --worker_max_instances=2
#test --test_strategy=standalone

# Below this line, .travis.yml will cat the default bazelrc.
Expand Down
58 changes: 37 additions & 21 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ sudo: required
# xcode8 has jdk8
osx_image: xcode8
# Not technically required but suppresses 'Ruby' in Job status message.
language: java
language: sh

cache:
directories:
Expand All @@ -13,38 +13,54 @@ cache:
os:
- linux
- osx
- windows

env:
# Linting is broken. Disable until fixed.
# See https://github.com/bazelbuild/rules_scala/pull/622
# we want to test the last release
#- V=0.16.1 TEST_SCRIPT=test_lint.sh
- V=0.23.1 TEST_SCRIPT=test_rules_scala.sh
- V=0.23.1 TEST_SCRIPT=test_rules_scala
#- V=0.14.1 TEST_SCRIPT=test_intellij_aspect.sh
- V=0.23.1 TEST_SCRIPT=test_reproducibility.sh
- V=0.23.1 TEST_SCRIPT=test_reproducibility


before_install:
- |
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
OS=darwin
else
sysctl kernel.unprivileged_userns_clone=1
sudo apt-get update -q
sudo apt-get install libxml2-utils -y
OS=linux
fi
if [[ $V =~ .*rc[0-9]+.* ]]; then
PRE_RC=$(expr "$V" : '\([0-9.]*\)rc.*')
RC_PRC=$(expr "$V" : '[0-9.]*\(rc.*\)')
URL="https://storage.googleapis.com/bazel/${PRE_RC}/${RC_PRC}/bazel-${V}-installer-${OS}-x86_64.sh"
if [[ "${TRAVIS_OS_NAME}" == "windows" ]]; then
choco install jdk8 -params 'installdir=c:\\java8'
choco install bazel --version ${V}
else
URL="https://github.com/bazelbuild/bazel/releases/download/${V}/bazel-${V}-installer-${OS}-x86_64.sh"
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
OS=darwin
else
sudo sysctl kernel.unprivileged_userns_clone=1
sudo add-apt-repository -y ppa:openjdk-r/ppa
sudo apt-get update -q
sudo apt-get install openjdk-8-jdk -y
sudo apt-get install libxml2-utils -y
OS=linux
fi
if [[ $V =~ .*rc[0-9]+.* ]]; then
PRE_RC=$(expr "$V" : '\([0-9.]*\)rc.*')
RC_PRC=$(expr "$V" : '[0-9.]*\(rc.*\)')
URL="https://storage.googleapis.com/bazel/${PRE_RC}/${RC_PRC}/bazel-${V}-installer-${OS}-x86_64.sh"
else
URL="https://github.com/bazelbuild/bazel/releases/download/${V}/bazel-${V}-installer-${OS}-x86_64.sh"
fi
wget -O install.sh "${URL}"
chmod +x install.sh
./install.sh --user
rm -f install.sh
fi
wget -O install.sh "${URL}"
chmod +x install.sh
./install.sh --user
rm -f install.sh
- cat .bazelrc.travis >> .bazelrc

script:
- bash $TEST_SCRIPT ci
- |
if [[ "${TRAVIS_OS_NAME}" == "windows" ]]; then
powershell -Command 'Set-ExecutionPolicy RemoteSigned -scope CurrentUser'
powershell -File ./${TEST_SCRIPT}.ps1
else
bash ./${TEST_SCRIPT}.sh ci
fi
91 changes: 78 additions & 13 deletions scala/private/rule_impls.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,35 @@ def _jar_path_based_on_java_bin(ctx):
jar_path = java_bin.rpartition("/")[0] + "/jar"
return jar_path

def _write_executable(ctx, rjars, main_class, jvm_flags, wrapper, use_jacoco):
def _write_executable(ctx, executable, rjars, main_class, jvm_flags, wrapper, use_jacoco):
if (_is_windows(ctx)):
return _write_executable_windows(ctx, executable, rjars, main_class, jvm_flags, wrapper, use_jacoco)
else:
return _write_executable_non_windows(ctx, executable, rjars, main_class, jvm_flags, wrapper, use_jacoco)

def _write_executable_windows(ctx, executable, rjars, main_class, jvm_flags, wrapper, use_jacoco):
# NOTE: `use_jacoco` is currently ignored on Windows.
# TODO: tests coverage support for Windows
classpath = ";".join(
[("external/%s" % (j.short_path[3:]) if j.short_path.startswith("../") else j.short_path) for j in rjars.to_list()],
)
jvm_flags_str = ";".join(jvm_flags)
java_for_exe = str(ctx.attr._java_runtime[java_common.JavaRuntimeInfo].java_executable_exec_path)

cpfile = ctx.actions.declare_file("%s.classpath" % ctx.label.name)
ctx.actions.write(cpfile, classpath)

ctx.actions.run(
outputs = [executable],
inputs = [cpfile],
executable = ctx.attr._exe.files_to_run.executable,
arguments = [executable.path, ctx.workspace_name, java_for_exe, main_class, cpfile.path, jvm_flags_str],
mnemonic = "ExeLauncher",
progress_message = "Creating exe launcher",
)
return []

def _write_executable_non_windows(ctx, executable, rjars, main_class, jvm_flags, wrapper, use_jacoco):
template = ctx.attr._java_stub_template.files.to_list()[0]

jvm_flags = " ".join(
Expand All @@ -608,15 +636,15 @@ def _write_executable(ctx, rjars, main_class, jvm_flags, wrapper, use_jacoco):
)
jacoco_metadata_file = ctx.actions.declare_file(
"%s.jacoco_metadata.txt" % ctx.attr.name,
sibling = ctx.outputs.executable,
sibling = executable,
)
ctx.actions.write(jacoco_metadata_file, "\n".join([
jar.short_path.replace("../", "external/")
for jar in rjars
]))
ctx.actions.expand_template(
template = template,
output = ctx.outputs.executable,
output = executable,
substitutions = {
"%classpath%": "\"%s\"" % classpath,
"%javabin%": javabin,
Expand All @@ -642,7 +670,7 @@ def _write_executable(ctx, rjars, main_class, jvm_flags, wrapper, use_jacoco):
)
ctx.actions.expand_template(
template = template,
output = ctx.outputs.executable,
output = executable,
substitutions = {
"%classpath%": "\"%s\"" % classpath,
"%java_start_class%": main_class,
Expand All @@ -661,6 +689,12 @@ def _write_executable(ctx, rjars, main_class, jvm_flags, wrapper, use_jacoco):
)
return []

def _declare_executable(ctx):
if (_is_windows(ctx)):
return ctx.actions.declare_file("%s.exe" % ctx.label.name)
else:
return ctx.actions.declare_file(ctx.label.name)

def _collect_runtime_jars(dep_targets):
runtime_jars = []

Expand Down Expand Up @@ -850,14 +884,16 @@ def scala_macro_library_impl(ctx):
# Common code shared by all scala binary implementations.
def _scala_binary_common(
ctx,
executable,
cjars,
rjars,
transitive_compile_time_jars,
jars2labels,
java_wrapper,
unused_dependency_checker_mode,
unused_dependency_checker_ignored_targets,
implicit_junit_deps_needed_for_java_compilation = []):
implicit_junit_deps_needed_for_java_compilation = [],
runfiles_ext = []):
write_manifest(ctx)
outputs = _compile_or_empty(
ctx,
Expand All @@ -878,7 +914,7 @@ def _scala_binary_common(

runfiles = ctx.runfiles(
transitive_files = depset(
[ctx.outputs.executable, java_wrapper] + ctx.files._java_runtime,
[executable, java_wrapper] + ctx.files._java_runtime + runfiles_ext,
transitive = [rjars],
),
collect_data = True,
Expand All @@ -900,8 +936,9 @@ def _scala_binary_common(
java_provider = create_java_provider(scalaattr, transitive_compile_time_jars)

return struct(
executable = executable,
coverage = outputs.coverage,
files = depset([ctx.outputs.executable, ctx.outputs.jar]),
files = depset([executable, ctx.outputs.jar]),
instrumented_files = outputs.coverage.instrumented_files,
providers = [java_provider, jars2labels] + outputs.coverage.providers,
runfiles = runfiles,
Expand Down Expand Up @@ -952,8 +989,12 @@ def scala_binary_impl(ctx):
(cjars, transitive_rjars) = (jars.compile_jars, jars.transitive_runtime_jars)

wrapper = _write_java_wrapper(ctx, "", "")

executable = _declare_executable(ctx)

out = _scala_binary_common(
ctx,
executable,
cjars,
transitive_rjars,
jars.transitive_compile_jars,
Expand All @@ -968,6 +1009,7 @@ def scala_binary_impl(ctx):
)
_write_executable(
ctx = ctx,
executable = executable,
jvm_flags = ctx.attr.jvm_flags,
main_class = ctx.attr.main_class,
rjars = out.transitive_rjars,
Expand All @@ -991,6 +1033,9 @@ def scala_repl_impl(ctx):
(cjars, transitive_rjars) = (jars.compile_jars, jars.transitive_runtime_jars)

args = " ".join(ctx.attr.scalacopts)

executable = _declare_executable(ctx)

wrapper = _write_java_wrapper(
ctx,
args,
Expand All @@ -1012,6 +1057,7 @@ trap finish EXIT

out = _scala_binary_common(
ctx,
executable,
cjars,
transitive_rjars,
jars.transitive_compile_jars,
Expand All @@ -1026,6 +1072,7 @@ trap finish EXIT
)
_write_executable(
ctx = ctx,
executable = executable,
jvm_flags = ["-Dscala.usejavacp=true"] + ctx.attr.jvm_flags,
main_class = "scala.tools.nsc.MainGenericRunner",
rjars = out.transitive_rjars,
Expand Down Expand Up @@ -1082,16 +1129,21 @@ def scala_test_impl(ctx):
jars.jars2labels,
)

args = " ".join([
"-R \"{path}\"".format(path = ctx.outputs.jar.short_path),
args = "\n".join([
"-R", ctx.outputs.jar.short_path,
_scala_test_flags(ctx),
"-C io.bazel.rules.scala.JUnitXmlReporter ",
"-C", "io.bazel.rules.scala.JUnitXmlReporter",
])

# main_class almost has to be "org.scalatest.tools.Runner" due to args....
wrapper = _write_java_wrapper(ctx, args, "")
argsFile = ctx.actions.declare_file("%s.args" % ctx.label.name)
ctx.actions.write(argsFile, args)

executable = _declare_executable(ctx)

wrapper = _write_java_wrapper(ctx, "", "")
out = _scala_binary_common(
ctx,
executable,
cjars,
transitive_rjars,
transitive_compile_jars,
Expand All @@ -1100,6 +1152,7 @@ def scala_test_impl(ctx):
unused_dependency_checker_ignored_targets =
unused_dependency_checker_ignored_targets,
unused_dependency_checker_mode = unused_dependency_checker_mode,
runfiles_ext = [argsFile]
)

rjars = out.transitive_rjars
Expand All @@ -1119,14 +1172,19 @@ def scala_test_impl(ctx):

coverage_runfiles.extend(_write_executable(
ctx = ctx,
jvm_flags = ctx.attr.jvm_flags,
executable = executable,
jvm_flags = [
"-DRULES_SCALA_MAIN_WS_NAME=%s" % ctx.workspace_name,
"-DRULES_SCALA_ARGS_FILE=%s" % argsFile.short_path
] + ctx.attr.jvm_flags,
main_class = ctx.attr.main_class,
rjars = rjars,
use_jacoco = ctx.configuration.coverage_enabled,
wrapper = wrapper,
))

return struct(
executable = executable,
files = out.files,
instrumented_files = out.instrumented_files,
providers = out.providers,
Expand Down Expand Up @@ -1204,9 +1262,12 @@ def scala_junit_test_impl(ctx):
ctx.attr._hamcrest,
]

executable = _declare_executable(ctx)

wrapper = _write_java_wrapper(ctx, "", "")
out = _scala_binary_common(
ctx,
executable,
cjars,
transitive_rjars,
jars.transitive_compile_jars,
Expand Down Expand Up @@ -1239,6 +1300,7 @@ def scala_junit_test_impl(ctx):
]
_write_executable(
ctx = ctx,
executable = executable,
jvm_flags = launcherJvmFlags + ctx.attr.jvm_flags,
main_class = "com.google.testing.junit.runner.BazelTestRunner",
rjars = out.transitive_rjars,
Expand Down Expand Up @@ -1295,3 +1357,6 @@ def _jacoco_offline_instrument(ctx, input_jar):

def _jacoco_offline_instrument_format_each(in_out_pair):
return (["%s=%s" % (in_out_pair[0].path, in_out_pair[1].path)])

def _is_windows(ctx):
return ctx.configuration.host_path_separator == ";"
Loading

0 comments on commit 78104d8

Please sign in to comment.