Skip to content

Commit eac6f06

Browse files
authored
Make tests pass on Windows (#1529)
* Make tests pass on Windows Bunch of changes. Here's some highlights: Code Changes - Refactored ScalacWorker to abstract common code between Scala 2 & 3 - Refactored dependency-analyzer plugin javaargs to use ‘;’ as a delimiter instead of ‘:’ - Renamed a couple function names containing rpathlocation to rlocationpath - added lineEndings=preserve to scalafmt.conf - added .bazelrc to enable needed flags for Windows Test Changes - disable running tests for features not-supported on Windows - make tests handle fact that sh_binary outputs .exe on Windows - Handle other Windows specifics where needed (i.e. backslash as pathseparator, crlf linendings, dependence on bash) * Fixed some minor nits
1 parent eb63ea0 commit eac6f06

Some content is hidden

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

42 files changed

+416
-545
lines changed

.bazelrc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
build --enable_platform_specific_config
2+
3+
#Windows needs --worker_quit_after_build due to workers not being shut down when the compiler tools need to be rebuilt (resulting in 'file in use' errors). See Bazel Issue#10498.
4+
5+
build:windows --worker_quit_after_build --enable_runfiles

.scalafmt.conf

+1
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ rewrite.rules = [
1313
SortImports
1414
]
1515
unindentTopLevelOperators = false
16+
lineEndings=preserve

dt_patches/dt_patch_test.sh

+5-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ run_test_local() {
1717
if [ $RESPONSE_CODE -eq 0 ]; then
1818
echo -e "${GREEN} Test \"$TEST_ARG\" successful ($DURATION sec) $NC"
1919
else
20+
echo $RES
2021
echo -e "${RED} Test \"$TEST_ARG\" failed $NC ($DURATION sec) $NC"
2122
return $RESPONSE_CODE
2223
fi
@@ -26,9 +27,12 @@ run_in_test_repo() {
2627
local test_command=$1
2728
local test_repo=$2
2829

29-
cd "${dir}/${test_repo}" || exit 1
30+
cd "${dir}/${test_repo}" || exit 1
3031
${test_command}
3132
RESPONSE_CODE=$?
33+
34+
bazel shutdown
35+
3236
cd ../..
3337

3438
return $RESPONSE_CODE

dt_patches/test_dt_patches/.bazelrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import ../../.bazelrc
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import ../../.bazelrc
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
build --enable_platform_specific_config
2+
windows:build --enable_runfiles
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
build --enable_platform_specific_config
2+
windows:build --enable_runfiles

scala/private/common.bzl

+6-2
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,11 @@ def sanitize_string_for_usage(s):
136136
res_array.append("_")
137137
return "".join(res_array)
138138

139-
#generates rpathlocation that should be used with the rlocation() at runtime. (rpathlocations start with repo name)
139+
#generates an rlocationpath that can be used with the rlocation() at runtime. (rlocationpath starts with repo name)
140+
def rlocationpath_from_file(ctx, file):
141+
return paths.normalize(ctx.workspace_name + "/" + file.short_path)
142+
143+
#generates an rlocationpath that can be used with the rlocation() at runtime. (rlocationpath start with repo name)
140144
#rootpath arg expects "rootpath" format (i.e. relative to runfilesDir/workspacename). Rootpath can be obtained by $rootpath macro or File.short_path
141-
def rpathlocation_from_rootpath(ctx, rootpath):
145+
def rlocationpath_from_rootpath(ctx, rootpath):
142146
return paths.normalize(ctx.workspace_name + "/" + rootpath)

scala/private/rule_impls.bzl

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
load("@bazel_skylib//lib:paths.bzl", "paths")
1717
load("@bazel_tools//tools/jdk:toolchain_utils.bzl", "find_java_toolchain")
18-
load(":common.bzl", "rpathlocation_from_rootpath", _collect_plugin_paths = "collect_plugin_paths")
18+
load(":common.bzl", "rlocationpath_from_rootpath", _collect_plugin_paths = "collect_plugin_paths")
1919
load(":resources.bzl", _resource_paths = "paths")
2020

2121
def expand_location(ctx, flags):
@@ -213,7 +213,7 @@ def java_bin_windows(ctx):
213213
if paths.is_absolute(java_runtime.java_executable_runfiles_path):
214214
java_bin = java_runtime.java_executable_runfiles_path
215215
else:
216-
java_bin = rpathlocation_from_rootpath(ctx, java_runtime.java_executable_runfiles_path)
216+
java_bin = rlocationpath_from_rootpath(ctx, java_runtime.java_executable_runfiles_path)
217217

218218
return java_bin
219219

src/java/io/bazel/rulesscala/exe/LauncherFileWriter.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ public static void main(String[] args) throws IOException {
3131
.addKeyValuePair("binary_type", "Java")
3232
.addKeyValuePair("workspace_name", workspaceName)
3333
.addKeyValuePair("symlink_runfiles_enabled", "0")
34-
.addKeyValuePair("java_bin_path", javaBinPath.replace("\\", "/")) //Expects rpathlocation (i.e. with prepended repo name)
35-
.addKeyValuePair("jar_bin_path", rpathlocation_to_rootpath( workspaceName, jarBinPath)) //Expects rootpath location
34+
.addKeyValuePair("java_bin_path", javaBinPath.replace("\\", "/")) //Expects rlocationpath (i.e. with prepended repo name)
35+
.addKeyValuePair("jar_bin_path", rlocationpath_to_rootpath( workspaceName, jarBinPath)) //Expects rootpath location
3636
.addKeyValuePair("java_start_class", javaStartClass)
3737
.addKeyValuePair("classpath", classpath) //Expects rootpath location
3838
.addJoinedValues("jvm_flags", "\t", jvmFlags)
@@ -56,9 +56,9 @@ public static void main(String[] args) throws IOException {
5656
}
5757
}
5858

59-
//Bazel's java_launcher expects some fields(i.e. jar_bin_path and classpaths) to be rootpath. rpathlocation is relative to runfiledir (always prefix with repo). Rootpath is relative to runfiledir/workspacename.
60-
static String rpathlocation_to_rootpath(String workspaceName, String rpathlocation){
61-
Path path = Paths.get(rpathlocation);
59+
//Bazel's java_launcher expects some fields(i.e. jar_bin_path and classpaths) to be rootpath. rlocationpath is relative to runfiledir (always prefix with repo). Rootpath is relative to runfiledir/workspacename.
60+
static String rlocationpath_to_rootpath(String workspaceName, String rlocationpath){
61+
Path path = Paths.get(rlocationpath);
6262

6363
Path result;
6464
if(!path.startsWith(workspaceName)){

src/java/io/bazel/rulesscala/scalac/BUILD

+10-5
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ java_binary(
2727
"-source 1.8",
2828
"-target 1.8",
2929
],
30-
main_class = "io.bazel.rulesscala.scalac.ScalacWorker" if SCALA_MAJOR_VERSION.startswith("2") else "io.bazel.rulesscala.scalac.ScalacWorker3",
30+
main_class = "io.bazel.rulesscala.scalac.ScalacWorker",
3131
visibility = ["//visibility:public"],
3232
deps = DEP_REPORTING_DEPS + SCALAC_DEPS,
3333
)
@@ -41,16 +41,21 @@ java_binary(
4141
"-source 1.8",
4242
"-target 1.8",
4343
],
44-
main_class = "io.bazel.rulesscala.scalac.ScalacWorker" if SCALA_MAJOR_VERSION.startswith("2") else "io.bazel.rulesscala.scalac.ScalacWorker3",
44+
main_class = "io.bazel.rulesscala.scalac.ScalacWorker",
4545
visibility = ["//visibility:public"],
4646
deps = SCALAC_DEPS,
4747
)
4848

4949
filegroup(
5050
name = "scalac_files",
51-
srcs = ([
51+
srcs = [
5252
"ScalacWorker.java",
53-
"ReportableMainClass.java",
54-
] if SCALA_MAJOR_VERSION.startswith("2") else ["ScalacWorker3.java"]),
53+
"ScalacInvokerResults.java",
54+
] + (
55+
[
56+
"ScalacInvoker.java",
57+
"ReportableMainClass.java",
58+
] if SCALA_MAJOR_VERSION.startswith("2") else ["ScalacInvoker3.java"]
59+
),
5560
visibility = ["//visibility:public"],
5661
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package io.bazel.rulesscala.scalac;
2+
3+
import io.bazel.rulesscala.scalac.reporter.DepsTrackingReporter;
4+
import io.bazel.rulesscala.scalac.compileoptions.CompileOptions;
5+
import java.nio.file.Paths;
6+
import io.bazel.rulesscala.scalac.reporter.ProtoReporter;
7+
import scala.tools.nsc.reporters.ConsoleReporter;
8+
import java.io.IOException;
9+
import java.util.Arrays;
10+
import java.nio.file.Files;
11+
12+
//Invokes Scala 2 compiler
13+
class ScalacInvoker{
14+
15+
public static ScalacInvokerResults invokeCompiler(CompileOptions ops, String[] compilerArgs)
16+
throws IOException, Exception{
17+
18+
ReportableMainClass comp = new ReportableMainClass(ops);
19+
20+
ScalacInvokerResults results = new ScalacInvokerResults();
21+
22+
results.startTime = System.currentTimeMillis();
23+
try {
24+
comp.process(compilerArgs);
25+
} catch (Throwable ex) {
26+
if (ex.toString().contains("scala.reflect.internal.Types$TypeError")) {
27+
throw new RuntimeException("Build failure with type error", ex);
28+
} else if (ex.toString().contains("java.lang.StackOverflowError")) {
29+
throw new RuntimeException("Build failure with StackOverflowError", ex);
30+
} else if (isMacroException(ex)) {
31+
throw new RuntimeException("Build failure during macro expansion", ex);
32+
} else {
33+
throw ex;
34+
}
35+
}
36+
37+
results.stopTime = System.currentTimeMillis();
38+
39+
ConsoleReporter reporter = (ConsoleReporter) comp.getReporter();
40+
if (reporter instanceof ProtoReporter) {
41+
ProtoReporter protoReporter = (ProtoReporter) reporter;
42+
protoReporter.writeTo(Paths.get(ops.diagnosticsFile));
43+
}
44+
45+
if (reporter instanceof DepsTrackingReporter) {
46+
DepsTrackingReporter depTrackingReporter = (DepsTrackingReporter) reporter;
47+
depTrackingReporter.prepareReport();
48+
depTrackingReporter.writeDiagnostics(ops.diagnosticsFile);
49+
}
50+
51+
if (reporter.hasErrors()) {
52+
reporter.flush();
53+
throw new RuntimeException("Build failed");
54+
}
55+
56+
return results;
57+
}
58+
59+
public static boolean isMacroException(Throwable ex) {
60+
for (StackTraceElement elem : ex.getStackTrace()) {
61+
if (elem.getMethodName().equals("macroExpand")) {
62+
return true;
63+
}
64+
}
65+
return false;
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package io.bazel.rulesscala.scalac;
2+
3+
import io.bazel.rulesscala.scalac.compileoptions.CompileOptions;
4+
import java.nio.file.Paths;
5+
import java.nio.file.Files;
6+
import scala.Tuple2;
7+
import java.io.IOException;
8+
9+
import dotty.tools.dotc.reporting.Reporter;
10+
import dotty.tools.dotc.Compiler;
11+
import dotty.tools.dotc.Driver;
12+
import dotty.tools.dotc.core.Contexts;
13+
import dotty.tools.io.AbstractFile;
14+
15+
//Invokes Scala 3 compiler
16+
class ScalacInvoker{
17+
public static ScalacInvokerResults invokeCompiler(CompileOptions ops, String[] compilerArgs)
18+
throws IOException, Exception{
19+
20+
21+
ScalacInvokerResults results = new ScalacInvokerResults();
22+
Driver driver = new dotty.tools.dotc.Driver();
23+
Contexts.Context ctx = driver.initCtx().fresh();
24+
25+
Tuple2<scala.collection.immutable.List<AbstractFile>, Contexts.Context> r = driver.setup(compilerArgs, ctx).get();
26+
27+
Compiler compiler = driver.newCompiler(r._2);
28+
29+
results.startTime= System.currentTimeMillis();
30+
31+
Reporter reporter = driver.doCompile(compiler, r._1, r._2);
32+
33+
results.stopTime = System.currentTimeMillis();
34+
35+
Files.createFile(
36+
Paths.get(ops.diagnosticsFile));
37+
Files.createFile(
38+
Paths.get(ops.scalaDepsFile));
39+
40+
41+
if (reporter.hasErrors()) {
42+
// reporter.flush();
43+
throw new RuntimeException("Build failed");
44+
}
45+
46+
return results;
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package io.bazel.rulesscala.scalac;
2+
3+
public class ScalacInvokerResults{
4+
public long startTime; //unixTime ms
5+
public long stopTime; //unixTime ms
6+
}

0 commit comments

Comments
 (0)