Skip to content

Commit

Permalink
Make tests pass on Windows (#1529)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
crt-31 authored Dec 19, 2023
1 parent eb63ea0 commit eac6f06
Show file tree
Hide file tree
Showing 42 changed files with 416 additions and 545 deletions.
5 changes: 5 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
build --enable_platform_specific_config

#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.

build:windows --worker_quit_after_build --enable_runfiles
1 change: 1 addition & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ rewrite.rules = [
SortImports
]
unindentTopLevelOperators = false
lineEndings=preserve
6 changes: 5 additions & 1 deletion dt_patches/dt_patch_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ run_test_local() {
if [ $RESPONSE_CODE -eq 0 ]; then
echo -e "${GREEN} Test \"$TEST_ARG\" successful ($DURATION sec) $NC"
else
echo $RES
echo -e "${RED} Test \"$TEST_ARG\" failed $NC ($DURATION sec) $NC"
return $RESPONSE_CODE
fi
Expand All @@ -26,9 +27,12 @@ run_in_test_repo() {
local test_command=$1
local test_repo=$2

cd "${dir}/${test_repo}" || exit 1
cd "${dir}/${test_repo}" || exit 1
${test_command}
RESPONSE_CODE=$?

bazel shutdown

cd ../..

return $RESPONSE_CODE
Expand Down
1 change: 1 addition & 0 deletions dt_patches/test_dt_patches/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import ../../.bazelrc
1 change: 1 addition & 0 deletions dt_patches/test_dt_patches_user_srcjar/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import ../../.bazelrc
2 changes: 2 additions & 0 deletions examples/testing/multi_frameworks_toolchain/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build --enable_platform_specific_config
windows:build --enable_runfiles
2 changes: 2 additions & 0 deletions examples/testing/specs2_junit_repositories/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build --enable_platform_specific_config
windows:build --enable_runfiles
8 changes: 6 additions & 2 deletions scala/private/common.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,11 @@ def sanitize_string_for_usage(s):
res_array.append("_")
return "".join(res_array)

#generates rpathlocation that should be used with the rlocation() at runtime. (rpathlocations start with repo name)
#generates an rlocationpath that can be used with the rlocation() at runtime. (rlocationpath starts with repo name)
def rlocationpath_from_file(ctx, file):
return paths.normalize(ctx.workspace_name + "/" + file.short_path)

#generates an rlocationpath that can be used with the rlocation() at runtime. (rlocationpath start with repo name)
#rootpath arg expects "rootpath" format (i.e. relative to runfilesDir/workspacename). Rootpath can be obtained by $rootpath macro or File.short_path
def rpathlocation_from_rootpath(ctx, rootpath):
def rlocationpath_from_rootpath(ctx, rootpath):
return paths.normalize(ctx.workspace_name + "/" + rootpath)
4 changes: 2 additions & 2 deletions scala/private/rule_impls.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

load("@bazel_skylib//lib:paths.bzl", "paths")
load("@bazel_tools//tools/jdk:toolchain_utils.bzl", "find_java_toolchain")
load(":common.bzl", "rpathlocation_from_rootpath", _collect_plugin_paths = "collect_plugin_paths")
load(":common.bzl", "rlocationpath_from_rootpath", _collect_plugin_paths = "collect_plugin_paths")
load(":resources.bzl", _resource_paths = "paths")

def expand_location(ctx, flags):
Expand Down Expand Up @@ -213,7 +213,7 @@ def java_bin_windows(ctx):
if paths.is_absolute(java_runtime.java_executable_runfiles_path):
java_bin = java_runtime.java_executable_runfiles_path
else:
java_bin = rpathlocation_from_rootpath(ctx, java_runtime.java_executable_runfiles_path)
java_bin = rlocationpath_from_rootpath(ctx, java_runtime.java_executable_runfiles_path)

return java_bin

Expand Down
10 changes: 5 additions & 5 deletions src/java/io/bazel/rulesscala/exe/LauncherFileWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ public static void main(String[] args) throws IOException {
.addKeyValuePair("binary_type", "Java")
.addKeyValuePair("workspace_name", workspaceName)
.addKeyValuePair("symlink_runfiles_enabled", "0")
.addKeyValuePair("java_bin_path", javaBinPath.replace("\\", "/")) //Expects rpathlocation (i.e. with prepended repo name)
.addKeyValuePair("jar_bin_path", rpathlocation_to_rootpath( workspaceName, jarBinPath)) //Expects rootpath location
.addKeyValuePair("java_bin_path", javaBinPath.replace("\\", "/")) //Expects rlocationpath (i.e. with prepended repo name)
.addKeyValuePair("jar_bin_path", rlocationpath_to_rootpath( workspaceName, jarBinPath)) //Expects rootpath location
.addKeyValuePair("java_start_class", javaStartClass)
.addKeyValuePair("classpath", classpath) //Expects rootpath location
.addJoinedValues("jvm_flags", "\t", jvmFlags)
Expand All @@ -56,9 +56,9 @@ public static void main(String[] args) throws IOException {
}
}

//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.
static String rpathlocation_to_rootpath(String workspaceName, String rpathlocation){
Path path = Paths.get(rpathlocation);
//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.
static String rlocationpath_to_rootpath(String workspaceName, String rlocationpath){
Path path = Paths.get(rlocationpath);

Path result;
if(!path.startsWith(workspaceName)){
Expand Down
15 changes: 10 additions & 5 deletions src/java/io/bazel/rulesscala/scalac/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ java_binary(
"-source 1.8",
"-target 1.8",
],
main_class = "io.bazel.rulesscala.scalac.ScalacWorker" if SCALA_MAJOR_VERSION.startswith("2") else "io.bazel.rulesscala.scalac.ScalacWorker3",
main_class = "io.bazel.rulesscala.scalac.ScalacWorker",
visibility = ["//visibility:public"],
deps = DEP_REPORTING_DEPS + SCALAC_DEPS,
)
Expand All @@ -41,16 +41,21 @@ java_binary(
"-source 1.8",
"-target 1.8",
],
main_class = "io.bazel.rulesscala.scalac.ScalacWorker" if SCALA_MAJOR_VERSION.startswith("2") else "io.bazel.rulesscala.scalac.ScalacWorker3",
main_class = "io.bazel.rulesscala.scalac.ScalacWorker",
visibility = ["//visibility:public"],
deps = SCALAC_DEPS,
)

filegroup(
name = "scalac_files",
srcs = ([
srcs = [
"ScalacWorker.java",
"ReportableMainClass.java",
] if SCALA_MAJOR_VERSION.startswith("2") else ["ScalacWorker3.java"]),
"ScalacInvokerResults.java",
] + (
[
"ScalacInvoker.java",
"ReportableMainClass.java",
] if SCALA_MAJOR_VERSION.startswith("2") else ["ScalacInvoker3.java"]
),
visibility = ["//visibility:public"],
)
67 changes: 67 additions & 0 deletions src/java/io/bazel/rulesscala/scalac/ScalacInvoker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package io.bazel.rulesscala.scalac;

import io.bazel.rulesscala.scalac.reporter.DepsTrackingReporter;
import io.bazel.rulesscala.scalac.compileoptions.CompileOptions;
import java.nio.file.Paths;
import io.bazel.rulesscala.scalac.reporter.ProtoReporter;
import scala.tools.nsc.reporters.ConsoleReporter;
import java.io.IOException;
import java.util.Arrays;
import java.nio.file.Files;

//Invokes Scala 2 compiler
class ScalacInvoker{

public static ScalacInvokerResults invokeCompiler(CompileOptions ops, String[] compilerArgs)
throws IOException, Exception{

ReportableMainClass comp = new ReportableMainClass(ops);

ScalacInvokerResults results = new ScalacInvokerResults();

results.startTime = System.currentTimeMillis();
try {
comp.process(compilerArgs);
} catch (Throwable ex) {
if (ex.toString().contains("scala.reflect.internal.Types$TypeError")) {
throw new RuntimeException("Build failure with type error", ex);
} else if (ex.toString().contains("java.lang.StackOverflowError")) {
throw new RuntimeException("Build failure with StackOverflowError", ex);
} else if (isMacroException(ex)) {
throw new RuntimeException("Build failure during macro expansion", ex);
} else {
throw ex;
}
}

results.stopTime = System.currentTimeMillis();

ConsoleReporter reporter = (ConsoleReporter) comp.getReporter();
if (reporter instanceof ProtoReporter) {
ProtoReporter protoReporter = (ProtoReporter) reporter;
protoReporter.writeTo(Paths.get(ops.diagnosticsFile));
}

if (reporter instanceof DepsTrackingReporter) {
DepsTrackingReporter depTrackingReporter = (DepsTrackingReporter) reporter;
depTrackingReporter.prepareReport();
depTrackingReporter.writeDiagnostics(ops.diagnosticsFile);
}

if (reporter.hasErrors()) {
reporter.flush();
throw new RuntimeException("Build failed");
}

return results;
}

public static boolean isMacroException(Throwable ex) {
for (StackTraceElement elem : ex.getStackTrace()) {
if (elem.getMethodName().equals("macroExpand")) {
return true;
}
}
return false;
}
}
48 changes: 48 additions & 0 deletions src/java/io/bazel/rulesscala/scalac/ScalacInvoker3.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package io.bazel.rulesscala.scalac;

import io.bazel.rulesscala.scalac.compileoptions.CompileOptions;
import java.nio.file.Paths;
import java.nio.file.Files;
import scala.Tuple2;
import java.io.IOException;

import dotty.tools.dotc.reporting.Reporter;
import dotty.tools.dotc.Compiler;
import dotty.tools.dotc.Driver;
import dotty.tools.dotc.core.Contexts;
import dotty.tools.io.AbstractFile;

//Invokes Scala 3 compiler
class ScalacInvoker{
public static ScalacInvokerResults invokeCompiler(CompileOptions ops, String[] compilerArgs)
throws IOException, Exception{


ScalacInvokerResults results = new ScalacInvokerResults();
Driver driver = new dotty.tools.dotc.Driver();
Contexts.Context ctx = driver.initCtx().fresh();

Tuple2<scala.collection.immutable.List<AbstractFile>, Contexts.Context> r = driver.setup(compilerArgs, ctx).get();

Compiler compiler = driver.newCompiler(r._2);

results.startTime= System.currentTimeMillis();

Reporter reporter = driver.doCompile(compiler, r._1, r._2);

results.stopTime = System.currentTimeMillis();

Files.createFile(
Paths.get(ops.diagnosticsFile));
Files.createFile(
Paths.get(ops.scalaDepsFile));


if (reporter.hasErrors()) {
// reporter.flush();
throw new RuntimeException("Build failed");
}

return results;
}
}
6 changes: 6 additions & 0 deletions src/java/io/bazel/rulesscala/scalac/ScalacInvokerResults.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.bazel.rulesscala.scalac;

public class ScalacInvokerResults{
public long startTime; //unixTime ms
public long stopTime; //unixTime ms
}
Loading

0 comments on commit eac6f06

Please sign in to comment.