diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java | 69 |
1 files changed, 63 insertions, 6 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java index 66b2722e83..5da414f134 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java @@ -41,6 +41,7 @@ import com.google.devtools.build.lib.vfs.PathFragment; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -78,6 +79,8 @@ public final class LinkCommandLine extends CommandLine { private final boolean nativeDeps; private final boolean useTestOnlyFlags; private final boolean needWholeArchive; + + @Nullable private final Iterable<LTOBackendArtifacts> allLTOArtifacts; @Nullable private final Artifact paramFile; @Nullable private final Artifact interfaceSoBuilder; @@ -106,6 +109,7 @@ public final class LinkCommandLine extends CommandLine { boolean nativeDeps, boolean useTestOnlyFlags, boolean needWholeArchive, + @Nullable Iterable<LTOBackendArtifacts> allLTOArtifacts, @Nullable Artifact paramFile, Artifact interfaceSoBuilder, CcToolchainFeatures.Variables variables, @@ -161,6 +165,7 @@ public final class LinkCommandLine extends CommandLine { this.nativeDeps = nativeDeps; this.useTestOnlyFlags = useTestOnlyFlags; this.needWholeArchive = needWholeArchive; + this.allLTOArtifacts = allLTOArtifacts; this.paramFile = paramFile; // For now, silently ignore interfaceSoBuilder if we don't build an interface dynamic library. @@ -641,7 +646,7 @@ public final class LinkCommandLine extends CommandLine { && linkTargetType == LinkTargetType.EXECUTABLE && cppConfiguration.skipStaticOutputs()) { // Linked binary goes to /dev/null; bogus dependency info in its place. - Collections.addAll(argv, "/dev/null", "-MMD", "-MF", execpath); // thanks Ambrose + Collections.addAll(argv, "/dev/null", "-MMD", "-MF", execpath); } else { argv.add(execpath); } @@ -784,6 +789,23 @@ public final class LinkCommandLine extends CommandLine { boolean includeSolibDir = false; + + Map<Artifact, Artifact> ltoMap = null; + if (allLTOArtifacts != null) { + // TODO(bazel-team): The LTO final link can only work if there are individual .o files on the + // command line. Rather than crashing, this should issue a nice error. We will get this by + // 1) moving supports_start_end_lib to a toolchain feature + // 2) having thin_lto require start_end_lib + // As a bonus, we can rephrase --nostart_end_lib as --features=-start_end_lib and get rid + // of a command line option. + + Preconditions.checkState(cppConfiguration.useStartEndLib()); + ltoMap = new HashMap<>(); + for (LTOBackendArtifacts l : allLTOArtifacts) { + ltoMap.put(l.getBitcodeFile(), l.getObjectFile()); + } + } + for (LinkerInput input : getLinkerInputs()) { if (isDynamicLibrary(input)) { PathFragment libDir = input.getArtifact().getExecPath().getParentDirectory(); @@ -795,7 +817,7 @@ public final class LinkCommandLine extends CommandLine { } addDynamicInputLinkOptions(input, linkerInputs, libOpts, solibDir, rpathRoot); } else { - addStaticInputLinkOptions(input, linkerInputs); + addStaticInputLinkOptions(input, linkerInputs, ltoMap); } } @@ -813,7 +835,7 @@ public final class LinkCommandLine extends CommandLine { includeRuntimeSolibDir = true; addDynamicInputLinkOptions(input, optionsList, libOpts, solibDir, rpathRoot); } else { - addStaticInputLinkOptions(input, optionsList); + addStaticInputLinkOptions(input, optionsList, ltoMap); } } @@ -857,6 +879,11 @@ public final class LinkCommandLine extends CommandLine { */ argv.addAll(linkopts); } + + if (ltoMap != null) { + Preconditions.checkState( + ltoMap.size() == 0, "Still have LTO objects left: " + ltoMap + ", command-line: " + argv); + } } /** @@ -902,8 +929,12 @@ public final class LinkCommandLine extends CommandLine { /** * Adds command-line options for a static library or non-library input * into options. + * + * @param ltoMap is a mutable list of exec paths that should be on the command-line, which + * must be supplied for LTO final links. */ - private void addStaticInputLinkOptions(LinkerInput input, List<String> options) { + private void addStaticInputLinkOptions( + LinkerInput input, List<String> options, @Nullable Map<Artifact, Artifact> ltoMap) { Preconditions.checkState(!isDynamicLibrary(input)); // start-lib/end-lib library: adds its input object files. @@ -912,13 +943,32 @@ public final class LinkCommandLine extends CommandLine { if (!Iterables.isEmpty(archiveMembers)) { options.add("-Wl,--start-lib"); for (Artifact member : archiveMembers) { - options.add(member.getExecPathString()); + if (ltoMap != null) { + Artifact backend = ltoMap.remove(member); + + if (backend == null) { + System.err.println( + "LTO backend file missing for " + member + " already did: " + options); + backend = member; + } + options.add(backend.getExecPathString()); + } else { + options.add(member.getExecPathString()); + } } options.add("-Wl,--end-lib"); } - // For anything else, add the input directly. } else { + // For anything else, add the input directly. Artifact inputArtifact = input.getArtifact(); + + if (ltoMap != null) { + Artifact ltoArtifact = ltoMap.remove(inputArtifact); + if (ltoArtifact != null) { + inputArtifact = ltoArtifact; + } + } + if (input.isFake()) { options.add(Link.FAKE_OBJECT_PREFIX + inputArtifact.getExecPathString()); } else { @@ -968,6 +1018,7 @@ public final class LinkCommandLine extends CommandLine { private boolean nativeDeps; private boolean useTestOnlyFlags; private boolean needWholeArchive; + @Nullable private Iterable<LTOBackendArtifacts> allLTOBackendArtifacts; @Nullable private Artifact paramFile; @Nullable private Artifact interfaceSoBuilder; @@ -1023,6 +1074,7 @@ public final class LinkCommandLine extends CommandLine { nativeDeps, useTestOnlyFlags, needWholeArchive, + allLTOBackendArtifacts, paramFile, interfaceSoBuilder, variables, @@ -1191,5 +1243,10 @@ public final class LinkCommandLine extends CommandLine { this.paramFile = paramFile; return this; } + + public Builder setAllLTOArtifacts(Iterable<LTOBackendArtifacts> allLTOArtifacts) { + this.allLTOBackendArtifacts = allLTOArtifacts; + return this; + } } } |