diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/analysis')
6 files changed, 107 insertions, 38 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/CommandHelper.java b/src/main/java/com/google/devtools/build/lib/analysis/CommandHelper.java index f364257c68..065d3074ad 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/CommandHelper.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/CommandHelper.java @@ -307,6 +307,6 @@ public final class CommandHelper { // Use vanilla /bin/bash for actions running on mac machines. return executionInfo.containsKey(ExecutionRequirements.REQUIRES_DARWIN) ? PathFragment.create("/bin/bash") - : ruleContext.getConfiguration().getFragment(ShellConfiguration.class).getShellExecutable(); + : ShToolchain.getPathOrError(ruleContext); } } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ShToolchain.java b/src/main/java/com/google/devtools/build/lib/analysis/ShToolchain.java new file mode 100644 index 0000000000..c785da410e --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/analysis/ShToolchain.java @@ -0,0 +1,62 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.devtools.build.lib.analysis; + +import com.google.devtools.build.lib.analysis.config.BuildConfiguration; +import com.google.devtools.build.lib.vfs.PathFragment; + +/** Class to work with the shell toolchain, e.g. get the shell interpreter's path. */ +public final class ShToolchain { + + /** + * Returns the shell executable's path, or an empty path if not set. + * + * <p>This method checks the configuration's {@link ShellConfiguration} fragment. + */ + public static PathFragment getPath(BuildConfiguration config) { + PathFragment result = PathFragment.EMPTY_FRAGMENT; + + ShellConfiguration configFragment = + (ShellConfiguration) config.getFragment(ShellConfiguration.class); + if (configFragment != null) { + PathFragment path = configFragment.getShellExecutable(); + if (path != null) { + result = path; + } + } + + return result; + } + + /** + * Returns the shell executable's path, or reports a rule error if the path is empty. + * + * <p>This method checks the rule's configuration's {@link ShellConfiguration} fragment for the + * shell executable's path. If null or empty, the method reports an error against the rule. + */ + public static PathFragment getPathOrError(RuleContext ctx) { + PathFragment result = getPath(ctx.getConfiguration()); + + if (result.isEmpty()) { + ctx.ruleError( + "This rule needs a shell interpreter. Use the --shell_executable=<path> flag to specify" + + " the interpreter's path, e.g. --shell_executable=/usr/local/bin/bash"); + } + + return result; + } + + private ShToolchain() {} +} diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java index 8f9e18aa97..c9a5a2dddc 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java @@ -56,7 +56,6 @@ import com.google.devtools.build.lib.actions.extra.ExtraActionInfo; import com.google.devtools.build.lib.actions.extra.SpawnInfo; import com.google.devtools.build.lib.analysis.AnalysisEnvironment; import com.google.devtools.build.lib.analysis.FilesToRunProvider; -import com.google.devtools.build.lib.analysis.ShellConfiguration; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.collect.nestedset.NestedSet; @@ -680,8 +679,7 @@ public class SpawnAction extends AbstractAction implements ExecutionInfoSpecifie AnalysisEnvironment analysisEnvironment, BuildConfiguration configuration, List<Action> paramFileActions) { - ImmutableList<String> executableArgs = buildExecutableArgs( - configuration.getFragment(ShellConfiguration.class).getShellExecutable()); + ImmutableList<String> executableArgs = buildExecutableArgs(); boolean hasConditionalParamFile = commandLines.stream().anyMatch(c -> c.paramFileInfo != null && !c.paramFileInfo.always()); boolean spillToParamFiles = false; @@ -812,7 +810,7 @@ public class SpawnAction extends AbstractAction implements ExecutionInfoSpecifie */ CommandLine buildCommandLineWithoutParamsFiles() { SpawnActionCommandLine.Builder result = new SpawnActionCommandLine.Builder(); - ImmutableList<String> executableArgs = buildExecutableArgs(null); + ImmutableList<String> executableArgs = buildExecutableArgs(); result.addExecutableArguments(executableArgs); for (CommandLineAndParamFileInfo commandLineAndParamFileInfo : commandLines) { result.addCommandLine(commandLineAndParamFileInfo.commandLine); @@ -851,12 +849,7 @@ public class SpawnAction extends AbstractAction implements ExecutionInfoSpecifie extraActionInfoSupplier); } - private ImmutableList<String> buildExecutableArgs( - @Nullable PathFragment defaultShellExecutable) { - if (isShellCommand && executable == null) { - Preconditions.checkNotNull(defaultShellExecutable); - executable = defaultShellExecutable; - } + private ImmutableList<String> buildExecutableArgs() { Preconditions.checkNotNull(executable); Preconditions.checkNotNull(executableArgs); @@ -1119,18 +1112,16 @@ public class SpawnAction extends AbstractAction implements ExecutionInfoSpecifie } /** - * Sets the executable to be the shell and adds the given command as the - * command to be executed. + * Sets the executable to be the shell and adds the given command as the command to be executed. * - * <p>Note that this will not clear the arguments, so any arguments will - * be passed in addition to the command given here. + * <p>Note that this will not clear the arguments, so any arguments will be passed in addition + * to the command given here. * - * <p>Calling this method overrides any previous values set via calls to - * {@link #setExecutable(Artifact)}, {@link #setJavaExecutable}, or - * {@link #setShellCommand(String)}. + * <p>Calling this method overrides any previous values set via calls to {@link + * #setExecutable(Artifact)}, {@link #setJavaExecutable}, or {@link #setShellCommand(String)}. */ - public Builder setShellCommand(String command) { - this.executable = null; + public Builder setShellCommand(PathFragment shExecutable, String command) { + this.executable = shExecutable; // 0=shell command switch, 1=command this.executableArgs = Lists.newArrayList("-c", command); this.isShellCommand = true; diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java index 416a62a5a0..4f09dde901 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java @@ -30,6 +30,7 @@ import com.google.devtools.build.lib.analysis.CommandHelper; import com.google.devtools.build.lib.analysis.FilesToRunProvider; import com.google.devtools.build.lib.analysis.PseudoAction; import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.ShToolchain; import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext; import com.google.devtools.build.lib.analysis.actions.FileWriteAction; import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction; @@ -654,10 +655,11 @@ public class SkylarkActionFactory implements SkylarkValue { Artifact helperScript = CommandHelper.shellCommandHelperScriptMaybe( ruleContext, command, helperScriptSuffix, executionInfo); + PathFragment shExecutable = ShToolchain.getPathOrError(ruleContext); if (helperScript == null) { - builder.setShellCommand(command); + builder.setShellCommand(shExecutable, command); } else { - builder.setShellCommand(helperScript.getExecPathString()); + builder.setShellCommand(shExecutable, helperScript.getExecPathString()); builder.addInput(helperScript); FilesToRunProvider provider = context.getExecutableRunfiles(helperScript); if (provider != null) { diff --git a/src/main/java/com/google/devtools/build/lib/analysis/test/TestActionBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/test/TestActionBuilder.java index bbce349638..5299d9a8b6 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/test/TestActionBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/test/TestActionBuilder.java @@ -28,6 +28,7 @@ import com.google.devtools.build.lib.analysis.FilesToRunProvider; import com.google.devtools.build.lib.analysis.PrerequisiteArtifacts; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.RunfilesSupport; +import com.google.devtools.build.lib.analysis.ShToolchain; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; @@ -306,14 +307,25 @@ public final class TestActionBuilder { coverageArtifacts.add(coverageArtifact); } - env.registerAction(new TestRunnerAction( - ruleContext.getActionOwner(), inputs, - testSetupScript, collectCoverageScript, - testLog, cacheStatus, - coverageArtifact, - testProperties, extraTestEnv, executionSettings, - shard, run, config, ruleContext.getWorkspaceName(), - useTestRunner)); + PathFragment shExecutable = ShToolchain.getPathOrError(ruleContext); + env.registerAction( + new TestRunnerAction( + ruleContext.getActionOwner(), + inputs, + testSetupScript, + collectCoverageScript, + testLog, + cacheStatus, + coverageArtifact, + testProperties, + extraTestEnv, + executionSettings, + shard, + run, + config, + ruleContext.getWorkspaceName(), + shExecutable, + useTestRunner)); results.add(cacheStatus); } } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/test/TestRunnerAction.java b/src/main/java/com/google/devtools/build/lib/analysis/test/TestRunnerAction.java index b8baf1838a..eb754bdbf4 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/test/TestRunnerAction.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/test/TestRunnerAction.java @@ -33,7 +33,6 @@ import com.google.devtools.build.lib.actions.CommandLineExpansionException; import com.google.devtools.build.lib.actions.ExecException; import com.google.devtools.build.lib.actions.NotifyOnActionCacheHit; import com.google.devtools.build.lib.analysis.RunfilesSupplierImpl; -import com.google.devtools.build.lib.analysis.ShellConfiguration; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.RunUnder; import com.google.devtools.build.lib.buildeventstream.TestFileNameConstants; @@ -80,6 +79,7 @@ public class TestRunnerAction extends AbstractAction implements NotifyOnActionCa private final Artifact cacheStatus; private final PathFragment testWarningsPath; private final PathFragment unusedRunfilesLogPath; + private final PathFragment shExecutable; private final PathFragment splitLogsPath; private final PathFragment splitLogsDir; private final PathFragment undeclaredOutputsDir; @@ -125,18 +125,18 @@ public class TestRunnerAction extends AbstractAction implements NotifyOnActionCa } /** - * Create new TestRunnerAction instance. Should not be called directly. - * Use {@link TestActionBuilder} instead. + * Create new TestRunnerAction instance. Should not be called directly. Use {@link + * TestActionBuilder} instead. * - * @param shardNum The shard number. Must be 0 if totalShards == 0 - * (no sharding). Otherwise, must be >= 0 and < totalShards. + * @param shardNum The shard number. Must be 0 if totalShards == 0 (no sharding). Otherwise, must + * be >= 0 and < totalShards. * @param runNumber test run number */ TestRunnerAction( ActionOwner owner, Iterable<Artifact> inputs, - Artifact testSetupScript, // Must be in inputs - @Nullable Artifact collectCoverageScript, // Must be in inputs, if not null + Artifact testSetupScript, // Must be in inputs + @Nullable Artifact collectCoverageScript, // Must be in inputs, if not null Artifact testLog, Artifact cacheStatus, Artifact coverageArtifact, @@ -147,6 +147,7 @@ public class TestRunnerAction extends AbstractAction implements NotifyOnActionCa int runNumber, BuildConfiguration configuration, String workspaceName, + PathFragment shExecutable, boolean useTestRunner) { super( owner, @@ -182,6 +183,7 @@ public class TestRunnerAction extends AbstractAction implements NotifyOnActionCa this.testWarningsPath = baseDir.getChild("test.warnings"); this.unusedRunfilesLogPath = baseDir.getChild("test.unused_runfiles_log"); this.testStderr = baseDir.getChild("test.err"); + this.shExecutable = shExecutable; this.splitLogsDir = baseDir.getChild("test.raw_splitlogs"); // See note in {@link #getSplitLogsPath} on the choice of file name. this.splitLogsPath = splitLogsDir.getChild("test.splitlogs"); @@ -756,7 +758,7 @@ public class TestRunnerAction extends AbstractAction implements NotifyOnActionCa } public PathFragment getShExecutable() { - return configuration.getFragment(ShellConfiguration.class).getShellExecutable(); + return shExecutable; } public ImmutableMap<String, String> getLocalShellEnvironment() { |