Symlink creation: add flag for in-process creation
This is in preparation for skipping manifest creation. If we don't have
an input manifest and no output service, we can't fall back to the
subprocess method, which requires a manifest. Instead, we will fall back
to an in-process implementation. This should be rare.
This also provides a fallback mechanism if the embedded tool is
unavailable, and we may switch this on by default if the performance is
acceptable.
PiperOrigin-RevId: 282895566
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 e5e2124..5aefaa4 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
@@ -18,6 +18,7 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
+import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.EnvironmentalExecException;
import com.google.devtools.build.lib.actions.ExecException;
import com.google.devtools.build.lib.shell.Command;
@@ -33,8 +34,10 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Helper class responsible for the symlink tree creation. Used to generate runfiles and fileset
@@ -66,6 +69,25 @@
return symlinkTreeRoot;
}
+ /** Creates a symlink tree using direct system calls. */
+ public void createSymlinksDirectly(Path symlinkTreeRoot, Map<PathFragment, Artifact> symlinks)
+ throws IOException {
+ Preconditions.checkState(!filesetTree);
+ Set<Path> dirs = new HashSet<>();
+ for (Map.Entry<PathFragment, Artifact> e : symlinks.entrySet()) {
+ Path symlinkPath = symlinkTreeRoot.getRelative(e.getKey());
+ Path parentDirectory = symlinkPath.getParentDirectory();
+ if (dirs.add(parentDirectory)) {
+ parentDirectory.createDirectoryAndParents();
+ }
+ if (e.getValue() == null) {
+ FileSystemUtils.createEmptyFile(symlinkPath);
+ } else {
+ symlinkPath.createSymbolicLink(e.getValue().getPath().asFragment());
+ }
+ }
+ }
+
/**
* Creates symlink tree and output manifest using the {@code build-runfiles.cc} tool.
*