diff options
3 files changed, 67 insertions, 15 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java index 87d2253a14..d902395c54 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java @@ -56,6 +56,7 @@ import com.google.devtools.build.lib.rules.java.JavaCommon; import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider; import com.google.devtools.build.lib.rules.java.JavaSemantics; import com.google.devtools.build.lib.rules.java.JavaTargetAttributes; +import com.google.devtools.build.lib.vfs.PathFragment; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -1112,14 +1113,16 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { .addInputArgument(javaResourceZip); } - ImmutableList<Artifact> nativeSymlinks = nativeLibs.createApkBuilderSymlinks(ruleContext); - if (!nativeSymlinks.isEmpty()) { + Artifact nativeSymlinks = nativeLibs.createApkBuilderSymlinks(ruleContext); + if (nativeSymlinks != null) { + PathFragment nativeSymlinksDir = nativeSymlinks.getExecPath().getParentDirectory(); actionBuilder - .addInputs(nativeSymlinks) + .addInputManifest(nativeSymlinks, nativeSymlinksDir) + .addInput(nativeSymlinks) + .addInputs(nativeLibs.getAllNativeLibs()) .addArgument("-nf") // If the native libs are "foo/bar/x86/foo.so", we need to pass "foo/bar" here - .addArgument(nativeSymlinks.get(0).getExecPath() - .getParentDirectory().getParentDirectory().getPathString()); + .addArgument(nativeSymlinksDir.getPathString()); } if (nativeLibs.getName() != null) { 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 7c48f1bdc8..1b5f1c9f9e 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 @@ -15,18 +15,22 @@ package com.google.devtools.build.lib.rules.android; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.SourceManifestAction; +import com.google.devtools.build.lib.analysis.SourceManifestAction.ManifestType; +import com.google.devtools.build.lib.analysis.SymlinkTreeAction; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.analysis.actions.FileWriteAction; -import com.google.devtools.build.lib.analysis.actions.SymlinkAction; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.rules.cpp.CcLinkParams; import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider; import com.google.devtools.build.lib.rules.cpp.LinkerInput; import com.google.devtools.build.lib.rules.nativedeps.NativeDepsHelper; +import com.google.devtools.build.lib.vfs.PathFragment; import java.util.Collection; import java.util.HashMap; @@ -107,21 +111,38 @@ public final class NativeLibs { return nativeLibs; } - public ImmutableList<Artifact> createApkBuilderSymlinks(RuleContext ruleContext) { - ImmutableList.Builder<Artifact> result = ImmutableList.builder(); + public ImmutableSet<Artifact> getAllNativeLibs() { + ImmutableSet.Builder<Artifact> result = ImmutableSet.builder(); + + for (Iterable<Artifact> libs : nativeLibs.values()) { + result.addAll(libs); + } + + return result.build(); + } + + public Artifact createApkBuilderSymlinks(RuleContext ruleContext) { + Map<PathFragment, Artifact> symlinks = new LinkedHashMap<>(); for (Map.Entry<String, Iterable<Artifact>> entry : nativeLibs.entrySet()) { String arch = entry.getKey(); for (Artifact lib : entry.getValue()) { - Artifact symlink = AndroidBinary.getDxArtifact(ruleContext, - "native_symlinks/" + arch + "/" + lib.getExecPath().getBaseName()); - ruleContext.registerAction(new SymlinkAction( - ruleContext.getActionOwner(), lib, symlink, - "Symlinking Android native library for " + ruleContext.getLabel())); - result.add(symlink); + symlinks.put(new PathFragment(arch + "/" + lib.getExecPath().getBaseName()), lib); } } - return result.build(); + if (symlinks.isEmpty()) { + return null; + } + + Artifact inputManifest = AndroidBinary.getDxArtifact(ruleContext, "native_symlinks.manifest"); + ruleContext.registerAction(new SourceManifestAction.Builder( + ManifestType.SOURCE_SYMLINKS, ruleContext.getActionOwner(), inputManifest) + .addRootSymlinks(symlinks) + .build()); + Artifact outputManifest = AndroidBinary.getDxArtifact(ruleContext, "native_symlinks/MANIFEST"); + ruleContext.registerAction(new SymlinkTreeAction( + ruleContext.getActionOwner(), inputManifest, outputManifest, false)); + return outputManifest; } /** diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java index ab6f345d1d..9bf3959e3e 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java @@ -20,6 +20,7 @@ import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.base.Predicates; +import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -62,6 +63,8 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.Runfiles; import com.google.devtools.build.lib.analysis.RunfilesProvider; import com.google.devtools.build.lib.analysis.RunfilesSupport; +import com.google.devtools.build.lib.analysis.SourceManifestAction; +import com.google.devtools.build.lib.analysis.SymlinkTreeAction; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; import com.google.devtools.build.lib.analysis.WorkspaceStatusAction; @@ -140,6 +143,7 @@ import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; @@ -1510,4 +1514,28 @@ public abstract class BuildViewTestCase extends FoundationTestCase { private String convertLabelToPath(String label) { return label.replace(':', '/').substring(1); } + + protected Map<String, String> getSymlinkTreeManifest(Artifact outputManifest) throws Exception { + SymlinkTreeAction symlinkTreeAction = (SymlinkTreeAction) getGeneratingAction(outputManifest); + Artifact inputManifest = Iterables.getOnlyElement(symlinkTreeAction.getInputs()); + SourceManifestAction inputManifestAction = + (SourceManifestAction) getGeneratingAction(inputManifest); + // Ask the manifest to write itself to a byte array so that we can + // read its contents. + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + inputManifestAction.writeOutputFile(stream, reporter); + String contents = stream.toString(); + + // Get the file names from the manifest output. + ImmutableMap.Builder<String, String> result = ImmutableMap.builder(); + for (String line : Splitter.on('\n').split(contents)) { + int space = line.indexOf(' '); + if (space < 0) { + continue; + } + result.put(line.substring(0, space), line.substring(space + 1)); + } + + return result.build(); + } } |