aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools
diff options
context:
space:
mode:
authorGravatar janakr <janakr@google.com>2017-09-29 21:11:53 +0200
committerGravatar Klaus Aehlig <aehlig@google.com>2017-10-02 10:31:16 +0200
commitae32398146a05ecbe60966b0fe16e409e7b3e3ae (patch)
tree46cd486fb8277c98cdc11a4f427dc370c58354a7 /src/main/java/com/google/devtools
parent5cc6246d429f7d9119b97ce263b4fd6893222e92 (diff)
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
Diffstat (limited to 'src/main/java/com/google/devtools')
-rw-r--r--src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java29
-rw-r--r--src/main/java/com/google/devtools/build/lib/actions/PackageRoots.java50
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/BuildView.java31
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/actions/ExecutableSymlinkAction.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/actions/SymlinkAction.java25
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java28
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/MapAsPackageRoots.java56
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/PackageRootsNoSymlinkCreation.java46
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/SkyframeAnalysisResult.java13
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java5
11 files changed, 232 insertions, 63 deletions
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<PackageIdentifier, Root> 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<PackageIdentifier, Root> 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<ImmutableMap<PackageIdentifier, Path>> 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<ConfiguredTarget> exclusiveTests;
@Nullable private final TopLevelArtifactContext topLevelContext;
private final ImmutableList<AspectValue> aspects;
- private final ImmutableMap<PackageIdentifier, Path> packageRoots;
+ private final PackageRoots packageRoots;
private final String workspaceName;
private AnalysisResult(
@@ -362,7 +359,7 @@ public class BuildView {
Collection<ConfiguredTarget> parallelTests,
Collection<ConfiguredTarget> exclusiveTests,
TopLevelArtifactContext topLevelContext,
- ImmutableMap<PackageIdentifier, Path> 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<PackageIdentifier, Path> 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<PackageIdentifier, Path> packageRoots) {
- Map<Path, Root> rootMap = new HashMap<>();
- Map<PackageIdentifier, Root> realPackageRoots = new HashMap<>();
- for (Map.Entry<PackageIdentifier, Path> 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<PackageIdentifier, Path> 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<PackageIdentifier, Path> packageRoots)
- throws ExecutorInitException {
+ private void prepare(PackageRoots packageRoots) throws ExecutorInitException {
+ Optional<ImmutableMap<PackageIdentifier, Path>> 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<PackageIdentifier, Path> packageRootsMap;
+
+ MapAsPackageRoots(ImmutableMap<PackageIdentifier, Path> packageRootsMap) {
+ this.packageRootsMap = packageRootsMap;
+ }
+
+ @Override
+ public Optional<ImmutableMap<PackageIdentifier, Path>> getPackageRootsMap() {
+ return Optional.of(packageRootsMap);
+ }
+
+ @Override
+ public PackageRootLookup getPackageRootLookup() {
+ Map<Path, Root> rootMap = new HashMap<>();
+ Map<PackageIdentifier, Root> realPackageRoots = new HashMap<>();
+ for (Map.Entry<PackageIdentifier, Path> 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<ImmutableMap<PackageIdentifier, Path>> 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<ConfiguredTarget> configuredTargets;
private final WalkableGraph walkableGraph;
private final ImmutableList<AspectValue> aspects;
- private final ImmutableMap<PackageIdentifier, Path> packageRoots;
+ private final PackageRoots packageRoots;
- public SkyframeAnalysisResult(
+ SkyframeAnalysisResult(
boolean hasLoadingError,
boolean hasAnalysisError,
ImmutableList<ConfiguredTarget> configuredTargets,
WalkableGraph walkableGraph,
ImmutableList<AspectValue> aspects,
- ImmutableMap<PackageIdentifier, Path> packageRoots) {
+ PackageRoots packageRoots) {
this.hasLoadingError = hasLoadingError;
this.hasAnalysisError = hasAnalysisError;
this.configuredTargets = configuredTargets;
@@ -73,7 +70,7 @@ public class SkyframeAnalysisResult {
return aspects;
}
- public ImmutableMap<PackageIdentifier, Path> 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<PackageIdentifier, Path> 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();