From ae32398146a05ecbe60966b0fe16e409e7b3e3ae Mon Sep 17 00:00:00 2001 From: janakr Date: Fri, 29 Sep 2017 21:11:53 +0200 Subject: Don't symlink into the execroot if possible in SymlinkAction: instead, symlink directly to the target artifact. Also offer the option to not provide the package roots to create the execroot: we would like to avoid the execroot if possible. PiperOrigin-RevId: 170515263 --- .../build/lib/actions/ArtifactFactory.java | 29 ++++++----- .../devtools/build/lib/actions/PackageRoots.java | 50 +++++++++++++++++++ .../devtools/build/lib/analysis/BuildView.java | 31 +++--------- .../analysis/actions/ExecutableSymlinkAction.java | 2 +- .../build/lib/analysis/actions/SymlinkAction.java | 25 +++++++--- .../build/lib/buildtool/ExecutionTool.java | 28 +++++++---- .../build/lib/skyframe/MapAsPackageRoots.java | 56 ++++++++++++++++++++++ .../skyframe/PackageRootsNoSymlinkCreation.java | 46 ++++++++++++++++++ .../build/lib/skyframe/SkyframeAnalysisResult.java | 13 ++--- .../build/lib/skyframe/SkyframeBuildView.java | 10 ++-- .../build/lib/skyframe/SkyframeExecutor.java | 5 ++ 11 files changed, 232 insertions(+), 63 deletions(-) create mode 100644 src/main/java/com/google/devtools/build/lib/actions/PackageRoots.java create mode 100644 src/main/java/com/google/devtools/build/lib/skyframe/MapAsPackageRoots.java create mode 100644 src/main/java/com/google/devtools/build/lib/skyframe/PackageRootsNoSymlinkCreation.java (limited to 'src/main/java/com/google/devtools') diff --git a/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java b/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java index 2a1f6634cc..dd7211e666 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java +++ b/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java @@ -15,7 +15,6 @@ package com.google.devtools.build.lib.actions; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.actions.Artifact.SpecialArtifactType; import com.google.devtools.build.lib.cmdline.PackageIdentifier; import com.google.devtools.build.lib.cmdline.RepositoryName; @@ -45,10 +44,10 @@ public class ArtifactFactory implements ArtifactResolver, ArtifactSerializer, Ar private final SourceArtifactCache sourceArtifactCache = new SourceArtifactCache(); /** - * Map of package names to source root paths so that we can create source - * artifact paths given execPaths in the symlink forest. + * Map of package names to source root paths so that we can create source artifact paths given + * execPaths in the symlink forest. */ - private ImmutableMap packageRoots; + private PackageRoots.PackageRootLookup packageRoots; private ArtifactIdRegistry artifactIdRegistry = new ArtifactIdRegistry(); @@ -140,14 +139,13 @@ public class ArtifactFactory implements ArtifactResolver, ArtifactSerializer, Ar } /** - * Set the set of known packages and their corresponding source artifact - * roots. Must be called exactly once after construction or clear(). + * Set the set of known packages and their corresponding source artifact roots. Must be called + * exactly once after construction or clear(). * - * @param packageRoots the map of package names to source artifact roots to - * use. + * @param packageRoots provider of a source root given a package identifier. */ - public synchronized void setPackageRoots(Map packageRoots) { - this.packageRoots = ImmutableMap.copyOf(packageRoots); + public synchronized void setPackageRoots(PackageRoots.PackageRootLookup packageRoots) { + this.packageRoots = packageRoots; sourceArtifactCache.newBuild(); } @@ -312,7 +310,13 @@ public class ArtifactFactory implements ArtifactResolver, ArtifactSerializer, Ar Root sourceRoot = findSourceRoot(execPath, baseExecPath, baseRoot, repositoryName); Artifact artifact = sourceArtifactCache.getArtifactIfValid(execPath); if (artifact != null) { - Preconditions.checkState(sourceRoot == null || sourceRoot.equals(artifact.getRoot())); + Root artifactRoot = artifact.getRoot(); + Preconditions.checkState( + sourceRoot == null || sourceRoot.equals(artifactRoot), + "roots mismatch: %s %s %s", + sourceRoot, + artifactRoot, + artifact); return artifact; } return createArtifactIfNotValid(sourceRoot, execPath); @@ -338,7 +342,8 @@ public class ArtifactFactory implements ArtifactResolver, ArtifactSerializer, Ar } while (dir != null && !dir.equals(baseExecPath)) { - Root sourceRoot = packageRoots.get(PackageIdentifier.create(repositoryName, dir)); + Root sourceRoot = + packageRoots.getRootForPackage(PackageIdentifier.create(repositoryName, dir)); if (sourceRoot != null) { return sourceRoot; } diff --git a/src/main/java/com/google/devtools/build/lib/actions/PackageRoots.java b/src/main/java/com/google/devtools/build/lib/actions/PackageRoots.java new file mode 100644 index 0000000000..35f7f3fb6d --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/actions/PackageRoots.java @@ -0,0 +1,50 @@ +// Copyright 2017 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.actions; + +import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.cmdline.PackageIdentifier; +import com.google.devtools.build.lib.vfs.Path; +import java.util.Optional; +import javax.annotation.Nullable; + +/** + * An interface that provides information about package's source roots, that is, the paths on disk + * that their BUILD files can be found at. Usually this information is not needed except for when + * planting the symlink forest in the exec root, and when resolving source exec paths to artifacts + * in an {@link ArtifactResolver}. + */ +public interface PackageRoots { + /** + * Gets a map from {@link PackageIdentifier} to {@link Path}. If present, all known packages for + * this build are present in the map. Should only be needed for planting the symlink forest. If it + * is absent, planting the symlink forest is not necessary. + */ + Optional> getPackageRootsMap(); + + PackageRootLookup getPackageRootLookup(); + + /** Interface for getting the source root of a package, given its {@link PackageIdentifier}. */ + interface PackageRootLookup { + /** + * Returns the {@link Root} of a package, given its {@link PackageIdentifier}. May be null if + * the given {@code packageIdentifier} does not correspond to a package in this build. However, + * if there is a unique source root for all packages, this may return that root even if the + * {@code packageIdentifier} given does not correspond to any packages. + */ + @Nullable + Root getRootForPackage(PackageIdentifier packageIdentifier); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java index 07688e6474..61dd9f199c 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java @@ -35,7 +35,7 @@ import com.google.devtools.build.lib.actions.ActionLookupValue; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.ArtifactFactory; import com.google.devtools.build.lib.actions.ArtifactOwner; -import com.google.devtools.build.lib.actions.Root; +import com.google.devtools.build.lib.actions.PackageRoots; import com.google.devtools.build.lib.analysis.DependencyResolver.InconsistentAspectOrderException; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection; @@ -50,7 +50,6 @@ import com.google.devtools.build.lib.analysis.test.CoverageReportActionFactory; import com.google.devtools.build.lib.analysis.test.CoverageReportActionFactory.CoverageReportActionsWrapper; import com.google.devtools.build.lib.analysis.test.InstrumentedFilesProvider; import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.cmdline.PackageIdentifier; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; @@ -95,7 +94,6 @@ import com.google.devtools.build.lib.util.OrderedSetMultimap; import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.util.RegexFilter; -import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.WalkableGraph; @@ -107,7 +105,6 @@ import com.google.devtools.common.options.OptionsBase; import com.google.devtools.common.options.OptionsParsingException; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -348,7 +345,7 @@ public class BuildView { private final ImmutableSet exclusiveTests; @Nullable private final TopLevelArtifactContext topLevelContext; private final ImmutableList aspects; - private final ImmutableMap packageRoots; + private final PackageRoots packageRoots; private final String workspaceName; private AnalysisResult( @@ -362,7 +359,7 @@ public class BuildView { Collection parallelTests, Collection exclusiveTests, TopLevelArtifactContext topLevelContext, - ImmutableMap packageRoots, + PackageRoots packageRoots, String workspaceName) { this.targetsToBuild = ImmutableSet.copyOf(targetsToBuild); this.aspects = ImmutableList.copyOf(aspects); @@ -385,11 +382,8 @@ public class BuildView { return targetsToBuild; } - /** - * The map from package names to the package root where each package was found; this is used to - * set up the symlink tree. - */ - public ImmutableMap getPackageRoots() { + /** @see PackageRoots */ + public PackageRoots getPackageRoots() { return packageRoots; } @@ -1023,19 +1017,8 @@ public class BuildView { * paths with unknown roots to artifacts. */ @VisibleForTesting // for BuildViewTestCase - public void setArtifactRoots(ImmutableMap packageRoots) { - Map rootMap = new HashMap<>(); - Map realPackageRoots = new HashMap<>(); - for (Map.Entry entry : packageRoots.entrySet()) { - Root root = rootMap.get(entry.getValue()); - if (root == null) { - root = Root.asSourceRoot(entry.getValue(), entry.getKey().getRepository().isMain()); - rootMap.put(entry.getValue(), root); - } - realPackageRoots.put(entry.getKey(), root); - } - // Source Artifact roots: - getArtifactFactory().setPackageRoots(realPackageRoots); + public void setArtifactRoots(PackageRoots packageRoots) { + getArtifactFactory().setPackageRoots(packageRoots.getPackageRootLookup()); } /** diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/ExecutableSymlinkAction.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/ExecutableSymlinkAction.java index 4070e5a73a..4cdf2f1e12 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/actions/ExecutableSymlinkAction.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/ExecutableSymlinkAction.java @@ -35,7 +35,7 @@ public final class ExecutableSymlinkAction extends SymlinkAction { @Override public void execute(ActionExecutionContext actionExecutionContext) throws ActionExecutionException { - Path inputPath = actionExecutionContext.getExecRoot().getRelative(getInputPath()); + Path inputPath = getPrimaryInput().getPath(); try { // Validate that input path is a file with the executable bit is set. if (!inputPath.isFile()) { diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/SymlinkAction.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/SymlinkAction.java index b79f152fb7..df3b56f829 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/actions/SymlinkAction.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/SymlinkAction.java @@ -26,6 +26,7 @@ import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; import java.io.IOException; +import javax.annotation.Nullable; /** * Action to create a symbolic link. @@ -34,7 +35,9 @@ public class SymlinkAction extends AbstractAction { private static final String GUID = "349675b5-437c-4da8-891a-7fb98fba6ab5"; - private final PathFragment inputPath; + /** Null when {@link #getPrimaryInput} is the target of the symlink. */ + @Nullable private final PathFragment inputPath; + private final Artifact output; private final String progressMessage; @@ -50,7 +53,10 @@ public class SymlinkAction extends AbstractAction { String progressMessage) { // These actions typically have only one input and one output, which // become the sole and primary in their respective lists. - this(owner, input.getExecPath(), input, output, progressMessage); + super(owner, ImmutableList.of(input), ImmutableList.of(output)); + this.inputPath = null; + this.output = Preconditions.checkNotNull(output); + this.progressMessage = progressMessage; } /** @@ -93,7 +99,7 @@ public class SymlinkAction extends AbstractAction { } public PathFragment getInputPath() { - return inputPath; + return inputPath == null ? getPrimaryInput().getExecPath() : inputPath; } public Path getOutputPath() { @@ -103,9 +109,14 @@ public class SymlinkAction extends AbstractAction { @Override public void execute(ActionExecutionContext actionExecutionContext) throws ActionExecutionException { + Path srcPath; + if (inputPath == null) { + srcPath = getPrimaryInput().getPath(); + } else { + srcPath = actionExecutionContext.getExecRoot().getRelative(inputPath); + } try { - getOutputPath() - .createSymbolicLink(actionExecutionContext.getExecRoot().getRelative(inputPath)); + getOutputPath().createSymbolicLink(srcPath); } catch (IOException e) { throw new ActionExecutionException("failed to create symbolic link '" + Iterables.getOnlyElement(getOutputs()).prettyPrint() @@ -120,7 +131,9 @@ public class SymlinkAction extends AbstractAction { f.addString(GUID); // We don't normally need to add inputs to the key. In this case, however, the inputPath can be // different from the actual input artifact. - f.addPath(inputPath); + if (inputPath != null) { + f.addPath(inputPath); + } return f.hexDigestAndReset(); } 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 af7659b8b8..241084782e 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 @@ -44,6 +44,7 @@ import com.google.devtools.build.lib.actions.ExecutionStrategy; import com.google.devtools.build.lib.actions.Executor; import com.google.devtools.build.lib.actions.ExecutorInitException; import com.google.devtools.build.lib.actions.LocalHostCapacity; +import com.google.devtools.build.lib.actions.PackageRoots; import com.google.devtools.build.lib.actions.ResourceManager; import com.google.devtools.build.lib.actions.ResourceSet; import com.google.devtools.build.lib.actions.SpawnActionContext; @@ -107,6 +108,7 @@ import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.TreeMap; import java.util.UUID; @@ -321,19 +323,23 @@ public class ExecutionTool { } /** - * Performs the execution phase (phase 3) of the build, in which the Builder - * is applied to the action graph to bring the targets up to date. (This - * function will return prior to execution-proper if --nobuild was specified.) + * Performs the execution phase (phase 3) of the build, in which the Builder is applied to the + * action graph to bring the targets up to date. (This function will return prior to + * execution-proper if --nobuild was specified.) + * * @param buildId UUID of the build id * @param analysisResult the analysis phase output * @param buildResult the mutable build result * @param packageRoots package roots collected from loading phase and BuildConfigurationCollection - * creation + * creation. May be empty if {@link + * SkyframeExecutor#getForcedSingleSourceRootIfNoExecrootSymlinkCreation} is false. */ - void executeBuild(UUID buildId, AnalysisResult analysisResult, + void executeBuild( + UUID buildId, + AnalysisResult analysisResult, BuildResult buildResult, BuildConfigurationCollection configurations, - ImmutableMap packageRoots, + PackageRoots packageRoots, TopLevelArtifactContext topLevelArtifactContext) throws BuildFailedException, InterruptedException, TestExecException, AbruptExitException { Stopwatch timer = Stopwatch.createStarted(); @@ -516,15 +522,19 @@ public class ExecutionTool { } } - private void prepare(ImmutableMap packageRoots) - throws ExecutorInitException { + private void prepare(PackageRoots packageRoots) throws ExecutorInitException { + Optional> packageRootMap = + packageRoots.getPackageRootsMap(); + if (!packageRootMap.isPresent()) { + return; + } // Prepare for build. Profiler.instance().markPhase(ProfilePhase.PREPARE); // Plant the symlink forest. try { new SymlinkForest( - packageRoots, getExecRoot(), runtime.getProductName(), env.getWorkspaceName()) + packageRootMap.get(), getExecRoot(), runtime.getProductName(), env.getWorkspaceName()) .plantSymlinkForest(); } catch (IOException e) { throw new ExecutorInitException("Source forest creation failed", e); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/MapAsPackageRoots.java b/src/main/java/com/google/devtools/build/lib/skyframe/MapAsPackageRoots.java new file mode 100644 index 0000000000..baca2e02a1 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skyframe/MapAsPackageRoots.java @@ -0,0 +1,56 @@ +// Copyright 2017 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.skyframe; + +import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.actions.PackageRoots; +import com.google.devtools.build.lib.actions.Root; +import com.google.devtools.build.lib.cmdline.PackageIdentifier; +import com.google.devtools.build.lib.vfs.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/** + * A {@link PackageRoots} backed by a map of package identifiers to paths. A symlink forest must be + * planted for execution. + */ +public class MapAsPackageRoots implements PackageRoots { + private final ImmutableMap packageRootsMap; + + MapAsPackageRoots(ImmutableMap packageRootsMap) { + this.packageRootsMap = packageRootsMap; + } + + @Override + public Optional> getPackageRootsMap() { + return Optional.of(packageRootsMap); + } + + @Override + public PackageRootLookup getPackageRootLookup() { + Map rootMap = new HashMap<>(); + Map realPackageRoots = new HashMap<>(); + for (Map.Entry entry : packageRootsMap.entrySet()) { + Root root = rootMap.get(entry.getValue()); + if (root == null) { + root = Root.asSourceRoot(entry.getValue(), entry.getKey().getRepository().isMain()); + rootMap.put(entry.getValue(), root); + } + realPackageRoots.put(entry.getKey(), root); + } + return realPackageRoots::get; + } +} diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageRootsNoSymlinkCreation.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageRootsNoSymlinkCreation.java new file mode 100644 index 0000000000..499e7413ae --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageRootsNoSymlinkCreation.java @@ -0,0 +1,46 @@ +// Copyright 2017 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.skyframe; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.actions.PackageRoots; +import com.google.devtools.build.lib.actions.Root; +import com.google.devtools.build.lib.cmdline.PackageIdentifier; +import com.google.devtools.build.lib.vfs.Path; +import java.util.Optional; + +/** + * {@link PackageRoots} with a single source root that does not want symlink forest creation, and + * whose {@link PackageRootLookup} returns the unique source root for any given package identifier. + */ +public class PackageRootsNoSymlinkCreation implements PackageRoots { + private final Root sourceRoot; + + @VisibleForTesting + public PackageRootsNoSymlinkCreation(Path sourcePath) { + this.sourceRoot = Root.asSourceRoot(sourcePath, true); + } + + @Override + public Optional> getPackageRootsMap() { + return Optional.empty(); + } + + @Override + public PackageRootLookup getPackageRootLookup() { + return packageIdentifier -> sourceRoot; + } +} diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeAnalysisResult.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeAnalysisResult.java index 7db70f3e62..0314debba0 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeAnalysisResult.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeAnalysisResult.java @@ -14,12 +14,9 @@ package com.google.devtools.build.lib.skyframe; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.actions.PackageRoots; import com.google.devtools.build.lib.analysis.ConfiguredTarget; -import com.google.devtools.build.lib.cmdline.PackageIdentifier; -import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.skyframe.WalkableGraph; - import java.util.Collection; /** @@ -31,15 +28,15 @@ public class SkyframeAnalysisResult { private final ImmutableList configuredTargets; private final WalkableGraph walkableGraph; private final ImmutableList aspects; - private final ImmutableMap packageRoots; + private final PackageRoots packageRoots; - public SkyframeAnalysisResult( + SkyframeAnalysisResult( boolean hasLoadingError, boolean hasAnalysisError, ImmutableList configuredTargets, WalkableGraph walkableGraph, ImmutableList aspects, - ImmutableMap packageRoots) { + PackageRoots packageRoots) { this.hasLoadingError = hasLoadingError; this.hasAnalysisError = hasAnalysisError; this.configuredTargets = configuredTargets; @@ -73,7 +70,7 @@ public class SkyframeAnalysisResult { return aspects; } - public ImmutableMap getPackageRoots() { + public PackageRoots getPackageRoots() { return packageRoots; } } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java index 56477bdbcd..20f1035990 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java @@ -30,6 +30,7 @@ import com.google.devtools.build.lib.actions.ArtifactOwner; import com.google.devtools.build.lib.actions.ArtifactPrefixConflictException; import com.google.devtools.build.lib.actions.MutableActionGraph; import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException; +import com.google.devtools.build.lib.actions.PackageRoots; import com.google.devtools.build.lib.analysis.AnalysisFailureEvent; import com.google.devtools.build.lib.analysis.BlazeDirectories; import com.google.devtools.build.lib.analysis.BuildView; @@ -46,7 +47,6 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection; import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider; import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.cmdline.PackageIdentifier; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.ExtendedEventHandler; @@ -241,8 +241,12 @@ public final class SkyframeBuildView { goodCts.add(ctValue.getConfiguredTarget()); packages.addTransitive(ctValue.getTransitivePackages()); } - ImmutableMap packageRoots = - LoadingPhaseRunner.collectPackageRoots(packages.build().toCollection()); + Path singleSourceRoot = skyframeExecutor.getForcedSingleSourceRootIfNoExecrootSymlinkCreation(); + PackageRoots packageRoots = + singleSourceRoot == null + ? new MapAsPackageRoots( + LoadingPhaseRunner.collectPackageRoots(packages.build().toCollection())) + : new PackageRootsNoSymlinkCreation(singleSourceRoot); if (!result.hasError() && badActions.isEmpty()) { return new SkyframeAnalysisResult( diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java index 97a10780fc..b3159c9134 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java @@ -653,6 +653,11 @@ public abstract class SkyframeExecutor implements WalkableGraphFactory { return true; } + @Nullable + protected Path getForcedSingleSourceRootIfNoExecrootSymlinkCreation() { + return null; + } + @VisibleForTesting protected abstract Injectable injectable(); -- cgit v1.2.3