diff options
author | 2016-11-02 17:52:00 +0000 | |
---|---|---|
committer | 2016-11-03 07:17:01 +0000 | |
commit | a1b2ae004c179e218acdd8028cd698e2c7102eba (patch) | |
tree | 7d1588022bc9796346af1cff9a1b1a2e8a07eba7 | |
parent | f7a5769187a11d4d15ed685abf55338eaeafdc12 (diff) |
java_binary: fix runfiles dir creation on Windows
Create the runfiles directory for the shell stub
script (bazel-bin/foo/bar_bin and
bazel-bin/foo/bar_bin.runfiles) but use the batch
script as the runfiles provider's executable
(bazel-bin/foo/bar_bin.cmd). This way we the shell
stub script can still find its runfiles (under its
parent directory + its base name + ".runfiles)
while "bazel run" can also work on Windows.
Fixes https://github.com/bazelbuild/bazel/issues/2025
See https://github.com/bazelbuild/bazel/issues/1925
--
MOS_MIGRATED_REVID=137965442
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java | 43 | ||||
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java | 8 |
2 files changed, 36 insertions, 15 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java index cd0173e777..db6563a6fd 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java @@ -147,14 +147,21 @@ public class JavaBinary implements RuleConfiguredTargetFactory { helper.createInstrumentationMetadata(classJar, javaArtifactsBuilder); NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder(); - Artifact executable = null; + Artifact executableForRunfiles = null; if (createExecutable) { - executable = ruleContext.createOutputArtifact(); // the artifact for the rule itself - filesBuilder.add(classJar).add(executable); + // This artifact is named as the rule itself, e.g. //foo:bar_bin -> bazel-bin/foo/bar_bin + executableForRunfiles = ruleContext.createOutputArtifact(); + filesBuilder.add(classJar).add(executableForRunfiles); if (ruleContext.getConfiguration().isCodeCoverageEnabled()) { - mainClass = semantics.addCoverageSupport(helper, attributesBuilder, - executable, instrumentationMetadata, javaArtifactsBuilder, mainClass); + mainClass = + semantics.addCoverageSupport( + helper, + attributesBuilder, + executableForRunfiles, + instrumentationMetadata, + javaArtifactsBuilder, + mainClass); } } else { filesBuilder.add(classJar); @@ -226,20 +233,20 @@ public class JavaBinary implements RuleConfiguredTargetFactory { return null; } + Artifact executableToRun = executableForRunfiles; if (createExecutable) { // Create a shell stub for a Java application - Artifact newExecutable = + executableToRun = semantics.createStubAction( ruleContext, common, jvmFlags, - executable, + executableForRunfiles, mainClass, JavaCommon.getJavaBinSubstitution(ruleContext, launcher)); - if (!newExecutable.equals(executable)) { - filesBuilder.add(newExecutable); - runfilesBuilder.addArtifact(newExecutable); - executable = newExecutable; + if (!executableToRun.equals(executableForRunfiles)) { + filesBuilder.add(executableToRun); + runfilesBuilder.addArtifact(executableToRun); } } @@ -297,8 +304,14 @@ public class JavaBinary implements RuleConfiguredTargetFactory { // otherwise, set classpath to deploy jar. extraArgs.add("--wrapper_script_flag=--singlejar"); } + // The executable we pass here will be used when creating the runfiles directory. E.g. for the + // stub script called bazel-bin/foo/bar_bin, the runfiles directory will be created under + // bazel-bin/foo/bar_bin.runfiles . On platforms where there's an extra stub script (Windows) + // which dispatches to this one, we still create the runfiles directory for the shell script, + // but use the dispatcher script (a batch file) as the RunfilesProvider's executable. runfilesSupport = - RunfilesSupport.withExecutable(ruleContext, defaultRunfiles, executable, extraArgs); + RunfilesSupport.withExecutable( + ruleContext, defaultRunfiles, executableForRunfiles, extraArgs); } RunfilesProvider runfilesProvider = RunfilesProvider.withData( @@ -364,7 +377,11 @@ public class JavaBinary implements RuleConfiguredTargetFactory { .setFilesToBuild(filesToBuild) .add(JavaRuleOutputJarsProvider.class, javaRuleOutputJarsProviderBuilder.build()) .add(RunfilesProvider.class, runfilesProvider) - .setRunfilesSupport(runfilesSupport, executable) + // The executable to run (below) may be different from the executable for runfiles (the one + // we create the runfiles support object with). On Linux they are the same (it's the same + // shell script), on Windows they are different (the executable to run is a batch file, the + // executable for runfiles is the shell script). + .setRunfilesSupport(runfilesSupport, executableToRun) .add( JavaRuntimeClasspathProvider.class, new JavaRuntimeClasspathProvider(common.getRuntimeClasspath())) diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java index 10a59d2a6c..b1b72dcea6 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java @@ -256,8 +256,12 @@ public interface JavaSemantics { * Creates the action that writes the Java executable stub script. * * <p>Returns the launcher script artifact. This may or may not be the same as {@code executable}, - * depending on the implementation of this method. If they are different, the returned value - * should be used as the stub script instead of the input {@code executable}. + * depending on the implementation of this method. If they are the same, then this Artifact should + * be used when creating both the {@code RunfilesProvider} and the {@code RunfilesSupport}. If + * they are different, the new value should be used when creating the {@code RunfilesProvider} (so + * it will be the stub script executed by "bazel run" for example), and the old value should be + * used when creasting the {@code RunfilesSupport} (so the runfiles directory will be named after + * it). * * <p>For example on Windows we use a double dispatch approach: the launcher is a batch file (and * is created and returned by this method) which shells out to a shell script (the {@code |