aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2017-11-30 13:03:50 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2017-11-30 13:05:59 -0800
commit8c5e290dfab3cab378a9ca107ecdd6267403cd4b (patch)
treefa353656eed2053e167ab18d8c89e27085616000 /src/main/java/com/google
parent5ddd804fac00ea075fbbafaa5aff9c0ecf56bc42 (diff)
Suppress ThinLTO indexing for linkstatic tests
ThinLTO and static linking of test suites is a bad combination since it results in a combinatorial explosion of the ThinLTO backends - each object file needs a separate LTO backend action per target. If you are static linking O(N) objects, and have O(M) targets, with ThinLTO you will get O(N*M) LTO backend jobs. This is because the whole program optimization step is per-target, and may make different decisions affecting the object files. With dynamic linking it isn't a problem, since the ThinLTO optimization happens at the .so level, which are shared across tests. And for statically-linked cc_binary it hasn't been an issue since typically only a single target is built at a time, unlike tests. In general it isn't incredibly useful to run tests with ThinLTO, although most projects are in the habit of running their tests with the same options that they use to optimize their main binary (and most blueprints seem to be set up to share options between them). With ThinLTO since it is doing whole-program optimization, you are getting different whole-program optimizations for the main binary and each test binary, so it isn't the case that this will optimize the tests in the same exact way as the main binary anyway. Therefore, when creating LTO backends for statically-linked *_test targets, skip the LTO indexing stage, and create (or use if already created) shared dummy LTO backend actions for each library. These LTO backends are fed an empty index, so they don't do any whole program optimization and are safe to share. Enable this under a new feature so that we can enable it by default via blazerc but provide a facility to disable if needed. RELNOTES: None PiperOrigin-RevId: 177495858
Diffstat (limited to 'src/main/java/com/google')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java289
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java45
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java4
6 files changed, 286 insertions, 67 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
index 5ad409bd86..9cdcef616c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
@@ -356,7 +356,9 @@ public abstract class CcBinary implements RuleConfiguredTargetFactory {
linkActionBuilder.setLtoIndexing(true);
linkActionBuilder.setUsePicForLtoBackendActions(usePic);
CppLinkAction indexAction = linkActionBuilder.build();
- ruleContext.registerAction(indexAction);
+ if (indexAction != null) {
+ ruleContext.registerAction(indexAction);
+ }
linkActionBuilder.setLtoIndexing(false);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
index 063066f927..a546292c2d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
@@ -153,6 +153,8 @@ public class CppLinkActionBuilder {
@Deprecated
public static final String IS_NOT_CC_TEST_LINK_ACTION_VARIABLE = "is_not_cc_test_link_action";
+ public static final String SHARED_NONLTO_BACKEND_ROOT_PREFIX = "shared.nonlto";
+
// Builder-only
// Null when invoked from tests (e.g. via createTestBuilder).
@Nullable private final RuleContext ruleContext;
@@ -498,7 +500,8 @@ public class CppLinkActionBuilder {
lib.getArtifactCategory(),
lib.getLibraryIdentifier(),
newObjectFilesBuilder.build(),
- lib.getLtoBitcodeFiles()));
+ lib.getLtoBitcodeFiles(),
+ /* sharedNonLtoBackends= */ null));
}
return uniqueLibrariesBuilder.build();
}
@@ -519,9 +522,83 @@ public class CppLinkActionBuilder {
return false;
}
+ /**
+ * An implementation of {@link
+ * com.google.devtools.build.lib.rules.cpp.CppLinkAction.LinkArtifactFactory} that can create
+ * artifacts anywhere.
+ *
+ * <p>Necessary when the LTO backend actions of libraries should be shareable, and thus cannot be
+ * under the package directory.
+ */
+ private static final CppLinkAction.LinkArtifactFactory SHAREABLE_LINK_ARTIFACT_FACTORY =
+ new CppLinkAction.LinkArtifactFactory() {
+ @Override
+ public Artifact create(
+ RuleContext ruleContext,
+ BuildConfiguration configuration,
+ PathFragment rootRelativePath) {
+ return ruleContext.getShareableArtifact(
+ rootRelativePath,
+ configuration.getBinDirectory(ruleContext.getRule().getRepository()));
+ }
+ };
+
+ /*
+ * Create an LtoBackendArtifacts object, using the appropriate constructor depending on whether
+ * the associated ThinLTO link will utilize LTO indexing (therefore unique LTO backend actions),
+ * or not (and therefore the library being linked will create a set of shared LTO backends).
+ */
+ private LtoBackendArtifacts createLtoArtifact(
+ Artifact bitcodeFile,
+ Map<PathFragment, Artifact> allBitcode,
+ PathFragment ltoOutputRootPrefix,
+ boolean createSharedNonLto,
+ List<String> argv) {
+ // Depending on whether LTO indexing is allowed, generate an LTO backend
+ // that will be fed the results of the indexing step, or a dummy LTO backend
+ // that simply compiles the bitcode into native code without any index-based
+ // cross module optimization.
+ LtoBackendArtifacts ltoArtifact =
+ createSharedNonLto
+ ? new LtoBackendArtifacts(
+ ltoOutputRootPrefix,
+ bitcodeFile,
+ ruleContext,
+ configuration,
+ SHAREABLE_LINK_ARTIFACT_FACTORY,
+ featureConfiguration,
+ toolchain,
+ fdoSupport,
+ usePicForLtoBackendActions,
+ CppHelper.useFission(cppConfiguration, toolchain),
+ argv)
+ : new LtoBackendArtifacts(
+ ltoOutputRootPrefix,
+ bitcodeFile,
+ allBitcode,
+ ruleContext,
+ configuration,
+ linkArtifactFactory,
+ featureConfiguration,
+ toolchain,
+ fdoSupport,
+ usePicForLtoBackendActions,
+ CppHelper.useFission(cppConfiguration, toolchain),
+ argv);
+ return ltoArtifact;
+ }
+
+ private List<String> getLtoBackendCommandLineOptions(ImmutableSet<String> features) {
+ List<String> argv = new ArrayList<>();
+ argv.addAll(toolchain.getLinkOptions());
+ argv.addAll(cppConfiguration.getCompilerOptions(features));
+ return argv;
+ }
+
private Iterable<LtoBackendArtifacts> createLtoArtifacts(
PathFragment ltoOutputRootPrefix,
NestedSet<LibraryToLink> uniqueLibraries,
+ boolean allowLtoIndexing,
ImmutableSet<String> features) {
Set<Artifact> compiled = new LinkedHashSet<>();
for (LibraryToLink lib : uniqueLibraries) {
@@ -535,9 +612,9 @@ public class CppLinkActionBuilder {
if (!lib.containsObjectFiles()) {
continue;
}
- for (Artifact a : lib.getObjectFiles()) {
- if (compiled.contains(a)) {
- allBitcode.put(a.getExecPath(), a);
+ for (Artifact objectFile : lib.getObjectFiles()) {
+ if (compiled.contains(objectFile)) {
+ allBitcode.put(objectFile.getExecPath(), objectFile);
}
}
}
@@ -547,30 +624,78 @@ public class CppLinkActionBuilder {
}
}
- List<String> argv = new ArrayList<>();
- argv.addAll(toolchain.getLinkOptions());
- argv.addAll(cppConfiguration.getCompilerOptions(features));
+ List<String> argv = getLtoBackendCommandLineOptions(features);
ImmutableList.Builder<LtoBackendArtifacts> ltoOutputs = ImmutableList.builder();
- for (Artifact a : allBitcode.values()) {
- LtoBackendArtifacts ltoArtifacts =
- new LtoBackendArtifacts(
- ltoOutputRootPrefix,
- a,
- allBitcode,
- ruleContext,
- configuration,
- linkArtifactFactory,
- featureConfiguration,
- toolchain,
- fdoSupport,
- usePicForLtoBackendActions,
- CppHelper.useFission(cppConfiguration, toolchain),
- argv);
- ltoOutputs.add(ltoArtifacts);
+ for (LibraryToLink lib : uniqueLibraries) {
+ if (!lib.containsObjectFiles()) {
+ continue;
+ }
+ // We will create new LTO backends whenever we are performing LTO indexing, in which case
+ // each target linking this library needs a unique set of LTO backends.
+ for (Artifact objectFile : lib.getObjectFiles()) {
+ if (compiled.contains(objectFile)) {
+ if (allowLtoIndexing) {
+ LtoBackendArtifacts ltoArtifacts =
+ createLtoArtifact(
+ objectFile,
+ allBitcode,
+ ltoOutputRootPrefix,
+ /* createSharedNonLto= */ false,
+ argv);
+ ltoOutputs.add(ltoArtifacts);
+ } else {
+ // We should have created shared LTO backends when the library was created.
+ Preconditions.checkNotNull(lib.getSharedNonLtoBackends());
+ LtoBackendArtifacts ltoArtifacts =
+ lib.getSharedNonLtoBackends().getOrDefault(objectFile, null);
+ Preconditions.checkNotNull(ltoArtifacts);
+ ltoOutputs.add(ltoArtifacts);
+ }
+ }
+ }
}
+ for (LinkerInput input : objectFiles) {
+ if (this.ltoBitcodeFiles.containsKey(input.getArtifact())) {
+ LtoBackendArtifacts ltoArtifacts =
+ createLtoArtifact(
+ input.getArtifact(), allBitcode, ltoOutputRootPrefix, !allowLtoIndexing, argv);
+ ltoOutputs.add(ltoArtifacts);
+ }
+ }
+
return ltoOutputs.build();
}
+ private ImmutableMap<Artifact, LtoBackendArtifacts> createSharedNonLtoArtifacts(
+ ImmutableSet<String> features, boolean isLtoIndexing) {
+ // Only create the shared LTO artifacts for a statically linked library that has bitcode files.
+ if (ltoBitcodeFiles == null || isLtoIndexing || linkType.staticness() != Staticness.STATIC) {
+ return ImmutableMap.<Artifact, LtoBackendArtifacts>of();
+ }
+
+ PathFragment ltoOutputRootPrefix = PathFragment.create(SHARED_NONLTO_BACKEND_ROOT_PREFIX);
+
+ List<String> argv = getLtoBackendCommandLineOptions(features);
+
+ ImmutableMap.Builder<Artifact, LtoBackendArtifacts> sharedNonLtoBackends =
+ ImmutableMap.builder();
+
+ for (LinkerInput input : objectFiles) {
+ if (this.ltoBitcodeFiles.containsKey(input.getArtifact())) {
+ LtoBackendArtifacts ltoArtifacts =
+ createLtoArtifact(
+ input.getArtifact(),
+ /* allBitcode= */ null,
+ ltoOutputRootPrefix,
+ /* createSharedNonLto= */ true,
+ argv);
+ sharedNonLtoBackends.put(input.getArtifact(), ltoArtifacts);
+ }
+ }
+
+ return sharedNonLtoBackends.build();
+ }
+
@VisibleForTesting
boolean canSplitCommandLine() {
if (fake) {
@@ -628,9 +753,44 @@ public class CppLinkActionBuilder {
boolean needWholeArchive =
wholeArchive
|| needWholeArchive(linkStaticness, linkType, linkopts, isNativeDeps, cppConfiguration);
+ // Disallow LTO indexing for tests that link statically. Otherwise this will provoke
+ // Blaze OOM errors in the case where multiple static tests are invoked together,
+ // since each target needs a separate set of LTO Backend actions. With dynamic linking,
+ // the targest share the dynamic libraries which were produced via smaller subsets of
+ // LTO indexing/backends. ThinLTO on the tests will be different than the ThinLTO
+ // optimizations applied to the associated main binaries anyway.
+ boolean allowLtoIndexing =
+ linkStaticness == LinkStaticness.DYNAMIC
+ || !ruleContext.isTestTarget()
+ || !featureConfiguration.isEnabled(
+ CppRuleClasses.THIN_LTO_LINKSTATIC_TESTS_USE_SHARED_NONLTO_BACKENDS);
+
+ // ruleContext can only be null during testing. This is kind of ugly.
+ final ImmutableSet<String> features =
+ (ruleContext == null) ? ImmutableSet.of() : ruleContext.getFeatures();
NestedSet<LibraryToLink> originalUniqueLibraries = libraries.build();
+ PathFragment ltoOutputRootPrefix = null;
+ if (isLtoIndexing) {
+ Preconditions.checkState(allLtoArtifacts == null);
+ ltoOutputRootPrefix =
+ allowLtoIndexing
+ ? FileSystemUtils.appendExtension(output.getRootRelativePath(), ".lto")
+ : PathFragment.create(SHARED_NONLTO_BACKEND_ROOT_PREFIX);
+ // Use the originalUniqueLibraries which contains the full bitcode files
+ // needed by the LTO backends (as opposed to the minimized bitcode files
+ // containing just the summaries and symbol information that can be used by
+ // the LTO indexing step).
+ allLtoArtifacts =
+ createLtoArtifacts(
+ ltoOutputRootPrefix, originalUniqueLibraries, allowLtoIndexing, features);
+
+ if (!allowLtoIndexing) {
+ return null;
+ }
+ }
+
// Get the set of object files and libraries containing the correct
// inputs for this link, depending on whether this is LTO indexing or
// a native link.
@@ -656,40 +816,32 @@ public class CppLinkActionBuilder {
CppHelper.getArchiveType(cppConfiguration, toolchain))))
.build();
- // ruleContext can only be null during testing. This is kind of ugly.
- final ImmutableSet<String> features =
- (ruleContext == null) ? ImmutableSet.of() : ruleContext.getFeatures();
-
- final LibraryToLink outputLibrary = linkType.isExecutable()
- ? null
- : LinkerInputs.newInputLibrary(output,
- linkType.getLinkerOutput(),
- libraryIdentifier,
- objectArtifacts, this.ltoBitcodeFiles);
+ final LibraryToLink outputLibrary =
+ linkType.isExecutable()
+ ? null
+ : LinkerInputs.newInputLibrary(
+ output,
+ linkType.getLinkerOutput(),
+ libraryIdentifier,
+ objectArtifacts,
+ ltoBitcodeFiles,
+ createSharedNonLtoArtifacts(features, isLtoIndexing));
final LibraryToLink interfaceOutputLibrary =
(interfaceOutput == null)
? null
- : LinkerInputs.newInputLibrary(interfaceOutput,
+ : LinkerInputs.newInputLibrary(
+ interfaceOutput,
ArtifactCategory.DYNAMIC_LIBRARY,
libraryIdentifier,
- objectArtifacts, this.ltoBitcodeFiles);
+ objectArtifacts,
+ ltoBitcodeFiles,
+ /* sharedNonLtoBackends= */ null);
final ImmutableMap<Artifact, Artifact> linkstampMap =
mapLinkstampsToOutputs(linkstamps, ruleContext, configuration, output, linkArtifactFactory);
- PathFragment ltoOutputRootPrefix = null;
- if (isLtoIndexing && allLtoArtifacts == null) {
- ltoOutputRootPrefix =
- FileSystemUtils.appendExtension(
- output.getRootRelativePath(), ".lto");
- // Use the originalUniqueLibraries which contains the full bitcode files
- // needed by the LTO backends (as opposed to the minimized bitcode files
- // that can be used by the LTO indexing step).
- allLtoArtifacts = createLtoArtifacts(ltoOutputRootPrefix, originalUniqueLibraries, features);
- }
-
@Nullable Artifact thinltoParamFile = null;
- if (allLtoArtifacts != null) {
+ if (allowLtoIndexing && allLtoArtifacts != null) {
// Create artifact for the file that the LTO indexing step will emit
// object file names into for any that were included in the link as
// determined by the linker's symbol resolution. It will be used to
@@ -736,6 +888,7 @@ public class CppLinkActionBuilder {
// Add build variables necessary to template link args into the crosstool.
Variables.Builder buildVariablesBuilder = new Variables.Builder(toolchain.getBuildVariables());
+ Preconditions.checkState(!isLtoIndexing || allowLtoIndexing);
CppLinkVariablesExtension variablesExtension =
isLtoIndexing
? new CppLinkVariablesExtension(
@@ -748,6 +901,8 @@ public class CppLinkActionBuilder {
paramFile,
thinltoParamFile,
ltoOutputRootPrefix,
+ // If we reached here, then allowLtoIndexing must be true (checked above).
+ /* allowLtoIndexing= */ true,
/* interfaceLibraryBuilder= */ null,
/* interfaceLibraryOutput= */ null)
: new CppLinkVariablesExtension(
@@ -758,8 +913,9 @@ public class CppLinkActionBuilder {
runtimeLinkerInputs,
output,
paramFile,
- thinltoParamFile,
+ allowLtoIndexing ? thinltoParamFile : null,
/* ltoOutputRootPrefix= */ PathFragment.EMPTY_FRAGMENT,
+ allowLtoIndexing,
toolchain.getInterfaceSoBuilder(),
interfaceOutput);
variablesExtension.addVariables(buildVariablesBuilder);
@@ -1407,6 +1563,7 @@ public class CppLinkActionBuilder {
private final Artifact paramFile;
private final Artifact thinltoParamFile;
private final PathFragment ltoOutputRootPrefix;
+ private final boolean allowLtoIndexing;
private final LinkArgCollector linkArgCollector = new LinkArgCollector();
@@ -1420,6 +1577,7 @@ public class CppLinkActionBuilder {
Artifact paramFile,
Artifact thinltoParamFile,
PathFragment ltoOutputRootPrefix,
+ boolean allowLtoIndexing,
Artifact interfaceLibraryBuilder,
Artifact interfaceLibraryOutput) {
this.configuration = configuration;
@@ -1433,6 +1591,7 @@ public class CppLinkActionBuilder {
this.paramFile = paramFile;
this.thinltoParamFile = thinltoParamFile;
this.ltoOutputRootPrefix = ltoOutputRootPrefix;
+ this.allowLtoIndexing = allowLtoIndexing;
addInputFileLinkOptions(linkArgCollector);
}
@@ -1841,7 +2000,7 @@ public class CppLinkActionBuilder {
// Those files will be included directly in the link (and not wrapped
// in --start-lib/--end-lib) to ensure consistency between the two link
// steps.
- Preconditions.checkState(ltoMap == null || thinltoParamFile != null);
+ Preconditions.checkState(ltoMap == null || thinltoParamFile != null || !allowLtoIndexing);
// start-lib/end-lib library: adds its input object files.
if (Link.useStartEndLib(input, CppHelper.getArchiveType(cppConfiguration, toolchain))) {
@@ -1849,12 +2008,18 @@ public class CppLinkActionBuilder {
if (!Iterables.isEmpty(archiveMembers)) {
ImmutableList.Builder<String> nonLtoArchiveMembersBuilder = ImmutableList.builder();
for (Artifact member : archiveMembers) {
- if (ltoMap != null && ltoMap.remove(member) != null) {
- // The LTO artifacts that should be included in the final link
- // are listed in the thinltoParamFile. When ltoMap is non-null
- // the backend artifact may be missing due to libraries that list .o
- // files explicitly, or generate .o files from assembler.
- continue;
+ Artifact a;
+ if (ltoMap != null && (a = ltoMap.remove(member)) != null) {
+ // When ltoMap is non-null the backend artifact may be missing due to libraries that
+ // list .o files explicitly, or generate .o files from assembler.
+ if (allowLtoIndexing) {
+ // The LTO artifacts that should be included in the final link
+ // are listed in the thinltoParamFile, generated by the LTO indexing.
+ continue;
+ }
+ // No LTO indexing step, so use the LTO backend's generated artifact directly
+ // instead of the bitcode object.
+ member = a;
}
nonLtoArchiveMembersBuilder.add(member.getExecPathString());
}
@@ -1877,10 +2042,16 @@ public class CppLinkActionBuilder {
|| (isRuntimeLinkerInput && isAlwaysLinkStaticLibrary && !needWholeArchive);
Artifact inputArtifact = input.getArtifact();
- if (ltoMap != null && ltoMap.remove(inputArtifact) != null) {
- // The LTO artifacts that should be included in the final link
- // are listed in the thinltoParamFile.
- return;
+ Artifact a;
+ if (ltoMap != null && (a = ltoMap.remove(inputArtifact)) != null) {
+ if (allowLtoIndexing) {
+ // The LTO artifacts that should be included in the final link
+ // are listed in the thinltoParamFile, generated by the LTO indexing.
+ return;
+ }
+ // No LTO indexing step, so use the LTO backend's generated artifact directly
+ // instead of the bitcode object.
+ inputArtifact = a;
}
String name;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java
index ce582c3dde..466b3ceed3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java
@@ -1449,7 +1449,9 @@ public final class CppModel {
dynamicLinkActionBuilder.setLtoIndexing(true);
dynamicLinkActionBuilder.setUsePicForLtoBackendActions(usePicForSharedLibs);
CppLinkAction indexAction = dynamicLinkActionBuilder.build();
- env.registerAction(indexAction);
+ if (indexAction != null) {
+ env.registerAction(indexAction);
+ }
dynamicLinkActionBuilder.setLtoIndexing(false);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
index 453ab635a2..ed54a38f70 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
@@ -288,6 +288,13 @@ public class CppRuleClasses {
public static final String THIN_LTO = "thin_lto";
/**
+ * A string constant for allowing use of shared LTO backend actions for linkstatic tests building
+ * with ThinLTO.
+ */
+ public static final String THIN_LTO_LINKSTATIC_TESTS_USE_SHARED_NONLTO_BACKENDS =
+ "thin_lto_linkstatic_tests_use_shared_nonlto_backends";
+
+ /**
* A string constant for the PDB file generation feature, should only be used for toolchains
* targeting Windows that include a linker producing PDB files
*/
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java
index f060d5de56..3dbbd3c722 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java
@@ -139,6 +139,15 @@ public abstract class LinkerInputs {
ImmutableMap<Artifact, Artifact> getLtoBitcodeFiles();
/**
+ * Return a map of object file artifacts to associated LTOBackendArtifacts objects generated
+ * when LTO backend actions are to be shared among different targets using this library. This is
+ * the case when we opt not to perform the LTO indexing step, such as when building tests with
+ * static linking. ThinLTO is otherwise too expensive when statically linking tests, due to the
+ * number of LTO backends that can be generated for a single blaze test invocation.
+ */
+ ImmutableMap<Artifact, LtoBackendArtifacts> getSharedNonLtoBackends();
+
+ /**
* Return the identifier for the library. This is used for de-duplication of linker inputs: two
* libraries should have the same identifier iff they are in fact the same library but linked
* in a different way (e.g. static/dynamic, PIC/no-PIC)
@@ -208,6 +217,12 @@ public abstract class LinkerInputs {
}
@Override
+ public ImmutableMap<Artifact, LtoBackendArtifacts> getSharedNonLtoBackends() {
+ throw new IllegalStateException(
+ "LinkerInputs: does not support getSharedNonLtoBackends: " + this);
+ }
+
+ @Override
public Artifact getOriginalLibraryArtifact() {
return libraryArtifact;
}
@@ -244,13 +259,15 @@ public abstract class LinkerInputs {
private final String libraryIdentifier;
private final Iterable<Artifact> objectFiles;
private final ImmutableMap<Artifact, Artifact> ltoBitcodeFiles;
+ private final ImmutableMap<Artifact, LtoBackendArtifacts> sharedNonLtoBackends;
private CompoundLibraryToLink(
Artifact libraryArtifact,
ArtifactCategory category,
String libraryIdentifier,
Iterable<Artifact> objectFiles,
- ImmutableMap<Artifact, Artifact> ltoBitcodeFiles) {
+ ImmutableMap<Artifact, Artifact> ltoBitcodeFiles,
+ ImmutableMap<Artifact, LtoBackendArtifacts> sharedNonLtoBackends) {
String basename = libraryArtifact.getFilename();
switch (category) {
case ALWAYSLINK_STATIC_LIBRARY:
@@ -275,6 +292,7 @@ public abstract class LinkerInputs {
this.objectFiles = objectFiles == null ? null : CollectionUtils.makeImmutable(objectFiles);
this.ltoBitcodeFiles =
(ltoBitcodeFiles == null) ? ImmutableMap.<Artifact, Artifact>of() : ltoBitcodeFiles;
+ this.sharedNonLtoBackends = sharedNonLtoBackends;
}
@Override
@@ -313,6 +331,11 @@ public abstract class LinkerInputs {
}
@Override
+ public ImmutableMap<Artifact, LtoBackendArtifacts> getSharedNonLtoBackends() {
+ return sharedNonLtoBackends;
+ }
+
+ @Override
public Iterable<Artifact> getObjectFiles() {
Preconditions.checkNotNull(objectFiles);
return objectFiles;
@@ -399,12 +422,23 @@ public abstract class LinkerInputs {
// !(artifact.getGeneratingAction() instanceof CppLinkAction) ||
// !Link.ARCHIVE_LIBRARY_FILETYPES.contains(artifact.getFileType()));
return new CompoundLibraryToLink(
- artifact, category, CcLinkingOutputs.libraryIdentifierOf(artifact), null, null);
+ artifact,
+ category,
+ CcLinkingOutputs.libraryIdentifierOf(artifact),
+ /* objectFiles= */ null,
+ /* ltoBitcodeFiles= */ null,
+ /* sharedNonLtoBackends= */ null);
}
public static LibraryToLink opaqueLibraryToLink(
Artifact artifact, ArtifactCategory category, String libraryIdentifier) {
- return new CompoundLibraryToLink(artifact, category, libraryIdentifier, null, null);
+ return new CompoundLibraryToLink(
+ artifact,
+ category,
+ libraryIdentifier,
+ /* objectFiles= */ null,
+ /* ltoBitcodeFiles= */ null,
+ /* sharedNonLtoBackends= */ null);
}
/** Creates a library to link with the specified object files. */
@@ -413,9 +447,10 @@ public abstract class LinkerInputs {
ArtifactCategory category,
String libraryIdentifier,
Iterable<Artifact> objectFiles,
- ImmutableMap<Artifact, Artifact> ltoBitcodeFiles) {
+ ImmutableMap<Artifact, Artifact> ltoBitcodeFiles,
+ ImmutableMap<Artifact, LtoBackendArtifacts> sharedNonLtoBackends) {
return new CompoundLibraryToLink(
- library, category, libraryIdentifier, objectFiles, ltoBitcodeFiles);
+ library, category, libraryIdentifier, objectFiles, ltoBitcodeFiles, sharedNonLtoBackends);
}
public static Iterable<Artifact> toNonSolibArtifacts(Iterable<LibraryToLink> libraries) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java b/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java
index 9d40f8ecd6..b95b91da04 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java
@@ -256,7 +256,9 @@ public abstract class NativeDepsHelper {
builder.setLtoIndexing(true);
builder.setUsePicForLtoBackendActions(CppHelper.usePic(ruleContext, toolchain, false));
CppLinkAction indexAction = builder.build();
- ruleContext.registerAction(indexAction);
+ if (indexAction != null) {
+ ruleContext.registerAction(indexAction);
+ }
builder.setLtoIndexing(false);
}