diff options
author | 2016-02-12 14:41:05 +0000 | |
---|---|---|
committer | 2016-02-12 15:25:33 +0000 | |
commit | dfe2f10e28376407db239f867fb39629b35bf8ad (patch) | |
tree | c08ed71ae4f52aab00c6151bb4b207e82e8fc17a /src/main/java/com/google | |
parent | 0032f17ba372b96201d36ea5716eb994ac3dcf28 (diff) |
Windows: execute build-runfiles through shell.
Needed for #276.
--
MOS_MIGRATED_REVID=114529775
Diffstat (limited to 'src/main/java/com/google')
10 files changed, 97 insertions, 35 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java b/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java index b657e8d1ea..b96a7e7049 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java @@ -292,9 +292,16 @@ public class RunfilesSupport { BuildConfiguration config = context.getConfiguration(); Artifact outputManifest = context.getDerivedArtifact( outputManifestPath, config.getBinDirectory()); - context.getAnalysisEnvironment().registerAction(new SymlinkTreeAction( - context.getActionOwner(), inputManifest, artifactsMiddleman, outputManifest, - /*filesetTree=*/false)); + context + .getAnalysisEnvironment() + .registerAction( + new SymlinkTreeAction( + context.getActionOwner(), + inputManifest, + artifactsMiddleman, + outputManifest, + /*filesetTree=*/ false, + config.getShExecutable())); return outputManifest; } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/SymlinkTreeAction.java b/src/main/java/com/google/devtools/build/lib/analysis/SymlinkTreeAction.java index 17591e0265..05f8ccd466 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/SymlinkTreeAction.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/SymlinkTreeAction.java @@ -23,6 +23,7 @@ import com.google.devtools.build.lib.actions.Executor; import com.google.devtools.build.lib.actions.ResourceSet; import com.google.devtools.build.lib.util.Fingerprint; import com.google.devtools.build.lib.util.Preconditions; +import com.google.devtools.build.lib.vfs.PathFragment; import javax.annotation.Nullable; @@ -37,6 +38,7 @@ public class SymlinkTreeAction extends AbstractAction { private final Artifact inputManifest; private final Artifact outputManifest; private final boolean filesetTree; + private final PathFragment shExecutable; /** * Creates SymlinkTreeAction instance. @@ -52,13 +54,19 @@ public class SymlinkTreeAction extends AbstractAction { * @param filesetTree true if this is fileset symlink tree, * false if this is a runfiles symlink tree. */ - public SymlinkTreeAction(ActionOwner owner, Artifact inputManifest, - @Nullable Artifact artifactMiddleman, Artifact outputManifest, boolean filesetTree) { + public SymlinkTreeAction( + ActionOwner owner, + Artifact inputManifest, + @Nullable Artifact artifactMiddleman, + Artifact outputManifest, + boolean filesetTree, + PathFragment shExecutable) { super(owner, computeInputs(inputManifest, artifactMiddleman), ImmutableList.of(outputManifest)); Preconditions.checkArgument(outputManifest.getPath().getBaseName().equals("MANIFEST")); this.inputManifest = inputManifest; this.outputManifest = outputManifest; this.filesetTree = filesetTree; + this.shExecutable = shExecutable; } private static ImmutableList<Artifact> computeInputs( @@ -114,7 +122,9 @@ public class SymlinkTreeAction extends AbstractAction { public void execute( ActionExecutionContext actionExecutionContext) throws ActionExecutionException, InterruptedException { - actionExecutionContext.getExecutor().getContext(SymlinkTreeActionContext.class) - .createSymlinks(this, actionExecutionContext); + actionExecutionContext + .getExecutor() + .getContext(SymlinkTreeActionContext.class) + .createSymlinks(this, actionExecutionContext, shExecutable); } } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/SymlinkTreeActionContext.java b/src/main/java/com/google/devtools/build/lib/analysis/SymlinkTreeActionContext.java index 9ad9c1ad58..dcf6ecbe4f 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/SymlinkTreeActionContext.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/SymlinkTreeActionContext.java @@ -16,6 +16,7 @@ package com.google.devtools.build.lib.analysis; import com.google.devtools.build.lib.actions.ActionExecutionContext; import com.google.devtools.build.lib.actions.ActionExecutionException; import com.google.devtools.build.lib.actions.Executor.ActionContext; +import com.google.devtools.build.lib.vfs.PathFragment; /** * Action context for symlink tree actions (an action that creates a tree of symlinks). @@ -25,7 +26,9 @@ public interface SymlinkTreeActionContext extends ActionContext { /** * Creates the symlink tree. */ - void createSymlinks(SymlinkTreeAction action, - ActionExecutionContext actionExecutionContext) + void createSymlinks( + SymlinkTreeAction action, + ActionExecutionContext actionExecutionContext, + PathFragment shExecutable) throws ActionExecutionException, InterruptedException; } diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java index 295dc0596a..3f9de4f8ce 100644 --- a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java +++ b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java @@ -178,6 +178,7 @@ public class ExecutionTool { this.runtime = env.getRuntime(); this.request = request; + // Create tools before getting the strategies from the modules as some of them need tools to // determine whether the host actually supports certain strategies (e.g. sandboxing). createToolsSymlinks(); diff --git a/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeHelper.java b/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeHelper.java index ed87aea887..494f4454ca 100644 --- a/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeHelper.java +++ b/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeHelper.java @@ -27,6 +27,7 @@ import com.google.devtools.build.lib.analysis.config.BinTools; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.shell.CommandException; import com.google.devtools.build.lib.util.CommandBuilder; +import com.google.devtools.build.lib.util.OS; import com.google.devtools.build.lib.util.OsUtils; import com.google.devtools.build.lib.vfs.FileSystem; import com.google.devtools.build.lib.vfs.Path; @@ -87,7 +88,7 @@ public final class SymlinkTreeHelper { */ public void createSymlinksUsingCommand(Path execRoot, BuildConfiguration config, BinTools binTools) throws CommandException { - List<String> argv = getSpawnArgumentList(execRoot, binTools); + List<String> argv = getSpawnArgumentList(execRoot, binTools, config.getShExecutable()); CommandBuilder builder = new CommandBuilder(); builder.addArgs(argv); @@ -103,16 +104,20 @@ public final class SymlinkTreeHelper { * block for undetermined period of time. If it is interrupted during * that wait, ExecException will be thrown but interrupted bit will be * preserved. - * - * @param action action instance that requested symlink tree creation + * @param action action instance that requested symlink tree creation * @param actionExecutionContext Services that are in the scope of the action. + * @param shExecutable */ - public void createSymlinks(AbstractAction action, ActionExecutionContext actionExecutionContext, - BinTools binTools) throws ExecException, InterruptedException { + public void createSymlinks( + AbstractAction action, + ActionExecutionContext actionExecutionContext, + BinTools binTools, + PathFragment shExecutable) + throws ExecException, InterruptedException { List<String> args = getSpawnArgumentList( - actionExecutionContext.getExecutor().getExecRoot(), binTools); + actionExecutionContext.getExecutor().getExecRoot(), binTools, shExecutable); try (ResourceHandle handle = - ResourceManager.instance().acquireResources(action, RESOURCE_SET)) { + ResourceManager.instance().acquireResources(action, RESOURCE_SET)) { actionExecutionContext.getExecutor().getSpawnActionContext(action.getMnemonic()).exec( new BaseSpawn.Local(args, ImmutableMap.<String, String>of(), action), actionExecutionContext); @@ -122,10 +127,20 @@ public final class SymlinkTreeHelper { /** * Returns the complete argument list build-runfiles has to be called with. */ - private List<String> getSpawnArgumentList(Path execRoot, BinTools binTools) { + private List<String> getSpawnArgumentList( + Path execRoot, BinTools binTools, PathFragment shExecutable) { PathFragment path = binTools.getExecPath(BUILD_RUNFILES); Preconditions.checkNotNull(path, BUILD_RUNFILES + " not found in embedded tools"); - List<String> args = Lists.newArrayList(execRoot.getRelative(path).getPathString()); + + List<String> args = Lists.newArrayList(); + if (OS.getCurrent() == OS.WINDOWS) { + // During bootstrapping, build-runfiles is a shell script, that cannot be directly + // executed on Windows, so we shell out. + args.add(shExecutable.getPathString()); + args.add("-c"); + args.add("$0 $*"); + } + args.add(execRoot.getRelative(path).getPathString()); if (filesetTree) { args.add("--allow_relative"); diff --git a/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeStrategy.java b/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeStrategy.java index f2b769533a..609ce57998 100644 --- a/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeStrategy.java +++ b/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeStrategy.java @@ -22,6 +22,7 @@ import com.google.devtools.build.lib.analysis.SymlinkTreeAction; import com.google.devtools.build.lib.analysis.SymlinkTreeActionContext; import com.google.devtools.build.lib.analysis.config.BinTools; import com.google.devtools.build.lib.profiler.AutoProfiler; +import com.google.devtools.build.lib.vfs.PathFragment; import java.util.logging.Logger; @@ -42,8 +43,10 @@ public final class SymlinkTreeStrategy implements SymlinkTreeActionContext { } @Override - public void createSymlinks(SymlinkTreeAction action, - ActionExecutionContext actionExecutionContext) + public void createSymlinks( + SymlinkTreeAction action, + ActionExecutionContext actionExecutionContext, + PathFragment shExecutable) throws ActionExecutionException, InterruptedException { Executor executor = actionExecutionContext.getExecutor(); try (AutoProfiler p = @@ -58,7 +61,7 @@ public final class SymlinkTreeStrategy implements SymlinkTreeActionContext { action.getOutputManifest().getPath(), action.isFilesetTree(), helper.getSymlinkTreeRoot()); } else { - helper.createSymlinks(action, actionExecutionContext, binTools); + helper.createSymlinks(action, actionExecutionContext, binTools, shExecutable); } } catch (ExecException e) { throw e.toActionExecutionException( diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java b/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java index 598b4fadbf..e11ff8ecfc 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java @@ -156,8 +156,14 @@ public final class NativeLibs { ruleContext.getActionOwner(), null, symlinks.values(), ruleContext.getConfiguration().getMiddlemanDirectory(), "android_native_libs"); - ruleContext.registerAction(new SymlinkTreeAction( - ruleContext.getActionOwner(), inputManifest, nativeLibsMiddleman, outputManifest, false)); + ruleContext.registerAction( + new SymlinkTreeAction( + ruleContext.getActionOwner(), + inputManifest, + nativeLibsMiddleman, + outputManifest, + false, + ruleContext.getConfiguration().getShExecutable())); return outputManifest; } diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/StandaloneTestStrategy.java b/src/main/java/com/google/devtools/build/lib/rules/test/StandaloneTestStrategy.java index 11b77f564c..d80fff8caf 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/test/StandaloneTestStrategy.java +++ b/src/main/java/com/google/devtools/build/lib/rules/test/StandaloneTestStrategy.java @@ -70,8 +70,9 @@ public class StandaloneTestStrategy extends TestStrategy { throws ExecException, InterruptedException { Path runfilesDir = null; try { - runfilesDir = TestStrategy.getLocalRunfilesDirectory( - action, actionExecutionContext, binTools); + runfilesDir = + TestStrategy.getLocalRunfilesDirectory( + action, actionExecutionContext, binTools, action.getShExecutable()); } catch (ExecException e) { throw new TestExecException(e.getMessage()); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/TestRunnerAction.java b/src/main/java/com/google/devtools/build/lib/rules/test/TestRunnerAction.java index f0860f8295..6fc354b6ff 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/test/TestRunnerAction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/test/TestRunnerAction.java @@ -88,6 +88,7 @@ public class TestRunnerAction extends AbstractAction implements NotifyOnActionCa private final int shardNum; private final int runNumber; private final String workspaceName; + private final PathFragment shExecutable; // Mutable state related to test caching. private boolean checkedCaching = false; @@ -167,6 +168,7 @@ public class TestRunnerAction extends AbstractAction implements NotifyOnActionCa this.undeclaredOutputsAnnotationsPath = undeclaredOutputsAnnotationsDir.getChild("ANNOTATIONS"); this.testInfrastructureFailure = baseDir.getChild(namePrefix + ".infrastructure_failure"); this.workspaceName = workspaceName; + this.shExecutable = configuration.getShExecutable(); Map<String, String> mergedTestEnv = new HashMap<>(configuration.getTestEnv()); mergedTestEnv.putAll(extraTestEnv); @@ -556,6 +558,10 @@ public class TestRunnerAction extends AbstractAction implements NotifyOnActionCa throw new UserExecException("'" + basename + "' not found in test runtime"); } + public PathFragment getShExecutable() { + return shExecutable; + } + /** * The same set of paths as the parent test action, resolved against a given exec root. */ diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/TestStrategy.java b/src/main/java/com/google/devtools/build/lib/rules/test/TestStrategy.java index 3275791cf1..2ac016bbde 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/test/TestStrategy.java +++ b/src/main/java/com/google/devtools/build/lib/rules/test/TestStrategy.java @@ -345,9 +345,12 @@ public abstract class TestStrategy implements TestActionContext { * Returns the runfiles directory associated with the test executable, * creating/updating it if necessary and --build_runfile_links is specified. */ - protected static Path getLocalRunfilesDirectory(TestRunnerAction testAction, - ActionExecutionContext actionExecutionContext, BinTools binTools) throws ExecException, - InterruptedException { + protected static Path getLocalRunfilesDirectory( + TestRunnerAction testAction, + ActionExecutionContext actionExecutionContext, + BinTools binTools, + PathFragment shExecutable) + throws ExecException, InterruptedException { TestTargetExecutionSettings execSettings = testAction.getExecutionSettings(); // If the symlink farm is already created then return the existing directory. If not we @@ -369,7 +372,8 @@ public abstract class TestStrategy implements TestActionContext { long startTime = Profiler.nanoTimeMaybe(); synchronized (execSettings.getInputManifest()) { Profiler.instance().logSimpleTask(startTime, ProfilerTask.WAIT, testAction); - updateLocalRunfilesDirectory(testAction, runfilesDir, actionExecutionContext, binTools); + updateLocalRunfilesDirectory( + testAction, runfilesDir, actionExecutionContext, binTools, shExecutable); } return runfilesDir; @@ -381,9 +385,13 @@ public abstract class TestStrategy implements TestActionContext { * $0.runfiles/MANIFEST, if it exists, are used a proxy for the set of existing symlinks, to avoid * the need for recursion. */ - private static void updateLocalRunfilesDirectory(TestRunnerAction testAction, Path runfilesDir, - ActionExecutionContext actionExecutionContext, BinTools binTools) throws ExecException, - InterruptedException { + private static void updateLocalRunfilesDirectory( + TestRunnerAction testAction, + Path runfilesDir, + ActionExecutionContext actionExecutionContext, + BinTools binTools, + PathFragment shExecutable) + throws ExecException, InterruptedException { Executor executor = actionExecutionContext.getExecutor(); TestTargetExecutionSettings execSettings = testAction.getExecutionSettings(); @@ -401,9 +409,11 @@ public abstract class TestStrategy implements TestActionContext { executor.getEventHandler().handle(Event.progress( "Building runfiles directory for '" + execSettings.getExecutable().prettyPrint() + "'.")); - new SymlinkTreeHelper(execSettings.getInputManifest().getExecPath(), - runfilesDir.relativeTo(executor.getExecRoot()), /* filesetTree= */ false) - .createSymlinks(testAction, actionExecutionContext, binTools); + new SymlinkTreeHelper( + execSettings.getInputManifest().getExecPath(), + runfilesDir.relativeTo(executor.getExecRoot()), /* filesetTree= */ + false) + .createSymlinks(testAction, actionExecutionContext, binTools, shExecutable); executor.getEventHandler().handle(Event.progress(testAction.getProgressMessage())); } |