diff options
author | 2017-08-04 10:02:53 +0200 | |
---|---|---|
committer | 2017-08-04 17:16:24 +0200 | |
commit | 7e4fbbe4ab3915a57b2187408c3909e5cd6c6013 (patch) | |
tree | b8e2c36553ca79e0035e2f701d3499c602dd8e9d /src/main/java/com/google/devtools | |
parent | 0d659c0dd219ae6a73689f4431d2432bc2025ec7 (diff) |
Add --windows_exe_launcher option
If this is enabled, Bazel will build a Windows native exe binary
launcher for sh_binary, in the future this flag will also
apply to py_binary and java_binary.
By default, it's turned ON, set --windows_exe_launcher=0 to turn it off.
Fix https://github.com/bazelbuild/bazel/issues/3491
Change-Id: Ic55bff745670446e585e3cc62af9dc6561527d4f
PiperOrigin-RevId: 164234552
Diffstat (limited to 'src/main/java/com/google/devtools')
4 files changed, 97 insertions, 17 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD index fb1870b6e8..f17579cdfa 100644 --- a/src/main/java/com/google/devtools/build/lib/BUILD +++ b/src/main/java/com/google/devtools/build/lib/BUILD @@ -734,6 +734,7 @@ java_library( "bazel/rules/java/java_stub_template.txt", "bazel/rules/java/java_stub_template_windows.txt", "bazel/rules/python/python_stub_template.txt", + "bazel/rules/sh/sh_stub_template_windows.txt", ], deps = [ ":bazel", diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java index 106a066666..a96156aa42 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java @@ -1129,6 +1129,17 @@ public final class BuildConfiguration implements BuildEvent { ) public TriState buildPythonZip; + @Option( + name = "windows_exe_launcher", + defaultValue = "true", + documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, + effectTags = {OptionEffectTag.UNKNOWN}, + help = + "Build a Windows exe launcher for sh_binary rule, " + + "it has no effect on other platforms than Windows" + ) + public boolean windowsExeLauncher; + @Override public FragmentOptions getHost(boolean fallback) { Options host = (Options) getDefault(); @@ -1139,6 +1150,7 @@ public final class BuildConfiguration implements BuildEvent { host.useDynamicConfigurations = useDynamicConfigurations; host.enableRunfiles = enableRunfiles; host.buildPythonZip = buildPythonZip; + host.windowsExeLauncher = windowsExeLauncher; host.commandLineBuildVariables = commandLineBuildVariables; host.enforceConstraints = enforceConstraints; host.separateGenfilesDirectory = separateGenfilesDirectory; @@ -2711,6 +2723,10 @@ public final class BuildConfiguration implements BuildEvent { } } + public boolean enableWindowsExeLauncher() { + return options.windowsExeLauncher; + } + /** * Collects executables defined by fragments. */ diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java index 0b3d37dfd3..f264df8d49 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java @@ -16,7 +16,6 @@ package com.google.devtools.build.lib.bazel.rules.sh; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.google.common.io.ByteSource; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.ConfiguredTarget; @@ -29,6 +28,9 @@ import com.google.devtools.build.lib.analysis.RunfilesSupport; import com.google.devtools.build.lib.analysis.actions.BinaryFileWriteAction; import com.google.devtools.build.lib.analysis.actions.ExecutableSymlinkAction; import com.google.devtools.build.lib.analysis.actions.SpawnAction; +import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction; +import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution; +import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Template; import com.google.devtools.build.lib.bazel.rules.BazelConfiguration; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; @@ -43,6 +45,8 @@ import java.nio.ByteOrder; * Implementation for the sh_binary rule. */ public class ShBinary implements RuleConfiguredTargetFactory { + private static final Template STUB_SCRIPT_WINDOWS = + Template.forResource(ShBinary.class, "sh_stub_template_windows.txt"); @Override public ConfiguredTarget create(RuleContext ruleContext) throws RuleErrorException { @@ -114,21 +118,8 @@ public class ShBinary implements RuleConfiguredTargetFactory { || artifact.getExtension().equals("bat"); } - private static Artifact launcherForWindows( - RuleContext ruleContext, Artifact primaryOutput, Artifact mainFile) + private static Artifact createWindowsExeLauncher(RuleContext ruleContext, Artifact mainFile) throws RuleErrorException { - if (isWindowsExecutable(mainFile)) { - // If the extensions don't match, we should always respect mainFile's extension. - if (mainFile.getExtension().equals(primaryOutput.getExtension())) { - return primaryOutput; - } else { - ruleContext.ruleError( - "Source file is a Windows executable file," - + " target name extension should match source file extension"); - throw new RuleErrorException(); - } - } - // The launcher file consists of a base launcher binary and the launch information appended to // the binary. The length of launch info is a signed 64-bit integer written at the end of // the binary in little endian. @@ -170,7 +161,7 @@ public class ShBinary implements RuleConfiguredTargetFactory { launchInfoFile, ByteSource.wrap(launchInfo.toByteArray()), /*makeExecutable=*/ false)); - String path = ruleContext.getConfiguration().getActionEnvironment().getFixedEnv().get("PATH"); + ruleContext.registerAction( new SpawnAction.Builder() .addInput(launcher) @@ -184,10 +175,47 @@ public class ShBinary implements RuleConfiguredTargetFactory { + " " + bashLauncher.getExecPathString().replace('/', '\\') + " > nul\"") - .setEnvironment(ImmutableMap.of("PATH", path)) + .useDefaultShellEnvironment() .setMnemonic("BuildBashLauncher") .build(ruleContext)); return bashLauncher; } + + private static Artifact launcherForWindows( + RuleContext ruleContext, Artifact primaryOutput, Artifact mainFile) + throws RuleErrorException { + if (isWindowsExecutable(mainFile)) { + if (mainFile.getExtension().equals(primaryOutput.getExtension())) { + return primaryOutput; + } else { + // If the extensions don't match, we should always respect mainFile's extension. + ruleContext.ruleError( + "Source file is a Windows executable file," + + " target name extension should match source file extension"); + throw new RuleErrorException(); + } + } + + if (ruleContext.getConfiguration().enableWindowsExeLauncher()) { + return createWindowsExeLauncher(ruleContext, mainFile); + } + + Artifact wrapper = + ruleContext.getImplicitOutputArtifact(ruleContext.getTarget().getName() + ".cmd"); + ruleContext.registerAction( + new TemplateExpansionAction( + ruleContext.getActionOwner(), + wrapper, + STUB_SCRIPT_WINDOWS, + ImmutableList.of( + Substitution.of( + "%bash_exe_path%", + ruleContext + .getFragment(BazelConfiguration.class) + .getShellExecutable() + .getPathString())), + true)); + return wrapper; + } } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/sh_stub_template_windows.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/sh_stub_template_windows.txt new file mode 100644 index 0000000000..175985fac6 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/sh_stub_template_windows.txt @@ -0,0 +1,35 @@ +@rem Copyright 2016 The Bazel Authors. All rights reserved. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem This script was generated from sh_stub_template_windows.txt. Please +@rem don't edit it directly. +@rem See the header comments in the accompanying shell script (same path as that +@rem of this file, minus the ".cmd" extension) for available command line flags. + +@echo off +SETLOCAL ENABLEEXTENSIONS + +set bash_path=%bash_exe_path% + +rem launcher=${$0%.cmd} +set launcher=%~dp0%~n0 + +set sh_path=%launcher:\=/% + +set RUNFILES_MANIFEST_ONLY=1 +set RUNFILES_MANIFEST_FILE=%sh_path%.runfiles/MANIFEST +set all_args=%* +rem replaces $ with \$ in $*, then puts it on the command line +rem Cribbed from here: http://ss64.com/nt/syntax-replace.html +call %bash_path% -c "'%sh_path%' %all_args:$=\$%" |