Skip to content

Commit 76ee19f

Browse files
authored
For Windows: Fix to enable scala_test and scala_binary outputs to be executed on Windows (#1502)
* Fixed path forms passed into the Windows Launcher. Passing the correct path forms (i.e. rpathlocation vs rootpath) to Windows Launcher. This enables running scala_test and scala_binary outputs through bazel on windows. * small lint fixes * minor changes to resolve review comments - Added comment on use of env in _write_executable_windows() - Removed unecessary var in rpathlocation_from_rootpath()
1 parent 12d60d2 commit 76ee19f

File tree

4 files changed

+44
-17
lines changed

4 files changed

+44
-17
lines changed

scala/private/common.bzl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
load("@io_bazel_rules_scala//scala:jars_to_labels.bzl", "JarsToLabelsInfo")
22
load("@io_bazel_rules_scala//scala:plusone.bzl", "PlusOneDeps")
3+
load("@bazel_skylib//lib:paths.bzl", "paths")
34

45
def write_manifest_file(actions, output_file, main_class):
56
# TODO(bazel-team): I don't think this classpath is what you want
@@ -134,3 +135,8 @@ def sanitize_string_for_usage(s):
134135
else:
135136
res_array.append("_")
136137
return "".join(res_array)
138+
139+
#generates rpathlocation that should be used with the rlocation() at runtime. (rpathlocations start with repo name)
140+
#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):
142+
return paths.normalize(ctx.workspace_name + "/" + rootpath)

scala/private/phases/phase_write_executable.bzl

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ load(
99
"first_non_empty",
1010
"is_windows",
1111
"java_bin",
12+
"java_bin_windows",
1213
"runfiles_root",
1314
)
1415

@@ -76,21 +77,24 @@ def _phase_write_executable(
7677
def _write_executable_windows(ctx, executable, rjars, main_class, jvm_flags, wrapper, use_jacoco):
7778
# NOTE: `use_jacoco` is currently ignored on Windows.
7879
# TODO: tests coverage support for Windows
79-
classpath = ";".join(
80-
[("external/%s" % (j.short_path[3:]) if j.short_path.startswith("../") else j.short_path) for j in rjars.to_list()],
81-
)
80+
#launcher expects classpaths to be in rootpath form (ie. relative to runfiles_dir, short_path does the trick)
81+
classpath = ";".join([j.short_path for j in rjars.to_list()])
82+
8283
jvm_flags_str = ";".join(jvm_flags)
83-
java_for_exe = str(ctx.attr._java_runtime[java_common.JavaRuntimeInfo].java_executable_exec_path)
84+
java_for_exe = java_bin_windows(ctx)
8485

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

89+
#Handle fact that some scala rules add env as an attr and some don't.
90+
specifiedEnv = getattr(ctx.attr, "env", {})
91+
8892
ctx.actions.run(
8993
outputs = [executable],
9094
inputs = [cpfile],
9195
executable = ctx.attr._exe.files_to_run.executable,
9296
arguments = [executable.path, ctx.workspace_name, java_for_exe, main_class, cpfile.path, jvm_flags_str],
93-
env = ctx.attr.env,
97+
env = specifiedEnv,
9498
mnemonic = "ExeLauncher",
9599
progress_message = "Creating exe launcher",
96100
)

scala/private/rule_impls.bzl

Lines changed: 14 additions & 1 deletion
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", _collect_plugin_paths = "collect_plugin_paths")
18+
load(":common.bzl", "rpathlocation_from_rootpath", _collect_plugin_paths = "collect_plugin_paths")
1919
load(":resources.bzl", _resource_paths = "paths")
2020

2121
def expand_location(ctx, flags):
@@ -203,5 +203,18 @@ def java_bin(ctx):
203203
javabin = "%s/%s" % (runfiles_root_var, java_path)
204204
return javabin
205205

206+
def java_bin_windows(ctx):
207+
java_runtime = specified_java_runtime(
208+
ctx,
209+
default_runtime = ctx.attr._java_runtime[java_common.JavaRuntimeInfo],
210+
)
211+
212+
if paths.is_absolute(java_runtime.java_executable_runfiles_path):
213+
java_bin = java_runtime.java_executable_runfiles_path
214+
else:
215+
java_bin = rpathlocation_from_rootpath(ctx, java_runtime.java_executable_runfiles_path)
216+
217+
return java_bin
218+
206219
def is_windows(ctx):
207220
return ctx.configuration.host_path_separator == ";"

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

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.nio.file.*;
1212
import java.util.Arrays;
1313
import java.util.List;
14+
import java.nio.file.Paths;
1415

1516
public class LauncherFileWriter {
1617
public static void main(String[] args) throws IOException {
@@ -30,10 +31,10 @@ public static void main(String[] args) throws IOException {
3031
.addKeyValuePair("binary_type", "Java")
3132
.addKeyValuePair("workspace_name", workspaceName)
3233
.addKeyValuePair("symlink_runfiles_enabled", "0")
33-
.addKeyValuePair("java_bin_path", fullJavaBinPath(workspaceName, Paths.get(javaBinPath)).toString())
34-
.addKeyValuePair("jar_bin_path", jarBinPath)
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
3536
.addKeyValuePair("java_start_class", javaStartClass)
36-
.addKeyValuePair("classpath", classpath)
37+
.addKeyValuePair("classpath", classpath) //Expects rootpath location
3738
.addJoinedValues("jvm_flags", "\t", jvmFlags)
3839
.build();
3940

@@ -55,14 +56,17 @@ public static void main(String[] args) throws IOException {
5556
}
5657
}
5758

58-
private static Path fullJavaBinPath(String workspaceName, Path javaBinPath) {
59-
if (javaBinPath.isAbsolute()) {
60-
return javaBinPath;
61-
} else if (javaBinPath.startsWith(Paths.get("external"))) {
62-
// Paths under `external/` already have a workspace name.
63-
return javaBinPath;
64-
} else {
65-
return Paths.get(workspaceName).resolve(javaBinPath);
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);
62+
63+
Path result;
64+
if(!path.startsWith(workspaceName)){
65+
//Assume that if its not in the main workspace, that it is an external repo (and should be one level down)
66+
result = Paths.get("../").resolve(path);
67+
}else{
68+
result = Paths.get(workspaceName).resolve(path);
6669
}
70+
return result.toString().replace("\\", "/");
6771
}
6872
}

0 commit comments

Comments
 (0)