diff --git a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java index 4cae09a35da..0efc183f18f 100644 --- a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java +++ b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java @@ -322,11 +322,12 @@ public static ConfiguredTarget init(CppSemantics semantics, RuleContext ruleCont // can also be enabled specifically for tests with an experimental flag. // TODO(meikeb): Retire the experimental flag by end of 2018. boolean linkCompileOutputSeparately = - ruleContext.isTestTarget() - && linkingMode == LinkingMode.DYNAMIC - && cppConfiguration.getDynamicModeFlag() == DynamicMode.DEFAULT - && (cppConfiguration.getLinkCompileOutputSeparately() - || ruleContext.getDisabledFeatures().contains(STATIC_LINK_TEST_SRCS)); + (ruleContext.isTestTarget() + && cppConfiguration.getLinkCompileOutputSeparately() + && linkingMode == LinkingMode.DYNAMIC) + || (ruleContext.isTestTarget() + && cppConfiguration.getDynamicModeFlag() == DynamicMode.DEFAULT + && ruleContext.getDisabledFeatures().contains(STATIC_LINK_TEST_SRCS)); // When linking the object files directly into the resulting binary, we do not need // library-level link outputs; thus, we do not let CcCompilationHelper produce link outputs // (either shared object files or archives) for a non-library link type [*], and add diff --git a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java index aabcb920f8b..ed7e921f486 100644 --- a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java +++ b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java @@ -32,17 +32,19 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; +import com.google.devtools.build.lib.rules.cpp.CcLinkParams.LinkOptions; +import com.google.devtools.build.lib.rules.cpp.CcLinkParams.Linkstamp; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.ExpansionException; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.VariablesExtension; import com.google.devtools.build.lib.rules.cpp.LibraryToLinkWrapper.CcLinkingContext; -import com.google.devtools.build.lib.rules.cpp.LibraryToLinkWrapper.CcLinkingContext.Linkstamp; import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType; import com.google.devtools.build.lib.rules.cpp.Link.LinkerOrArchiver; import com.google.devtools.build.lib.rules.cpp.Link.LinkingMode; import com.google.devtools.build.lib.rules.cpp.Link.Picness; import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink; import com.google.devtools.build.lib.skylarkbuildapi.cpp.LinkingInfoApi; +import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.PathFragment; import java.util.ArrayList; @@ -64,17 +66,17 @@ public final class CcLinkingHelper { // TODO(plf): Only used by Skylark API. Remove after migrating. @Deprecated public static final class LinkingInfo implements LinkingInfoApi { - private final CcLinkingContext ccLinkingContext; + private final CcLinkingInfo ccLinkingInfo; private final CcLinkingOutputs linkingOutputs; - public LinkingInfo(CcLinkingContext ccLinkingContext, CcLinkingOutputs linkingOutputs) { - this.ccLinkingContext = ccLinkingContext; + public LinkingInfo(CcLinkingInfo ccLinkingInfo, CcLinkingOutputs linkingOutputs) { + this.ccLinkingInfo = ccLinkingInfo; this.linkingOutputs = linkingOutputs; } @Override - public CcLinkingContext getCcLinkingContext() { - return ccLinkingContext; + public CcLinkingInfo getCcLinkingInfo() { + return ccLinkingInfo; } @Override @@ -91,7 +93,7 @@ public CcLinkingOutputs getCcLinkingOutputs() { private final List nonCodeLinkerInputs = new ArrayList<>(); private final List linkopts = new ArrayList<>(); private final List deps = new ArrayList<>(); - private final List ccLinkingContexts = new ArrayList<>(); + private final List ccLinkingInfos = new ArrayList<>(); private final NestedSetBuilder linkstamps = NestedSetBuilder.stableOrder(); private final List linkActionInputs = new ArrayList<>(); @@ -192,20 +194,20 @@ public CcLinkingHelper addLinkopts(Iterable linkopts) { * (like from a "deps" attribute) and also implicit dependencies on runtime libraries. */ public CcLinkingHelper addDeps(Iterable deps) { - this.ccLinkingContexts.addAll( + this.ccLinkingInfos.addAll( Streams.stream(AnalysisUtils.getProviders(deps, CcInfo.PROVIDER)) - .map(CcInfo::getCcLinkingContext) + .map(CcInfo::getCcLinkingInfo) .collect(ImmutableList.toImmutableList())); Iterables.addAll(this.deps, deps); return this; } /** - * Adds additional {@link CcLinkingContext} that will be used everywhere where CcLinkingInfos were + * Adds additional {@link CcLinkingInfo} that will be used everywhere where CcLinkingInfos were * obtained from deps. */ - public CcLinkingHelper addCcLinkingContexts(Iterable ccLinkingContexts) { - Iterables.addAll(this.ccLinkingContexts, ccLinkingContexts); + public CcLinkingHelper addCcLinkingInfos(Iterable ccLinkingInfos) { + Iterables.addAll(this.ccLinkingInfos, ccLinkingInfos); return this; } @@ -357,37 +359,32 @@ public CcLinkingOutputs link(CcCompilationOutputs ccOutputs) return ccLinkingOutputs; } - public CcLinkingContext buildCcLinkingContextFromLibraryToLinkWrappers( + public CcLinkingInfo buildCcLinkingInfoFromLibraryToLinkWrappers( ImmutableCollection libraryToLinkWrappers, CcCompilationContext ccCompilationContext) { NestedSetBuilder linkstampBuilder = NestedSetBuilder.stableOrder(); for (Artifact linkstamp : linkstamps.build()) { linkstampBuilder.add(new Linkstamp(linkstamp, ccCompilationContext.getDeclaredIncludeSrcs())); } - CcLinkingContext ccLinkingContext = CcLinkingContext.EMPTY; + CcLinkingInfo ccLinkingInfo = CcLinkingInfo.EMPTY; if (!neverlink) { - // We want an empty set if there are no link options. We have to make sure we don't - // create a LinkOptions instance that contains an empty list. - ccLinkingContext = - CcLinkingContext.builder() - .addUserLinkFlags( - linkopts.isEmpty() - ? NestedSetBuilder.emptySet(Order.LINK_ORDER) - : NestedSetBuilder.create( - Order.LINK_ORDER, CcLinkingContext.LinkOptions.of(linkopts))) - .addLibraries( - NestedSetBuilder.linkOrder() - .addAll(libraryToLinkWrappers) - .build()) - .addNonCodeInputs( - NestedSetBuilder.linkOrder().addAll(nonCodeLinkerInputs).build()) - .addLinkstamps(linkstampBuilder.build()) - .build(); + ccLinkingInfo = + LibraryToLinkWrapper.toCcLinkingInfo( + cppConfiguration.forcePic(), + libraryToLinkWrappers, + // We want an empty set if there are no link options. We have to make sure we don't + // create a LinkOptions instance that contains an empty list. + linkopts.isEmpty() + ? NestedSetBuilder.emptySet(Order.LINK_ORDER) + : NestedSetBuilder.create(Order.LINK_ORDER, LinkOptions.of(linkopts)), + linkstampBuilder.build(), + nonCodeLinkerInputs, + /* extraLinkTimeLibraries= */ null); } - ImmutableList.Builder mergedCcLinkingContexts = ImmutableList.builder(); - mergedCcLinkingContexts.add(ccLinkingContext); - mergedCcLinkingContexts.addAll(ccLinkingContexts); - return CcLinkingContext.merge(mergedCcLinkingContexts.build()); + ImmutableList.Builder mergedCcLinkingInfos = ImmutableList.builder(); + mergedCcLinkingInfos.add(ccLinkingInfo); + mergedCcLinkingInfos.addAll(ccLinkingInfos); + return CcLinkingInfo.merge(mergedCcLinkingInfos.build()); } /** @@ -412,7 +409,7 @@ private CcLinkingOutputs createCcLinkActions(CcCompilationOutputs ccOutputs) staticLinkType.linkerOrArchiver() == LinkerOrArchiver.ARCHIVER, "can only handle static links"); - LibraryToLinkWrapper.Builder libraryToLinkBuilder = LibraryToLinkWrapper.builder(); + CcLinkingOutputs.Builder result = new CcLinkingOutputs.Builder(); AnalysisEnvironment env = ruleContext.getAnalysisEnvironment(); boolean usePicForBinaries = CppHelper.usePicForBinaries(ruleContext, ccToolchain, featureConfiguration); @@ -426,36 +423,30 @@ private CcLinkingOutputs createCcLinkActions(CcCompilationOutputs ccOutputs) .getPathString(); if (shouldCreateStaticLibraries) { - createNoPicAndPicStaticLibraries( - libraryToLinkBuilder, - env, - usePicForBinaries, - usePicForDynamicLibs, - libraryIdentifier, - ccOutputs); + Pair staticLibrariesToLink = + createNoPicAndPicStaticLibraries( + env, usePicForBinaries, usePicForDynamicLibs, libraryIdentifier, ccOutputs); + if (staticLibrariesToLink.first != null) { + result.addStaticLibrary(staticLibrariesToLink.first); + } + if (staticLibrariesToLink.second != null) { + result.addPicStaticLibrary(staticLibrariesToLink.second); + } } - boolean hasBuiltDynamicLibrary = false; - CcLinkingOutputs.Builder ccLinkingOutputsBuilder = CcLinkingOutputs.builder(); if (shouldCreateDynamicLibrary) { boolean usePic = (!dynamicLinkType.isExecutable() && usePicForDynamicLibs) || (dynamicLinkType.isExecutable() && usePicForBinaries); - hasBuiltDynamicLibrary = - createDynamicLibrary( - ccLinkingOutputsBuilder, - libraryToLinkBuilder, - env, - usePic, - libraryIdentifier, - ccOutputs); - } - - if (hasBuiltDynamicLibrary || shouldCreateStaticLibraries) { - ccLinkingOutputsBuilder.setLibraryToLink(libraryToLinkBuilder.build()); + createDynamicLibrary(result, env, usePic, libraryIdentifier, ccOutputs); } - return ccLinkingOutputsBuilder.build(); + CcLinkingOutputs ccLinkingOutputs = result.build(); + Preconditions.checkState(ccLinkingOutputs.getStaticLibraries().size() <= 1); + Preconditions.checkState(ccLinkingOutputs.getPicStaticLibraries().size() <= 1); + Preconditions.checkState(ccLinkingOutputs.getDynamicLibrariesForLinking().size() <= 1); + Preconditions.checkState(ccLinkingOutputs.getDynamicLibrariesForRuntime().size() <= 1); + return ccLinkingOutputs; } public CcLinkingHelper setWillOnlyBeLinkedIntoDynamicLibraries( @@ -494,14 +485,15 @@ public CcLinkingHelper setDefFile(Artifact defFile) { return this; } - private void createNoPicAndPicStaticLibraries( - LibraryToLinkWrapper.Builder libraryToLinkBuilder, + private Pair createNoPicAndPicStaticLibraries( AnalysisEnvironment env, boolean usePicForBinaries, boolean usePicForDynamicLibs, String libraryIdentifier, CcCompilationOutputs ccOutputs) throws RuleErrorException, InterruptedException { + LibraryToLink staticLibrary = null; + LibraryToLink picStaticLibrary = null; // Create static library (.a). The staticLinkType only reflects whether the library is // alwayslink or not. The PIC-ness is determined by whether we need to use PIC or not. There // are four cases: @@ -533,18 +525,10 @@ private void createNoPicAndPicStaticLibraries( } if (createNoPicAction) { - LibraryToLink staticLibrary = + staticLibrary = registerActionForStaticLibrary( staticLinkType, ccOutputs, /* usePic= */ false, libraryIdentifier, env) .getOutputLibrary(); - libraryToLinkBuilder - .setLibraryIdentifier(staticLibrary.getLibraryIdentifier()) - .setStaticLibrary(staticLibrary.getArtifact()) - .setObjectFiles(ImmutableList.copyOf(staticLibrary.getObjectFiles())) - .setLtoCompilationContext(staticLibrary.getLtoCompilationContext()) - .setSharedNonLtoBackends(staticLibrary.getSharedNonLtoBackends()) - .setAlwayslink( - staticLibrary.getArtifactCategory() == ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY); } if (createPicAction) { @@ -558,7 +542,7 @@ private void createNoPicAndPicStaticLibraries( ? LinkTargetType.ALWAYS_LINK_PIC_STATIC_LIBRARY : LinkTargetType.PIC_STATIC_LIBRARY; } - LibraryToLink picStaticLibrary = + picStaticLibrary = registerActionForStaticLibrary( linkTargetTypeUsedForNaming, ccOutputs, @@ -566,15 +550,8 @@ private void createNoPicAndPicStaticLibraries( libraryIdentifier, env) .getOutputLibrary(); - libraryToLinkBuilder - .setLibraryIdentifier(picStaticLibrary.getLibraryIdentifier()) - .setPicStaticLibrary(picStaticLibrary.getArtifact()) - .setPicObjectFiles(ImmutableList.copyOf(picStaticLibrary.getObjectFiles())) - .setPicLtoCompilationContext(picStaticLibrary.getLtoCompilationContext()) - .setPicSharedNonLtoBackends(picStaticLibrary.getSharedNonLtoBackends()) - .setAlwayslink( - picStaticLibrary.getArtifactCategory() == ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY); } + return new Pair<>(staticLibrary, picStaticLibrary); } private CppLinkAction registerActionForStaticLibrary( @@ -601,15 +578,13 @@ private CppLinkAction registerActionForStaticLibrary( return action; } - private boolean createDynamicLibrary( - CcLinkingOutputs.Builder ccLinkingOutputs, - LibraryToLinkWrapper.Builder libraryToLinkBuilder, + private void createDynamicLibrary( + CcLinkingOutputs.Builder result, AnalysisEnvironment env, boolean usePic, String libraryIdentifier, CcCompilationOutputs ccOutputs) throws RuleErrorException, InterruptedException { - boolean hasBuiltDynamicLibrary = false; // Create dynamic library. Artifact soImpl; String mainLibraryIdentifier; @@ -689,12 +664,16 @@ private boolean createDynamicLibrary( || dynamicLinkType != LinkTargetType.NODEPS_DYNAMIC_LIBRARY; if (shouldLinkTransitively) { - CcLinkingContext ccLinkingContext = CcLinkingContext.merge(ccLinkingContexts); + CcLinkingInfo mergedCcLinkingInfo = CcLinkingInfo.merge(ccLinkingInfos); + CcLinkingContext ccLinkingContext = + LibraryToLinkWrapper.fromCcLinkingInfo(mergedCcLinkingInfo); List libraries = - LibraryToLinkWrapper.convertLibraryToLinkWrapperListToLibraryToLinkList( - ccLinkingContext.getLibraries(), - linkingMode != LinkingMode.DYNAMIC, - dynamicLinkType.isDynamicLibrary()); + ccLinkingContext + .toCcLinkingInfo() + .getCcLinkParams( + linkingMode != LinkingMode.DYNAMIC, dynamicLinkType.isDynamicLibrary()) + .getLibraries() + .toList(); dynamicLinkActionBuilder.addLinkParams( libraries, ccLinkingContext.getFlattenedUserLinkFlags(), @@ -724,10 +703,10 @@ private boolean createDynamicLibrary( } if (dynamicLinkActionBuilder.getAllLtoBackendArtifacts() != null) { - ccLinkingOutputs.addAllLtoArtifacts(dynamicLinkActionBuilder.getAllLtoBackendArtifacts()); + result.addAllLtoArtifacts(dynamicLinkActionBuilder.getAllLtoBackendArtifacts()); } CppLinkAction dynamicLinkAction = dynamicLinkActionBuilder.build(); - ccLinkingOutputs.addLinkActionInputs(dynamicLinkAction.getInputs()); + result.addLinkActionInputs(dynamicLinkAction.getInputs()); env.registerAction(dynamicLinkAction); LibraryToLink dynamicLibrary = dynamicLinkAction.getOutputLibrary(); @@ -740,14 +719,11 @@ private boolean createDynamicLibrary( // When COPY_DYNAMIC_LIBRARIES_TO_BINARY is enabled, we don't need to create the special // solibDir, instead we use the original interface library and dynamic library. if (dynamicLibrary != null) { - hasBuiltDynamicLibrary = true; - libraryToLinkBuilder.setLibraryIdentifier(dynamicLibrary.getLibraryIdentifier()); if (neverlink || featureConfiguration.isEnabled(CppRuleClasses.COPY_DYNAMIC_LIBRARIES_TO_BINARY)) { - if (interfaceLibrary != null) { - libraryToLinkBuilder.setInterfaceLibrary(interfaceLibrary.getArtifact()); - } - libraryToLinkBuilder.setDynamicLibrary(dynamicLibrary.getArtifact()); + result.addDynamicLibraryForLinking( + interfaceLibrary == null ? dynamicLibrary : interfaceLibrary); + result.addDynamicLibraryForRuntime(dynamicLibrary); } else { Artifact implLibraryLinkArtifact = SolibSymlinkAction.getDynamicLibrarySymlink( @@ -758,10 +734,15 @@ private boolean createDynamicLibrary( /* preserveName= */ false, /* prefixConsumer= */ false, ruleContext.getConfiguration()); - libraryToLinkBuilder.setDynamicLibrary(implLibraryLinkArtifact); - libraryToLinkBuilder.setResolvedSymlinkDynamicLibrary(dynamicLibrary.getArtifact()); - - if (interfaceLibrary != null) { + LibraryToLink implLibraryLink = + LinkerInputs.solibLibraryToLink( + implLibraryLinkArtifact, dynamicLibrary.getArtifact(), libraryIdentifier); + result.addDynamicLibraryForRuntime(implLibraryLink); + + LibraryToLink libraryLink; + if (interfaceLibrary == null) { + libraryLink = implLibraryLink; + } else { Artifact libraryLinkArtifact = SolibSymlinkAction.getDynamicLibrarySymlink( /* actionRegistry= */ ruleContext, @@ -771,12 +752,13 @@ private boolean createDynamicLibrary( /* preserveName= */ false, /* prefixConsumer= */ false, ruleContext.getConfiguration()); - libraryToLinkBuilder.setInterfaceLibrary(libraryLinkArtifact); - libraryToLinkBuilder.setResolvedSymlinkInterfaceLibrary(interfaceLibrary.getArtifact()); + libraryLink = + LinkerInputs.solibLibraryToLink( + libraryLinkArtifact, interfaceLibrary.getArtifact(), libraryIdentifier); } + result.addDynamicLibraryForLinking(libraryLink); } } - return hasBuiltDynamicLibrary; } private CppLinkActionBuilder newLinkActionBuilder(Artifact outputArtifact) { diff --git a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibraries.java b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibraries.java index ec2ef032b8e..997ef10a8ac 100644 --- a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibraries.java +++ b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibraries.java @@ -20,6 +20,7 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.rules.cpp.ExtraLinkTimeLibrary.BuildLibraryOutput; +import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization; import java.util.Collection; diff --git a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java index 4dc742a6241..fab76f856af 100644 --- a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java +++ b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java @@ -18,6 +18,7 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; +import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink; /** * An extra library to include in a link. The actual library is built at link time. diff --git a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/LibraryToLinkWrapper.java b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/LibraryToLinkWrapper.java index 453aa0cb28f..0d1057bc42d 100644 --- a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/LibraryToLinkWrapper.java +++ b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/LibraryToLinkWrapper.java @@ -13,11 +13,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -import com.google.common.base.Objects; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import com.google.common.collect.Streams; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.collect.nestedset.NestedSet; @@ -31,6 +32,7 @@ import com.google.devtools.build.lib.syntax.SkylarkList; import com.google.devtools.build.lib.vfs.FileSystemUtils; import java.util.Collection; +import java.util.Iterator; import java.util.List; import java.util.ListIterator; import javax.annotation.Nullable; @@ -48,7 +50,7 @@ *

To do this refactoring incrementally, we first introduce this class and add a method that is * able to convert from this representation to the old four CcLinkParams variables. */ -public class LibraryToLinkWrapper implements LibraryToLinkWrapperApi { +public class LibraryToLinkWrapper implements LibraryToLinkWrapperApi { public static LibraryToLinkWrapper convertLinkOutputsToLibraryToLinkWrapper( CcLinkingOutputs ccLinkingOutputs) { @@ -116,78 +118,11 @@ public static LibraryToLinkWrapper convertLinkOutputsToLibraryToLinkWrapper( return libraryToLinkWrapperBuilder.build(); } - public static List convertLibraryToLinkWrapperListToLibraryToLinkList( - NestedSet libraryToLinkWrappers, - boolean staticMode, - boolean forDynamicLibrary) { - ImmutableList.Builder librariesToLink = ImmutableList.builder(); - for (LibraryToLinkWrapper libraryToLinkWrapper : libraryToLinkWrappers) { - LibraryToLink staticLibraryToLink = - libraryToLinkWrapper.getStaticLibrary() == null - ? null - : libraryToLinkWrapper.getStaticLibraryToLink(); - LibraryToLink picStaticLibraryToLink = - libraryToLinkWrapper.getPicStaticLibrary() == null - ? null - : libraryToLinkWrapper.getPicStaticLibraryToLink(); - LibraryToLink libraryToLinkToUse = null; - if (staticMode) { - if (forDynamicLibrary) { - if (picStaticLibraryToLink != null) { - libraryToLinkToUse = picStaticLibraryToLink; - } else if (staticLibraryToLink != null) { - libraryToLinkToUse = staticLibraryToLink; - } - } else { - if (staticLibraryToLink != null) { - libraryToLinkToUse = staticLibraryToLink; - } else if (picStaticLibraryToLink != null) { - libraryToLinkToUse = picStaticLibraryToLink; - } - } - if (libraryToLinkToUse == null) { - if (libraryToLinkWrapper.getInterfaceLibrary() != null) { - libraryToLinkToUse = libraryToLinkWrapper.getInterfaceLibraryToLink(); - } else if (libraryToLinkWrapper.getDynamicLibrary() != null) { - libraryToLinkToUse = libraryToLinkWrapper.getDynamicLibraryToLink(); - } - } - } else { - if (libraryToLinkWrapper.getInterfaceLibrary() != null) { - libraryToLinkToUse = libraryToLinkWrapper.getInterfaceLibraryToLink(); - } else if (libraryToLinkWrapper.getDynamicLibrary() != null) { - libraryToLinkToUse = libraryToLinkWrapper.getDynamicLibraryToLink(); - } - if (libraryToLinkToUse == null) { - if (forDynamicLibrary) { - if (picStaticLibraryToLink != null) { - libraryToLinkToUse = picStaticLibraryToLink; - } else if (staticLibraryToLink != null) { - libraryToLinkToUse = staticLibraryToLink; - } - } else { - if (staticLibraryToLink != null) { - libraryToLinkToUse = staticLibraryToLink; - } else if (picStaticLibraryToLink != null) { - libraryToLinkToUse = picStaticLibraryToLink; - } - } - } - } - Preconditions.checkNotNull(libraryToLinkToUse); - librariesToLink.add(libraryToLinkToUse); + public Artifact getDynamicLibraryForRuntimeOrNull() { + if (staticLibrary == null && picStaticLibrary == null && dynamicLibrary != null) { + return dynamicLibrary; } - return librariesToLink.build(); - } - - public Artifact getDynamicLibraryForRuntimeOrNull(boolean linkingStatically) { - if (dynamicLibrary == null) { - return null; - } - if (linkingStatically && (staticLibrary != null || picStaticLibrary != null)) { - return null; - } - return dynamicLibrary; + return null; } /** Structure of the new CcLinkingContext. This will replace {@link CcLinkingInfo}. */ @@ -213,27 +148,10 @@ public CcLinkingContext( this.extraLinkTimeLibraries = extraLinkTimeLibraries; } - public static CcLinkingContext merge(List ccLinkingContexts) { - CcLinkingContext.Builder mergedCcLinkingContext = CcLinkingContext.builder(); - ExtraLinkTimeLibraries.Builder mergedExtraLinkTimeLibraries = - ExtraLinkTimeLibraries.builder(); - for (CcLinkingContext ccLinkingContext : ccLinkingContexts) { - mergedCcLinkingContext - .addLibraries(ccLinkingContext.getLibraries()) - .addUserLinkFlags(ccLinkingContext.getUserLinkFlags()) - .addLinkstamps(ccLinkingContext.getLinkstamps()) - .addNonCodeInputs(ccLinkingContext.getNonCodeInputs()); - if (ccLinkingContext.getExtraLinkTimeLibraries() != null) { - mergedExtraLinkTimeLibraries.addTransitive(ccLinkingContext.getExtraLinkTimeLibraries()); - } - } - mergedCcLinkingContext.setExtraLinkTimeLibraries(mergedExtraLinkTimeLibraries.build()); - return mergedCcLinkingContext.build(); - } - - public List getStaticModeParamsForExecutableLibraries() { + private static List getStaticModeParamsForExecutableLibraries( + CcLinkingContext ccLinkingContext) { ImmutableList.Builder libraryListBuilder = ImmutableList.builder(); - for (LibraryToLinkWrapper libraryToLinkWrapper : getLibraries()) { + for (LibraryToLinkWrapper libraryToLinkWrapper : ccLinkingContext.getLibraries()) { if (libraryToLinkWrapper.getStaticLibrary() != null) { libraryListBuilder.add(libraryToLinkWrapper.getStaticLibrary()); } else if (libraryToLinkWrapper.getPicStaticLibrary() != null) { @@ -247,64 +165,13 @@ public List getStaticModeParamsForExecutableLibraries() { return libraryListBuilder.build(); } - public List getStaticModeParamsForDynamicLibraryLibraries() { - ImmutableList.Builder artifactListBuilder = ImmutableList.builder(); - for (LibraryToLinkWrapper library : getLibraries()) { - if (library.getPicStaticLibrary() != null) { - artifactListBuilder.add(library.getPicStaticLibrary()); - } else if (library.getStaticLibrary() != null) { - artifactListBuilder.add(library.getStaticLibrary()); - } else if (library.getInterfaceLibrary() != null) { - artifactListBuilder.add(library.getInterfaceLibrary()); - } else { - artifactListBuilder.add(library.getDynamicLibrary()); - } - } - return artifactListBuilder.build(); - } - - public List getDynamicModeParamsForExecutableLibraries() { - ImmutableList.Builder artifactListBuilder = ImmutableList.builder(); - for (LibraryToLinkWrapper library : getLibraries()) { - if (library.getInterfaceLibrary() != null) { - artifactListBuilder.add(library.getInterfaceLibrary()); - } else if (library.getDynamicLibrary() != null) { - artifactListBuilder.add(library.getDynamicLibrary()); - } else if (library.getStaticLibrary() != null) { - artifactListBuilder.add(library.getStaticLibrary()); - } else if (library.getPicStaticLibrary() != null) { - artifactListBuilder.add(library.getPicStaticLibrary()); - } - } - return artifactListBuilder.build(); - } - - public List getDynamicModeParamsForDynamicLibraryLibraries() { - ImmutableList.Builder artifactListBuilder = ImmutableList.builder(); - for (LibraryToLinkWrapper library : getLibraries()) { - if (library.getInterfaceLibrary() != null) { - artifactListBuilder.add(library.getInterfaceLibrary()); - } else if (library.getDynamicLibrary() != null) { - artifactListBuilder.add(library.getDynamicLibrary()); - } else if (library.getPicStaticLibrary() != null) { - artifactListBuilder.add(library.getPicStaticLibrary()); - } else if (library.getStaticLibrary() != null) { - artifactListBuilder.add(library.getStaticLibrary()); - } - } - return artifactListBuilder.build(); + public static List getStaticModeParamsForExecutableLibraries(CcInfo ccInfo) { + return getStaticModeParamsForExecutableLibraries(ccInfo.getCcLinkingContext()); } - public List getDynamicLibrariesForRuntime(boolean linkingStatically) { - ImmutableList.Builder dynamicLibrariesForRuntimeBuilder = ImmutableList.builder(); - for (LibraryToLinkWrapper libraryToLinkWrapper : libraries) { - Artifact artifact = - libraryToLinkWrapper.getDynamicLibraryForRuntimeOrNull(linkingStatically); - if (artifact != null) { - dynamicLibrariesForRuntimeBuilder.add(artifact); - } - } - return dynamicLibrariesForRuntimeBuilder.build(); + public static List getStaticModeParamsForExecutableLibraries( + CcLinkingInfo ccLinkingInfo) { + return getStaticModeParamsForExecutableLibraries(fromCcLinkingInfo(ccLinkingInfo)); } public NestedSet getLibraries() { @@ -344,6 +211,16 @@ public ExtraLinkTimeLibraries getExtraLinkTimeLibraries() { return extraLinkTimeLibraries; } + public CcLinkingInfo toCcLinkingInfo() { + return LibraryToLinkWrapper.toCcLinkingInfo( + /* forcePic= */ false, + ImmutableList.copyOf(libraries), + userLinkFlags, + linkstamps, + nonCodeInputs, + extraLinkTimeLibraries); + } + public static Builder builder() { return new Builder(); } @@ -391,33 +268,6 @@ public CcLinkingContext build() { extraLinkTimeLibraries); } } - - @Override - public boolean equals(Object otherObject) { - if (!(otherObject instanceof CcLinkingContext)) { - return false; - } - CcLinkingContext other = (CcLinkingContext) otherObject; - if (this == other) { - return true; - } - if (!this.libraries.shallowEquals(other.libraries) - || !this.userLinkFlags.shallowEquals(other.userLinkFlags) - || !this.linkstamps.shallowEquals(other.linkstamps) - || !this.nonCodeInputs.shallowEquals(other.nonCodeInputs)) { - return false; - } - return true; - } - - @Override - public int hashCode() { - return Objects.hashCode( - libraries.shallowHashCode(), - userLinkFlags.shallowHashCode(), - linkstamps.shallowHashCode(), - nonCodeInputs.shallowHashCode()); - } } private final String libraryIdentifier; @@ -528,40 +378,269 @@ public Artifact getDynamicLibrary() { return dynamicLibrary; } - public Artifact getResolvedSymlinkDynamicLibrary() { - return resolvedSymlinkDynamicLibrary; - } - @Override public Artifact getInterfaceLibrary() { return interfaceLibrary; } - public Artifact getResolvedSymlinkInterfaceLibrary() { - return resolvedSymlinkInterfaceLibrary; - } - @Override public boolean getAlwayslink() { return alwayslink; } - public boolean getMustKeepDebug() { - return mustKeepDebug; - } - public static Builder builder() { return new Builder(); } + public static CcLinkingInfo toCcLinkingInfo( + boolean forcePic, + ImmutableCollection libraryToLinkWrappers, + NestedSet linkOpts, + NestedSet linkstamps, + Iterable nonCodeInputs, + ExtraLinkTimeLibraries extraLinkTimeLibraries) { + CcLinkParams staticModeParamsForDynamicLibrary = + buildStaticModeParamsForDynamicLibraryCcLinkParams( + libraryToLinkWrappers, linkOpts, linkstamps, nonCodeInputs, extraLinkTimeLibraries); + + CcLinkParams staticModeParamsForExecutable; + if (forcePic) { + staticModeParamsForExecutable = staticModeParamsForDynamicLibrary; + } else { + staticModeParamsForExecutable = + buildStaticModeParamsForExecutableCcLinkParams( + libraryToLinkWrappers, linkOpts, linkstamps, nonCodeInputs, extraLinkTimeLibraries); + } + + CcLinkParams dynamicModeParamsForDynamicLibrary = + buildDynamicModeParamsForDynamicLibraryCcLinkParams( + libraryToLinkWrappers, linkOpts, linkstamps, nonCodeInputs, extraLinkTimeLibraries); + CcLinkParams dynamicModeParamsForExecutable; + if (forcePic) { + dynamicModeParamsForExecutable = dynamicModeParamsForDynamicLibrary; + } else { + dynamicModeParamsForExecutable = + buildDynamicModeParamsForExecutableCcLinkParams( + libraryToLinkWrappers, linkOpts, linkstamps, nonCodeInputs, extraLinkTimeLibraries); + } + + CcLinkingInfo.Builder ccLinkingInfoBuilder = + new CcLinkingInfo.Builder() + .setStaticModeParamsForExecutable(staticModeParamsForExecutable) + .setStaticModeParamsForDynamicLibrary(staticModeParamsForDynamicLibrary) + .setDynamicModeParamsForExecutable(dynamicModeParamsForExecutable) + .setDynamicModeParamsForDynamicLibrary(dynamicModeParamsForDynamicLibrary); + return ccLinkingInfoBuilder.build(); + } + + /** + * WARNING: If CcLinkingInfo contains linking parameters from transitive closure, this method will + * be very expensive to execute because of nested set flattening. Should only be called by top + * level targets that do transitive linking when the nested sets have to be flattened anyway. + */ + public static CcLinkingContext fromCcLinkingInfo(CcLinkingInfo ccLinkingInfo) { + CcLinkingContext.Builder ccLinkingContextBuilder = CcLinkingContext.builder(); + CcLinkParams staticModeParamsForExecutable = ccLinkingInfo.getStaticModeParamsForExecutable(); + CcLinkParams staticModeParamsForDynamicLibrary = + ccLinkingInfo.getStaticModeParamsForDynamicLibrary(); + CcLinkParams dynamicModeParamsForExecutable = ccLinkingInfo.getDynamicModeParamsForExecutable(); + CcLinkParams dynamicModeParamsForDynamicLibrary = + ccLinkingInfo.getDynamicModeParamsForDynamicLibrary(); + + ccLinkingContextBuilder.addUserLinkFlags( + getUserLinkFlags( + staticModeParamsForExecutable, + staticModeParamsForDynamicLibrary, + dynamicModeParamsForExecutable, + dynamicModeParamsForDynamicLibrary)); + + ccLinkingContextBuilder.addLinkstamps( + getLinkstamps( + staticModeParamsForExecutable, + staticModeParamsForDynamicLibrary, + dynamicModeParamsForExecutable, + dynamicModeParamsForDynamicLibrary)); + + ccLinkingContextBuilder.addNonCodeInputs( + getNonCodeInputs( + staticModeParamsForExecutable, + staticModeParamsForDynamicLibrary, + dynamicModeParamsForExecutable, + dynamicModeParamsForDynamicLibrary)); + + ccLinkingContextBuilder.setExtraLinkTimeLibraries( + getExtraLinkTimeLibraries( + staticModeParamsForExecutable, + staticModeParamsForDynamicLibrary, + dynamicModeParamsForExecutable, + dynamicModeParamsForDynamicLibrary)); + + ccLinkingContextBuilder.addLibraries( + getLibraries( + staticModeParamsForExecutable, + staticModeParamsForDynamicLibrary, + dynamicModeParamsForExecutable, + dynamicModeParamsForDynamicLibrary)); + return ccLinkingContextBuilder.build(); + } + + private static void checkAllSizesMatch( + int staticModeForExecutable, + int staticModeForDynamicLibrary, + int dynamicModeForExecutable, + int dynamicModeForDynamicLibrary) { + Preconditions.checkState( + staticModeForExecutable == staticModeForDynamicLibrary + && staticModeForDynamicLibrary == dynamicModeForExecutable + && dynamicModeForExecutable == dynamicModeForDynamicLibrary); + } + + private static ExtraLinkTimeLibraries getExtraLinkTimeLibraries( + CcLinkParams staticModeParamsForExecutable, + CcLinkParams staticModeParamsForDynamicLibrary, + CcLinkParams dynamicModeParamsForExecutable, + CcLinkParams dynamicModeParamsForDynamicLibrary) { + Preconditions.checkState( + (staticModeParamsForExecutable.getExtraLinkTimeLibraries() == null + && staticModeParamsForDynamicLibrary.getExtraLinkTimeLibraries() == null) + || (staticModeParamsForExecutable.getExtraLinkTimeLibraries().getExtraLibraries().size() + == staticModeParamsForDynamicLibrary + .getExtraLinkTimeLibraries() + .getExtraLibraries() + .size())); + + Preconditions.checkState( + (staticModeParamsForDynamicLibrary.getExtraLinkTimeLibraries() == null + && dynamicModeParamsForExecutable.getExtraLinkTimeLibraries() == null) + || (staticModeParamsForDynamicLibrary + .getExtraLinkTimeLibraries() + .getExtraLibraries() + .size() + == dynamicModeParamsForExecutable + .getExtraLinkTimeLibraries() + .getExtraLibraries() + .size())); + Preconditions.checkState( + (dynamicModeParamsForExecutable.getExtraLinkTimeLibraries() == null + && dynamicModeParamsForDynamicLibrary.getExtraLinkTimeLibraries() == null) + || (dynamicModeParamsForExecutable + .getExtraLinkTimeLibraries() + .getExtraLibraries() + .size() + == dynamicModeParamsForDynamicLibrary + .getExtraLinkTimeLibraries() + .getExtraLibraries() + .size())); + return staticModeParamsForExecutable.getExtraLinkTimeLibraries(); + } + + private static NestedSet getUserLinkFlags( + CcLinkParams staticModeParamsForExecutable, + CcLinkParams staticModeParamsForDynamicLibrary, + CcLinkParams dynamicModeParamsForExecutable, + CcLinkParams dynamicModeParamsForDynamicLibrary) { + checkAllSizesMatch( + staticModeParamsForExecutable.flattenedLinkopts().size(), + staticModeParamsForDynamicLibrary.flattenedLinkopts().size(), + dynamicModeParamsForExecutable.flattenedLinkopts().size(), + dynamicModeParamsForDynamicLibrary.flattenedLinkopts().size()); + return staticModeParamsForExecutable.getLinkopts(); + } + + private static NestedSet getLinkstamps( + CcLinkParams staticModeParamsForExecutable, + CcLinkParams staticModeParamsForDynamicLibrary, + CcLinkParams dynamicModeParamsForExecutable, + CcLinkParams dynamicModeParamsForDynamicLibrary) { + checkAllSizesMatch( + staticModeParamsForExecutable.getLinkstamps().toList().size(), + staticModeParamsForDynamicLibrary.getLinkstamps().toList().size(), + dynamicModeParamsForExecutable.getLinkstamps().toList().size(), + dynamicModeParamsForDynamicLibrary.getLinkstamps().toList().size()); + return staticModeParamsForExecutable.getLinkstamps(); + } + + private static NestedSet getNonCodeInputs( + CcLinkParams staticModeParamsForExecutable, + CcLinkParams staticModeParamsForDynamicLibrary, + CcLinkParams dynamicModeParamsForExecutable, + CcLinkParams dynamicModeParamsForDynamicLibrary) { + NestedSet seNonCodeInputs = staticModeParamsForExecutable.getNonCodeInputs(); + NestedSet sdNonCodeInputs = staticModeParamsForDynamicLibrary.getNonCodeInputs(); + NestedSet deNonCodeInputs = dynamicModeParamsForExecutable.getNonCodeInputs(); + NestedSet ddNonCodeInputs = dynamicModeParamsForDynamicLibrary.getNonCodeInputs(); + Preconditions.checkState( + !(seNonCodeInputs == null + || sdNonCodeInputs == null + || deNonCodeInputs == null + || ddNonCodeInputs == null) + || (seNonCodeInputs == null + && sdNonCodeInputs == null + && deNonCodeInputs == null + && ddNonCodeInputs == null)); + if (sdNonCodeInputs == null) { + return NestedSetBuilder.linkOrder().build(); + } + checkAllSizesMatch( + sdNonCodeInputs.toList().size(), + deNonCodeInputs.toList().size(), + deNonCodeInputs.toList().size(), + ddNonCodeInputs.toList().size()); + return staticModeParamsForExecutable.getNonCodeInputs(); + } + + @Nullable + private static String setStaticArtifactsAndReturnIdentifier( + LibraryToLinkWrapper.Builder libraryToLinkWrapperBuilder, + LibraryToLink staticModeParamsForExecutableEntry, + LibraryToLink staticModeParamsForDynamicLibraryEntry) { + LibraryToLinkByPicness noPicAndPicStaticLibraryToLink = + returnNoPicAndPicStaticLibraryToLink( + staticModeParamsForExecutableEntry, staticModeParamsForDynamicLibraryEntry); + String libraryIdentifier = null; + LibraryToLink noPicStaticLibrary = noPicAndPicStaticLibraryToLink.getNoPicLibrary(); + if (noPicStaticLibrary != null) { + libraryToLinkWrapperBuilder.setStaticLibrary(noPicStaticLibrary.getArtifact()); + libraryIdentifier = noPicStaticLibrary.getLibraryIdentifier(); + if (noPicStaticLibrary.containsObjectFiles()) { + libraryToLinkWrapperBuilder.setObjectFiles(noPicStaticLibrary.getObjectFiles()); + } + libraryToLinkWrapperBuilder.setLtoCompilationContext( + noPicStaticLibrary.getLtoCompilationContext()); + libraryToLinkWrapperBuilder.setSharedNonLtoBackends( + noPicStaticLibrary.getSharedNonLtoBackends()); + libraryToLinkWrapperBuilder.setAlwayslink( + noPicStaticLibrary.getArtifactCategory() == ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY); + } + LibraryToLink picStaticLibrary = noPicAndPicStaticLibraryToLink.getPicLibrary(); + if (picStaticLibrary != null) { + libraryToLinkWrapperBuilder.setPicStaticLibrary(picStaticLibrary.getArtifact()); + if (libraryIdentifier == null) { + libraryIdentifier = picStaticLibrary.getLibraryIdentifier(); + } else { + Preconditions.checkState(libraryIdentifier.equals(picStaticLibrary.getLibraryIdentifier())); + } + if (picStaticLibrary.containsObjectFiles()) { + libraryToLinkWrapperBuilder.setPicObjectFiles(picStaticLibrary.getObjectFiles()); + } + libraryToLinkWrapperBuilder.setPicLtoCompilationContext( + picStaticLibrary.getLtoCompilationContext()); + libraryToLinkWrapperBuilder.setPicSharedNonLtoBackends( + picStaticLibrary.getSharedNonLtoBackends()); + libraryToLinkWrapperBuilder.setAlwayslink( + picStaticLibrary.getArtifactCategory() == ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY); + } + + return libraryIdentifier; + } + @Nullable @SuppressWarnings("ReferenceEquality") - public static String setDynamicArtifactsAndReturnIdentifier( + private static String setDynamicArtifactsAndReturnIdentifier( LibraryToLinkWrapper.Builder libraryToLinkWrapperBuilder, LibraryToLink dynamicModeParamsForExecutableEntry, LibraryToLink dynamicModeParamsForDynamicLibraryEntry, ListIterator runtimeLibraryIterator) { - Preconditions.checkNotNull(runtimeLibraryIterator); Artifact artifact = dynamicModeParamsForExecutableEntry.getArtifact(); String libraryIdentifier = null; Artifact runtimeArtifact = null; @@ -632,6 +711,166 @@ public static String setDynamicArtifactsAndReturnIdentifier( return libraryIdentifier; } + private static NestedSet getLibraries( + CcLinkParams staticModeParamsForExecutable, + CcLinkParams staticModeParamsForDynamicLibrary, + CcLinkParams dynamicModeParamsForExecutable, + CcLinkParams dynamicModeParamsForDynamicLibrary) { + Iterator staticModeParamsForExecutableIterator = + staticModeParamsForExecutable.getLibraries().iterator(); + Iterator staticModeParamsForDynamicLibraryIterator = + staticModeParamsForDynamicLibrary.getLibraries().iterator(); + Iterator dynamicModeParamsForExecutableIterator = + dynamicModeParamsForExecutable.getLibraries().iterator(); + Iterator dynamicModeParamsForDynamicLibraryIterator = + dynamicModeParamsForDynamicLibrary.getLibraries().iterator(); + + ListIterator runtimeLibraryIterator = + dynamicModeParamsForExecutable.getDynamicLibrariesForRuntime().toList().listIterator(); + + NestedSetBuilder libraryToLinkWrappers = NestedSetBuilder.linkOrder(); + while (staticModeParamsForExecutableIterator.hasNext() + && staticModeParamsForDynamicLibraryIterator.hasNext() + && dynamicModeParamsForExecutableIterator.hasNext() + && dynamicModeParamsForDynamicLibraryIterator.hasNext()) { + LibraryToLinkWrapper.Builder libraryToLinkWrapperBuilder = LibraryToLinkWrapper.builder(); + LibraryToLink staticModeParamsForExecutableEntry = + staticModeParamsForExecutableIterator.next(); + LibraryToLink staticModeParamsForDynamicLibraryEntry = + staticModeParamsForDynamicLibraryIterator.next(); + + String identifier = + setStaticArtifactsAndReturnIdentifier( + libraryToLinkWrapperBuilder, + staticModeParamsForExecutableEntry, + staticModeParamsForDynamicLibraryEntry); + + LibraryToLink dynamicModeParamsForExecutableEntry = + dynamicModeParamsForExecutableIterator.next(); + LibraryToLink dynamicModeParamsForDynamicLibraryEntry = + dynamicModeParamsForDynamicLibraryIterator.next(); + + String dynamicLibraryIdentifier = + setDynamicArtifactsAndReturnIdentifier( + libraryToLinkWrapperBuilder, + dynamicModeParamsForExecutableEntry, + dynamicModeParamsForDynamicLibraryEntry, + runtimeLibraryIterator); + + if (identifier == null) { + identifier = dynamicLibraryIdentifier; + } else { + Preconditions.checkState( + dynamicLibraryIdentifier == null || identifier.equals(dynamicLibraryIdentifier)); + } + + libraryToLinkWrapperBuilder.setLibraryIdentifier(identifier); + + Preconditions.checkState( + staticModeParamsForExecutableEntry.isMustKeepDebug() + == staticModeParamsForDynamicLibraryEntry.isMustKeepDebug() + && staticModeParamsForDynamicLibraryEntry.isMustKeepDebug() + == dynamicModeParamsForExecutableEntry.isMustKeepDebug() + && dynamicModeParamsForExecutableEntry.isMustKeepDebug() + == dynamicModeParamsForDynamicLibraryEntry.isMustKeepDebug()); + libraryToLinkWrapperBuilder.setMustKeepDebug( + staticModeParamsForExecutableEntry.isMustKeepDebug()); + + libraryToLinkWrappers.add(libraryToLinkWrapperBuilder.build()); + } + Preconditions.checkState( + !(staticModeParamsForExecutableIterator.hasNext() + || staticModeParamsForDynamicLibraryIterator.hasNext() + || dynamicModeParamsForExecutableIterator.hasNext() + || dynamicModeParamsForDynamicLibraryIterator.hasNext())); + return libraryToLinkWrappers.build(); + } + + private static class LibraryToLinkByPicness { + private final LibraryToLink noPicLibrary; + private final LibraryToLink picLibrary; + + private LibraryToLinkByPicness(LibraryToLink noPicLibrary, LibraryToLink picLibrary) { + this.noPicLibrary = noPicLibrary; + this.picLibrary = picLibrary; + } + + private LibraryToLink getNoPicLibrary() { + return noPicLibrary; + } + + private LibraryToLink getPicLibrary() { + return picLibrary; + } + } + + /** + * In the two static mode params objects of {@link CcLinkingInfo} we may have {@link + * LibraryToLink} objects that are static libraries. This method grabs two instances, each coming + * from one of the static mode params objects and returns a pair with a no-pic static + * LibraryToLink as the first element and a pic static LibraryToLink in the second element. + * + *

We know that for dynamic libraries we will always prefer the pic variant, so if the + * artifacts are different for the executable and for the dynamic library, then we know the former + * is the no-pic static library and the latter is the pic static library. + * + *

If the artifacts are the same, then we check if they have the extension .pic. If they do, + * then we know that there isn't a no-pic static library, so we return null for the first element. + * + *

If the artifacts are the same and they don't have the extension .pic. Then two of the + * following things could be happening: 1. The static library is no-pic and the pic static library + * wasn't generated. 2. The static library is pic and the no-pic static library wasn't generated. + * This can only be happening if we created the static library from {@link CcCompilationHelper}. + * When we create a static library from this class, the {@link LibraryToLink} will have the object + * files used to create the library. We can look at the extension of these objects file to decide + * if the library is pic or no-pic. If there are no object files, then the library must be no-pic. + */ + private static LibraryToLinkByPicness returnNoPicAndPicStaticLibraryToLink( + LibraryToLink fromStaticModeParamsForExecutable, + LibraryToLink fromStaticModeParamsForDynamicLibrary) { + if (fromStaticModeParamsForExecutable.getArtifactCategory() != ArtifactCategory.STATIC_LIBRARY + && fromStaticModeParamsForExecutable.getArtifactCategory() + != ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY) { + return new LibraryToLinkByPicness(/* noPicLibrary= */ null, /* picLibrary= */ null); + } + Preconditions.checkState( + fromStaticModeParamsForExecutable.getArtifactCategory() + == fromStaticModeParamsForDynamicLibrary.getArtifactCategory()); + Artifact artifactFromStaticModeParamsForExecutable = + fromStaticModeParamsForExecutable.getArtifact(); + Artifact artifactFromStaticModeParamsForDynamicLibrary = + fromStaticModeParamsForDynamicLibrary.getArtifact(); + if (artifactFromStaticModeParamsForExecutable + != artifactFromStaticModeParamsForDynamicLibrary) { + Preconditions.checkState( + !FileSystemUtils.removeExtension(artifactFromStaticModeParamsForExecutable.getFilename()) + .endsWith(".pic")); + Preconditions.checkState( + FileSystemUtils.removeExtension( + artifactFromStaticModeParamsForDynamicLibrary.getFilename()) + .endsWith(".pic")); + return new LibraryToLinkByPicness( + fromStaticModeParamsForExecutable, fromStaticModeParamsForDynamicLibrary); + } else if (FileSystemUtils.removeExtension( + artifactFromStaticModeParamsForExecutable.getFilename()) + .endsWith(".pic")) { + return new LibraryToLinkByPicness( + /* noPicLibrary= */ null, fromStaticModeParamsForDynamicLibrary); + } else if (fromStaticModeParamsForExecutable.containsObjectFiles() + && !Iterables.isEmpty(fromStaticModeParamsForExecutable.getObjectFiles()) + && FileSystemUtils.removeExtension( + Iterables.getFirst( + fromStaticModeParamsForExecutable.getObjectFiles(), + /* defaultValue= */ null) + .getFilename()) + .endsWith(".pic")) { + return new LibraryToLinkByPicness( + /* noPicLibrary= */ null, fromStaticModeParamsForDynamicLibrary); + } + return new LibraryToLinkByPicness( + fromStaticModeParamsForDynamicLibrary, /* picLibrary= */ null); + } + private static boolean doArtifactsHaveSameBasename(Artifact first, Artifact second) { String nameFirst = removeAllExtensions(first.getRootRelativePath().getPathString()); String nameSecond = removeAllExtensions(second.getRootRelativePath().getPathString()); @@ -648,6 +887,138 @@ private static String removeAllExtensions(String name) { return currentWithoutExtension; } + /** + * In this method and {@link #buildStaticModeParamsForDynamicLibraryCcLinkParams}, {@link + * #buildDynamicModeParamsForExecutableCcLinkParams} and {@link + * #buildDynamicModeParamsForDynamicLibraryCcLinkParams}, we add the ".a", ".pic.a" and/or ".so" + * files in appropriate order of preference depending on the link preferences. + * + *

For static libraries, first choice is the PIC or no-PIC static variable, depending on + * whether we prefer PIC or not. Even if we are using PIC, we still prefer the no PIC static + * variant than using a dynamic library, although this may be an error later. Best performance is + * obtained with no-PIC static libraries. If we don't have that we use the PIC variant, we can + * live with the extra overhead. + */ + private static CcLinkParams buildStaticModeParamsForExecutableCcLinkParams( + ImmutableCollection libraryToLinkWrappers, + NestedSet linkOpts, + NestedSet linkstamps, + Iterable nonCodeInputs, + ExtraLinkTimeLibraries extraLinkTimeLibraries) { + CcLinkParams.Builder ccLinkParamsBuilder = + initializeCcLinkParams(linkOpts, linkstamps, nonCodeInputs, extraLinkTimeLibraries); + for (LibraryToLinkWrapper libraryToLinkWrapper : libraryToLinkWrappers) { + boolean usedDynamic = false; + if (libraryToLinkWrapper.getStaticLibrary() != null) { + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getStaticLibraryToLink()); + } else if (libraryToLinkWrapper.getPicStaticLibrary() != null) { + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getPicStaticLibraryToLink()); + } else if (libraryToLinkWrapper.getInterfaceLibrary() != null) { + usedDynamic = true; + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getInterfaceLibraryToLink()); + } else if (libraryToLinkWrapper.getDynamicLibrary() != null) { + usedDynamic = true; + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getDynamicLibraryToLink()); + } + + if (usedDynamic && libraryToLinkWrapper.getDynamicLibrary() != null) { + ccLinkParamsBuilder.addDynamicLibrariesForRuntime( + ImmutableList.of(libraryToLinkWrapper.getDynamicLibrary())); + } + } + return ccLinkParamsBuilder.build(); + } + + private static CcLinkParams buildStaticModeParamsForDynamicLibraryCcLinkParams( + ImmutableCollection libraryToLinkWrappers, + NestedSet linkOpts, + NestedSet linkstamps, + Iterable nonCodeInputs, + ExtraLinkTimeLibraries extraLinkTimeLibraries) { + CcLinkParams.Builder ccLinkParamsBuilder = + initializeCcLinkParams(linkOpts, linkstamps, nonCodeInputs, extraLinkTimeLibraries); + for (LibraryToLinkWrapper libraryToLinkWrapper : libraryToLinkWrappers) { + boolean usedDynamic = false; + if (libraryToLinkWrapper.getPicStaticLibrary() != null) { + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getPicStaticLibraryToLink()); + } else if (libraryToLinkWrapper.getStaticLibrary() != null) { + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getStaticLibraryToLink()); + } else if (libraryToLinkWrapper.getInterfaceLibrary() != null) { + usedDynamic = true; + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getInterfaceLibraryToLink()); + } else if (libraryToLinkWrapper.getDynamicLibrary() != null) { + usedDynamic = true; + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getDynamicLibraryToLink()); + } + + if (usedDynamic && libraryToLinkWrapper.getDynamicLibrary() != null) { + ccLinkParamsBuilder.addDynamicLibrariesForRuntime( + ImmutableList.of(libraryToLinkWrapper.getDynamicLibrary())); + } + } + return ccLinkParamsBuilder.build(); + } + + private static CcLinkParams buildDynamicModeParamsForExecutableCcLinkParams( + ImmutableCollection libraryToLinkWrappers, + NestedSet linkOpts, + NestedSet linkstamps, + Iterable nonCodeInputs, + ExtraLinkTimeLibraries extraLinkTimeLibraries) { + CcLinkParams.Builder ccLinkParamsBuilder = + initializeCcLinkParams(linkOpts, linkstamps, nonCodeInputs, extraLinkTimeLibraries); + for (LibraryToLinkWrapper libraryToLinkWrapper : libraryToLinkWrappers) { + boolean usedDynamic = false; + if (libraryToLinkWrapper.getInterfaceLibrary() != null) { + usedDynamic = true; + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getInterfaceLibraryToLink()); + } else if (libraryToLinkWrapper.getDynamicLibrary() != null) { + usedDynamic = true; + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getDynamicLibraryToLink()); + } else if (libraryToLinkWrapper.getStaticLibrary() != null) { + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getStaticLibraryToLink()); + } else if (libraryToLinkWrapper.getPicStaticLibrary() != null) { + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getPicStaticLibraryToLink()); + } + + if (usedDynamic && libraryToLinkWrapper.getDynamicLibrary() != null) { + ccLinkParamsBuilder.addDynamicLibrariesForRuntime( + ImmutableList.of(libraryToLinkWrapper.getDynamicLibrary())); + } + } + return ccLinkParamsBuilder.build(); + } + + private static CcLinkParams buildDynamicModeParamsForDynamicLibraryCcLinkParams( + ImmutableCollection libraryToLinkWrappers, + NestedSet linkOpts, + NestedSet linkstamps, + Iterable nonCodeInputs, + ExtraLinkTimeLibraries extraLinkTimeLibraries) { + CcLinkParams.Builder ccLinkParamsBuilder = + initializeCcLinkParams(linkOpts, linkstamps, nonCodeInputs, extraLinkTimeLibraries); + for (LibraryToLinkWrapper libraryToLinkWrapper : libraryToLinkWrappers) { + boolean usedDynamic = false; + if (libraryToLinkWrapper.getInterfaceLibrary() != null) { + usedDynamic = true; + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getInterfaceLibraryToLink()); + } else if (libraryToLinkWrapper.getDynamicLibrary() != null) { + usedDynamic = true; + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getDynamicLibraryToLink()); + } else if (libraryToLinkWrapper.getPicStaticLibrary() != null) { + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getPicStaticLibraryToLink()); + } else if (libraryToLinkWrapper.getStaticLibrary() != null) { + ccLinkParamsBuilder.addLibrary(libraryToLinkWrapper.getStaticLibraryToLink()); + } + + if (usedDynamic && libraryToLinkWrapper.getDynamicLibrary() != null) { + ccLinkParamsBuilder.addDynamicLibrariesForRuntime( + ImmutableList.of(libraryToLinkWrapper.getDynamicLibrary())); + } + } + return ccLinkParamsBuilder.build(); + } + public LibraryToLink getStaticLibraryToLink() { Preconditions.checkNotNull(staticLibrary); if (staticLibraryToLink != null) { @@ -732,6 +1103,23 @@ public LibraryToLink getInterfaceLibraryToLink() { return interfaceLibraryToLink; } + private static CcLinkParams.Builder initializeCcLinkParams( + NestedSet linkOpts, + NestedSet linkstamps, + Iterable nonCodeInputs, + ExtraLinkTimeLibraries extraLinkTimeLibraries) { + CcLinkParams.Builder ccLinkParamsBuilder = CcLinkParams.builder(); + if (!linkOpts.isEmpty()) { + ccLinkParamsBuilder.addLinkOpts(linkOpts); + } + ccLinkParamsBuilder.addLinkstamps(linkstamps); + ccLinkParamsBuilder.addNonCodeInputs(nonCodeInputs); + if (extraLinkTimeLibraries != null) { + ccLinkParamsBuilder.addTransitiveExtraLinkTimeLibrary(extraLinkTimeLibraries); + } + return ccLinkParamsBuilder; + } + /** Builder for LibraryToLinkWrapper. */ public static class Builder { private String libraryIdentifier;