blob: 61fbca942d22c98c878548beddfad23da1d37d93 [file] [log] [blame]
// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.rules.objc;
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;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
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.apple.AppleCommandLineOptions.AppleBitcodeMode;
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 java.util.Map;
import java.util.TreeMap;
/** Native support for Apple binary rules. */
public class AppleBinary {
private AppleBinary() {}
/**
* Links a (potentially multi-architecture) binary targeting Apple platforms.
*
* <p>This method comprises a bulk of the logic of the {@code apple_binary} rule, and is
* statically available so that it may be referenced by Starlark APIs that replicate its
* functionality.
*
* @param ruleContext the current rule context
* @param cppSemantics the cpp semantics to use
* @param avoidDeps a list of {@code TransitiveInfoColllection} that contain information about
* dependencies whose symbols are used by the linked binary but should not be linked into the
* binary itself
* @param extraLinkopts extra linkopts to pass to the linker actions
* @param extraLinkInputs extra input files to pass to the linker action
* @param isStampingEnabled whether linkstamping is enabled
* @return a tuple containing all necessary information about the linked binary
*/
public static AppleLinkingOutputs linkMultiArchBinary(
RuleContext ruleContext,
CppSemantics cppSemantics,
ImmutableList<TransitiveInfoCollection> avoidDeps,
Iterable<String> extraLinkopts,
Iterable<Artifact> extraLinkInputs,
boolean isStampingEnabled)
throws InterruptedException, RuleErrorException, ActionConflictException {
ImmutableListMultimap<String, TransitiveInfoCollection> cpuToDepsCollectionMap =
MultiArchBinarySupport.transformMap(ruleContext.getPrerequisitesByConfiguration("deps"));
ImmutableMap<BuildConfigurationValue, CcToolchainProvider> childConfigurationsAndToolchains =
MultiArchBinarySupport.getChildConfigurationsAndToolchains(ruleContext);
MultiArchBinarySupport multiArchBinarySupport =
new MultiArchBinarySupport(ruleContext, cppSemantics);
ImmutableSet<DependencySpecificConfiguration> dependencySpecificConfigurations =
multiArchBinarySupport.getDependencySpecificConfigurations(
childConfigurationsAndToolchains, cpuToDepsCollectionMap, avoidDeps);
Map<String, NestedSet<Artifact>> outputGroupCollector = new TreeMap<>();
ImmutableList.Builder<Artifact> allLinkInputs = ImmutableList.builder();
ImmutableList.Builder<String> allLinkopts = ImmutableList.builder();
allLinkInputs.addAll(extraLinkInputs);
allLinkopts.addAll(extraLinkopts);
ImmutableListMultimap<BuildConfigurationValue, CcInfo> buildConfigToCcInfoMap =
ruleContext.getPrerequisitesByConfiguration("deps", CcInfo.PROVIDER);
NestedSetBuilder<Artifact> headerTokens = NestedSetBuilder.stableOrder();
for (Map.Entry<BuildConfigurationValue, CcInfo> entry : buildConfigToCcInfoMap.entries()) {
CcInfo dep = entry.getValue();
headerTokens.addTransitive(dep.getCcCompilationContext().getHeaderTokens());
}
outputGroupCollector.put(OutputGroupInfo.VALIDATION, headerTokens.build());
ObjcProvider.Builder objcProviderBuilder =
new ObjcProvider.Builder(ruleContext.getAnalysisEnvironment().getStarlarkSemantics());
for (DependencySpecificConfiguration dependencySpecificConfiguration :
dependencySpecificConfigurations) {
objcProviderBuilder.addTransitiveAndPropagate(
dependencySpecificConfiguration.objcProviderWithDylibSymbols());
}
AppleDebugOutputsInfo.Builder legacyDebugOutputsBuilder =
AppleDebugOutputsInfo.Builder.create();
AppleLinkingOutputs.Builder builder =
new AppleLinkingOutputs.Builder().addOutputGroups(outputGroupCollector);
for (DependencySpecificConfiguration dependencySpecificConfiguration :
dependencySpecificConfigurations) {
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);
IntermediateArtifacts intermediateArtifacts =
new IntermediateArtifacts(
ruleContext, /*archiveFileNameSuffix*/ "", /*outputPrefix*/ "", childConfig);
String arch = childAppleConfig.getSingleArchitecture();
Artifact binaryArtifact =
multiArchBinarySupport.registerConfigurationSpecificLinkActions(
dependencySpecificConfiguration,
new ExtraLinkArgs(allLinkopts.build()),
allLinkInputs.build(),
isStampingEnabled,
cpuToDepsCollectionMap.get(configCpu),
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.
ApplePlatform cpuPlatform = ApplePlatform.forTargetCpu(configCpu);
AppleLinkingOutputs.LinkingOutput.Builder outputBuilder =
AppleLinkingOutputs.LinkingOutput.builder()
.setPlatform(cpuPlatform.getTargetPlatform())
.setArchitecture(arch)
.setEnvironment(cpuPlatform.getTargetEnvironment())
.setBinary(binaryArtifact);
if (childCppConfig.getAppleBitcodeMode() == AppleBitcodeMode.EMBEDDED) {
Artifact bitcodeSymbols = intermediateArtifacts.bitcodeSymbolMap();
outputBuilder.setBitcodeSymbols(bitcodeSymbols);
legacyDebugOutputsBuilder.addOutput(arch, OutputType.BITCODE_SYMBOLS, bitcodeSymbols);
}
if (childCppConfig.appleGenerateDsym()) {
Artifact dsymBinary =
childObjcConfig.shouldStripBinary()
? intermediateArtifacts.dsymSymbolForUnstrippedBinary()
: intermediateArtifacts.dsymSymbolForStrippedBinary();
outputBuilder.setDsymBinary(dsymBinary);
legacyDebugOutputsBuilder.addOutput(arch, OutputType.DSYM_BINARY, dsymBinary);
}
if (childObjcConfig.generateLinkmap()) {
Artifact linkmap = intermediateArtifacts.linkmap();
outputBuilder.setLinkmap(linkmap);
legacyDebugOutputsBuilder.addOutput(arch, OutputType.LINKMAP, linkmap);
}
builder.addOutput(outputBuilder.build());
}
return builder
.setDepsObjcProvider(objcProviderBuilder.build())
.setLegacyDebugOutputsProvider(legacyDebugOutputsBuilder.build())
.build();
}
}