Skip to content

Commit

Permalink
Removed cpu flag dependency for linkMultiArchBinary
Browse files Browse the repository at this point in the history
This change removes any dependency to `--cpu` Blaze flag throughout the
implementation of `apple_common.link_multi_arch_binary`.

RELNOTES: N/A
PiperOrigin-RevId: 430570788
  • Loading branch information
Googler authored and copybara-github committed Feb 24, 2022
1 parent 0b09e9e commit bdcc080
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@

package com.google.devtools.build.lib.rules.objc;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
Expand All @@ -31,12 +32,13 @@
import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
import com.google.devtools.build.lib.rules.apple.ApplePlatform;
import com.google.devtools.build.lib.rules.cpp.CcInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppSemantics;
import com.google.devtools.build.lib.rules.objc.AppleDebugOutputsInfo.OutputType;
import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs;
import com.google.devtools.build.lib.rules.objc.MultiArchBinarySupport.DependencySpecificConfiguration;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

Expand Down Expand Up @@ -69,17 +71,25 @@ public static AppleLinkingOutputs linkMultiArchBinary(
Iterable<Artifact> extraLinkInputs,
boolean isStampingEnabled)
throws InterruptedException, RuleErrorException, ActionConflictException {
ImmutableListMultimap<String, TransitiveInfoCollection> cpuToDepsCollectionMap =
MultiArchBinarySupport.transformMap(ruleContext.getPrerequisitesByConfiguration("deps"));
Map<Optional<String>, List<ConfiguredTargetAndData>> splitDeps =
ruleContext.getSplitPrerequisiteConfiguredTargetAndTargets("deps");
Map<Optional<String>, List<ConfiguredTargetAndData>> splitToolchains =
ruleContext.getSplitPrerequisiteConfiguredTargetAndTargets(
ObjcRuleClasses.CHILD_CONFIG_ATTR);

Preconditions.checkState(
splitDeps.keySet().isEmpty() || splitDeps.keySet().equals(splitToolchains.keySet()),
"Split transition keys are different between 'deps' [%s] and '%s' [%s]",
splitDeps.keySet(),
ObjcRuleClasses.CHILD_CONFIG_ATTR,
splitToolchains.keySet());

ImmutableMap<BuildConfigurationValue, CcToolchainProvider> childConfigurationsAndToolchains =
MultiArchBinarySupport.getChildConfigurationsAndToolchains(ruleContext);
MultiArchBinarySupport multiArchBinarySupport =
new MultiArchBinarySupport(ruleContext, cppSemantics);

ImmutableSet<DependencySpecificConfiguration> dependencySpecificConfigurations =
multiArchBinarySupport.getDependencySpecificConfigurations(
childConfigurationsAndToolchains, cpuToDepsCollectionMap, avoidDeps);
ImmutableMap<Optional<String>, DependencySpecificConfiguration>
dependencySpecificConfigurations =
multiArchBinarySupport.getDependencySpecificConfigurations(
splitToolchains, splitDeps, avoidDeps);

Map<String, NestedSet<Artifact>> outputGroupCollector = new TreeMap<>();

Expand All @@ -100,7 +110,7 @@ public static AppleLinkingOutputs linkMultiArchBinary(
ObjcProvider.Builder objcProviderBuilder =
new ObjcProvider.Builder(ruleContext.getAnalysisEnvironment().getStarlarkSemantics());
for (DependencySpecificConfiguration dependencySpecificConfiguration :
dependencySpecificConfigurations) {
dependencySpecificConfigurations.values()) {
objcProviderBuilder.addTransitiveAndPropagate(
dependencySpecificConfiguration.objcProviderWithDylibSymbols());
}
Expand All @@ -110,10 +120,10 @@ public static AppleLinkingOutputs linkMultiArchBinary(
AppleLinkingOutputs.Builder builder =
new AppleLinkingOutputs.Builder().addOutputGroups(outputGroupCollector);

for (DependencySpecificConfiguration dependencySpecificConfiguration :
dependencySpecificConfigurations) {
for (Optional<String> splitTransitionKey : dependencySpecificConfigurations.keySet()) {
DependencySpecificConfiguration dependencySpecificConfiguration =
dependencySpecificConfigurations.get(splitTransitionKey);
BuildConfigurationValue childConfig = dependencySpecificConfiguration.config();
String configCpu = childConfig.getCpu();
AppleConfiguration childAppleConfig = childConfig.getFragment(AppleConfiguration.class);
CppConfiguration childCppConfig = childConfig.getFragment(CppConfiguration.class);
ObjcConfiguration childObjcConfig = childConfig.getFragment(ObjcConfiguration.class);
Expand All @@ -122,17 +132,21 @@ public static AppleLinkingOutputs linkMultiArchBinary(
ruleContext, /*archiveFileNameSuffix*/ "", /*outputPrefix*/ "", childConfig);
String arch = childAppleConfig.getSingleArchitecture();

List<? extends TransitiveInfoCollection> propagatedDeps =
MultiArchBinarySupport.getProvidersFromCtads(splitDeps.get(splitTransitionKey));

Artifact binaryArtifact =
multiArchBinarySupport.registerConfigurationSpecificLinkActions(
dependencySpecificConfiguration,
new ExtraLinkArgs(allLinkopts.build()),
allLinkInputs.build(),
isStampingEnabled,
cpuToDepsCollectionMap.get(configCpu),
propagatedDeps,
outputGroupCollector);

// TODO(b/177442911): Use the target platform from platform info coming from split
// transition outputs instead of inferring this based on the target CPU.
String configCpu = childConfig.getCpu();
ApplePlatform cpuPlatform = ApplePlatform.forTargetCpu(configCpu);

AppleLinkingOutputs.LinkingOutput.Builder outputBuilder =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,9 @@
import com.google.auto.value.AutoValue;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Streams;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.PlatformOptions;
Expand All @@ -50,6 +47,7 @@
import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider;
import com.google.devtools.build.lib.rules.cpp.CppSemantics;
import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
Expand All @@ -59,36 +57,6 @@ public class MultiArchBinarySupport {
private final RuleContext ruleContext;
private final CppSemantics cppSemantics;

/**
* Returns all child configurations for this multi-arch target, mapped to the toolchains that they
* should use.
*/
static ImmutableMap<BuildConfigurationValue, CcToolchainProvider>
getChildConfigurationsAndToolchains(RuleContext ruleContext) {
ImmutableListMultimap<BuildConfigurationValue, CcToolchainProvider> configToProvider =
ruleContext.getPrerequisitesByConfiguration(
ObjcRuleClasses.CHILD_CONFIG_ATTR, CcToolchainProvider.PROVIDER);

ImmutableMap.Builder<BuildConfigurationValue, CcToolchainProvider> result =
ImmutableMap.builder();
for (BuildConfigurationValue config : configToProvider.keySet()) {
CcToolchainProvider toolchain = Iterables.getOnlyElement(configToProvider.get(config));
result.put(config, toolchain);
}

return result.buildOrThrow();
}

static <V> ImmutableListMultimap<String, V> transformMap(
Multimap<BuildConfigurationValue, V> input) {
ImmutableListMultimap.Builder<String, V> result = ImmutableListMultimap.builder();
for (Map.Entry<BuildConfigurationValue, V> entry : input.entries()) {
result.put(entry.getKey().getCpu(), entry.getValue());
}

return result.build();
}

/** A tuple of values about dependency trees in a specific child configuration. */
@AutoValue
abstract static class DependencySpecificConfiguration {
Expand Down Expand Up @@ -149,7 +117,7 @@ public Artifact registerConfigurationSpecificLinkActions(
ExtraLinkArgs extraLinkArgs,
Iterable<Artifact> extraLinkInputs,
boolean isStampingEnabled,
Iterable<TransitiveInfoCollection> infoCollections,
Iterable<? extends TransitiveInfoCollection> infoCollections,
Map<String, NestedSet<Artifact>> outputMapCollector)
throws RuleErrorException, InterruptedException {
IntermediateArtifacts intermediateArtifacts =
Expand Down Expand Up @@ -191,53 +159,60 @@ public Artifact registerConfigurationSpecificLinkActions(
}

/**
* Returns a set of {@link DependencySpecificConfiguration} instances that comprise all
* information about the dependencies for each child configuration. This can be used both to
* register actions in {@link #registerConfigurationSpecificLinkActions} and collect provider
* information to be propagated upstream.
* Returns a map of {@link DependencySpecificConfiguration} instances keyed by their split
* transition key. Each dependency specific configuration comprise all information about the
* dependencies for each child configuration. This can be used both to register actions in {@link
* #registerConfigurationSpecificLinkActions} and collect provider information to be propagated
* upstream.
*
* @param childConfigurationsAndToolchains the set of configurations and toolchains for which
* dependencies of the current rule are built
* @param cpuToDepsCollectionMap a map from child configuration CPU to providers that "deps" of
* the current rule have propagated in that configuration
* @param splitToolchains a map from split toolchains for which dependencies of the current rule
* are built
* @param splitDeps a map from split "deps" of the current rule.
* @param dylibProviders {@link TransitiveInfoCollection}s that dynamic library dependencies of
* the current rule have propagated
* @throws RuleErrorException if there are attribute errors in the current rule context
*/
public ImmutableSet<DependencySpecificConfiguration> getDependencySpecificConfigurations(
Map<BuildConfigurationValue, CcToolchainProvider> childConfigurationsAndToolchains,
ImmutableListMultimap<String, TransitiveInfoCollection> cpuToDepsCollectionMap,
ImmutableList<TransitiveInfoCollection> dylibProviders)
throws RuleErrorException, InterruptedException {
public ImmutableMap<Optional<String>, DependencySpecificConfiguration>
getDependencySpecificConfigurations(
Map<Optional<String>, List<ConfiguredTargetAndData>> splitToolchains,
Map<Optional<String>, List<ConfiguredTargetAndData>> splitDeps,
ImmutableList<TransitiveInfoCollection> dylibProviders)
throws RuleErrorException, InterruptedException {
Iterable<ObjcProvider> dylibObjcProviders = getDylibObjcProviders(dylibProviders);
ImmutableSet.Builder<DependencySpecificConfiguration> childInfoBuilder = ImmutableSet.builder();

for (BuildConfigurationValue childToolchainConfig : childConfigurationsAndToolchains.keySet()) {
String childCpu = childToolchainConfig.getCpu();

ImmutableMap.Builder<Optional<String>, DependencySpecificConfiguration> childInfoBuilder =
ImmutableMap.builder();
for (Optional<String> splitTransitionKey : splitToolchains.keySet()) {
ConfiguredTargetAndData ctad =
Iterables.getOnlyElement(splitToolchains.get(splitTransitionKey));
BuildConfigurationValue childToolchainConfig = ctad.getConfiguration();
IntermediateArtifacts intermediateArtifacts =
ObjcRuleClasses.intermediateArtifacts(ruleContext, childToolchainConfig);

List<? extends TransitiveInfoCollection> propagatedDeps =
getProvidersFromCtads(splitDeps.get(splitTransitionKey));

ObjcCommon common =
common(
ruleContext,
childToolchainConfig,
intermediateArtifacts,
nullToEmptyList(cpuToDepsCollectionMap.get(childCpu)),
propagatedDeps,
dylibObjcProviders);
ObjcProvider objcProviderWithDylibSymbols = common.getObjcProvider();
ObjcProvider objcProvider =
objcProviderWithDylibSymbols.subtractSubtrees(dylibObjcProviders, ImmutableList.of());

childInfoBuilder.add(
CcToolchainProvider toolchainProvider =
ctad.getConfiguredTarget().get(CcToolchainProvider.PROVIDER);

childInfoBuilder.put(
splitTransitionKey,
DependencySpecificConfiguration.create(
childToolchainConfig,
childConfigurationsAndToolchains.get(childToolchainConfig),
objcProvider,
objcProviderWithDylibSymbols));
childToolchainConfig, toolchainProvider, objcProvider, objcProviderWithDylibSymbols));
}

return childInfoBuilder.build();
return childInfoBuilder.buildOrThrow();
}

/**
Expand Down Expand Up @@ -540,15 +515,23 @@ private ObjcCommon common(
return commonBuilder.build();
}

private <T> List<T> nullToEmptyList(List<T> inputList) {
return inputList != null ? inputList : ImmutableList.<T>of();
}

private static <T extends Info> ImmutableList<T> getTypedProviders(
Iterable<TransitiveInfoCollection> infoCollections, BuiltinProvider<T> providerClass) {
Iterable<? extends TransitiveInfoCollection> infoCollections,
BuiltinProvider<T> providerClass) {
return Streams.stream(infoCollections)
.filter(infoCollection -> infoCollection.get(providerClass) != null)
.map(infoCollection -> infoCollection.get(providerClass))
.collect(ImmutableList.toImmutableList());
}

/** Returns providers from a list of {@link ConfiguredTargetAndData} */
public static List<? extends TransitiveInfoCollection> getProvidersFromCtads(
List<ConfiguredTargetAndData> ctads) {
if (ctads == null) {
return ImmutableList.<TransitiveInfoCollection>of();
}
return ctads.stream()
.map(ConfiguredTargetAndData::getConfiguredTarget)
.collect(Collectors.toList());
}
}

0 comments on commit bdcc080

Please sign in to comment.