forked from bazelbuild/bazel
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce apple_binary, which links together one or more c-family lib…
…raries and produces a potentially multi-architecture binary, controlled by the --ios_multi_cpus flag -- MOS_MIGRATED_REVID=120874805
- Loading branch information
1 parent
140634e
commit b5a76c5
Showing
8 changed files
with
341 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
159 changes: 159 additions & 0 deletions
159
src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
// 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 static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY; | ||
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY; | ||
|
||
import com.google.common.annotations.VisibleForTesting; | ||
import com.google.common.collect.ImmutableList; | ||
import com.google.common.collect.ImmutableListMultimap; | ||
import com.google.common.collect.Iterables; | ||
import com.google.devtools.build.lib.actions.Artifact; | ||
import com.google.devtools.build.lib.analysis.ConfiguredTarget; | ||
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; | ||
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; | ||
import com.google.devtools.build.lib.analysis.RuleContext; | ||
import com.google.devtools.build.lib.analysis.config.BuildConfiguration; | ||
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; | ||
import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; | ||
import com.google.devtools.build.lib.rules.apple.AppleConfiguration; | ||
import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider; | ||
import com.google.devtools.build.lib.rules.cpp.CppCompilationContext; | ||
import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs; | ||
import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; | ||
import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes; | ||
|
||
import java.util.List; | ||
import java.util.Set; | ||
|
||
/** | ||
* Implementation for the "apple_binary" rule. | ||
*/ | ||
public class AppleBinary implements RuleConfiguredTargetFactory { | ||
@VisibleForTesting | ||
static final String REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE = | ||
"At least one library dependency or source file is required."; | ||
|
||
@Override | ||
public final ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException { | ||
ImmutableListMultimap<BuildConfiguration, ObjcProvider> configurationToObjcDepMap = | ||
ruleContext.getPrerequisitesByConfiguration("deps", Mode.SPLIT, ObjcProvider.class); | ||
ImmutableListMultimap<BuildConfiguration, CppCompilationContext> configurationToCcDepMap = | ||
ruleContext.getPrerequisitesByConfiguration("deps", Mode.SPLIT, | ||
CppCompilationContext.class); | ||
ImmutableListMultimap<BuildConfiguration, ObjcProvider> configurationToNonPropagatedObjcMap = | ||
ruleContext.getPrerequisitesByConfiguration("non_propagated_deps", Mode.SPLIT, | ||
ObjcProvider.class); | ||
|
||
Set<BuildConfiguration> childConfigurations = getChildConfigurations(ruleContext); | ||
|
||
IntermediateArtifacts ruleIntermediateArtifacts = | ||
ObjcRuleClasses.intermediateArtifacts(ruleContext); | ||
|
||
NestedSetBuilder<Artifact> binariesToLipo = | ||
NestedSetBuilder.<Artifact>stableOrder(); | ||
NestedSetBuilder<Artifact> filesToBuild = | ||
NestedSetBuilder.<Artifact>stableOrder() | ||
.add(ruleIntermediateArtifacts.combinedArchitectureBinary()); | ||
|
||
for (BuildConfiguration childConfig : childConfigurations) { | ||
IntermediateArtifacts intermediateArtifacts = | ||
ObjcRuleClasses.intermediateArtifacts(ruleContext, childConfig); | ||
ObjcCommon common = common(ruleContext, childConfig, intermediateArtifacts, | ||
nullToEmptyList(configurationToObjcDepMap.get(childConfig)), | ||
nullToEmptyList(configurationToNonPropagatedObjcMap.get(childConfig)), | ||
nullToEmptyList(configurationToCcDepMap.get(childConfig))); | ||
ObjcProvider objcProvider = common.getObjcProvider(); | ||
if (!hasLibraryOrSources(objcProvider)) { | ||
ruleContext.ruleError(REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE); | ||
return null; | ||
} | ||
if (ruleContext.hasErrors()) { | ||
return null; | ||
} | ||
binariesToLipo.add(intermediateArtifacts.strippedSingleArchitectureBinary()); | ||
new CompilationSupport(ruleContext, childConfig) | ||
.registerCompileAndArchiveActions(common) | ||
.registerLinkActions( | ||
objcProvider, new ExtraLinkArgs(), ImmutableList.<Artifact>of(), | ||
DsymOutputType.APP) | ||
.validateAttributes(); | ||
|
||
if (ruleContext.hasErrors()) { | ||
return null; | ||
} | ||
} | ||
|
||
AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class); | ||
|
||
new LipoSupport(ruleContext).registerCombineArchitecturesAction( | ||
binariesToLipo.build(), | ||
ruleIntermediateArtifacts.combinedArchitectureBinary(), | ||
appleConfiguration.getIosCpuPlatform()); | ||
|
||
RuleConfiguredTargetBuilder targetBuilder = | ||
ObjcRuleClasses.ruleConfiguredTarget(ruleContext, filesToBuild.build()); | ||
|
||
return targetBuilder.build(); | ||
} | ||
|
||
private boolean hasLibraryOrSources(ObjcProvider objcProvider) { | ||
return !Iterables.isEmpty(objcProvider.get(LIBRARY)) // Includes sources from this target. | ||
|| !Iterables.isEmpty(objcProvider.get(IMPORTED_LIBRARY)); | ||
} | ||
|
||
private ObjcCommon common(RuleContext ruleContext, BuildConfiguration buildConfiguration, | ||
IntermediateArtifacts intermediateArtifacts, List<ObjcProvider> propagatedObjcDeps, | ||
List<ObjcProvider> nonPropagatedObjcDeps, List<CppCompilationContext> cppDeps) { | ||
CompilationArtifacts compilationArtifacts = | ||
CompilationSupport.compilationArtifacts(ruleContext, intermediateArtifacts); | ||
|
||
return new ObjcCommon.Builder(ruleContext, buildConfiguration) | ||
.setCompilationAttributes(new CompilationAttributes(ruleContext)) | ||
.setResourceAttributes(new ResourceAttributes(ruleContext)) | ||
.setCompilationArtifacts(compilationArtifacts) | ||
.addDefines(ruleContext.getTokenizedStringListAttr("defines")) | ||
.addDepObjcProviders(propagatedObjcDeps) | ||
.addDepCcHeaderProviders(cppDeps) | ||
// TODO(cparsons): The below call only gets CC link params from one child configuration, | ||
// as it is accessed via Mode.TARGET. This poses a problem with multi-architecture | ||
// builds with CC dependencies. | ||
.addDepCcLinkProviders(ruleContext) | ||
.addDepObjcProviders( | ||
ruleContext.getPrerequisites("bundles", Mode.TARGET, ObjcProvider.class)) | ||
.addNonPropagatedDepObjcProviders(nonPropagatedObjcDeps) | ||
.setIntermediateArtifacts(intermediateArtifacts) | ||
.setAlwayslink(false) | ||
.setHasModuleMap() | ||
.setLinkedBinary(intermediateArtifacts.strippedSingleArchitectureBinary()) | ||
.build(); | ||
} | ||
|
||
private <T> List<T> nullToEmptyList(List<T> inputList) { | ||
return inputList != null ? inputList : ImmutableList.<T>of(); | ||
} | ||
|
||
private Set<BuildConfiguration> getChildConfigurations(RuleContext ruleContext) { | ||
// This is currently a hack to obtain all child configurations regardless of the attribute | ||
// values of this rule -- this rule does not currently use the actual info provided by | ||
// this attribute. b/28403953 tracks cc toolchain usage. | ||
ImmutableListMultimap<BuildConfiguration, CcToolchainProvider> configToProvider = | ||
ruleContext.getPrerequisitesByConfiguration(":cc_toolchain", Mode.SPLIT, | ||
CcToolchainProvider.class); | ||
|
||
return configToProvider.keySet(); | ||
} | ||
} |
84 changes: 84 additions & 0 deletions
84
src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinaryRule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// 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 static com.google.devtools.build.lib.packages.Attribute.attr; | ||
import static com.google.devtools.build.lib.packages.BuildType.LABEL; | ||
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST; | ||
import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fromTemplates; | ||
import static com.google.devtools.build.lib.syntax.Type.BOOLEAN; | ||
|
||
import com.google.devtools.build.lib.analysis.BaseRuleClasses; | ||
import com.google.devtools.build.lib.analysis.RuleDefinition; | ||
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; | ||
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction; | ||
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; | ||
import com.google.devtools.build.lib.packages.RuleClass; | ||
import com.google.devtools.build.lib.packages.RuleClass.Builder; | ||
import com.google.devtools.build.lib.rules.apple.AppleConfiguration; | ||
|
||
/** | ||
* Rule definition for apple_binary. | ||
*/ | ||
public class AppleBinaryRule implements RuleDefinition { | ||
|
||
/** | ||
* Template for the fat binary output (using Apple's "lipo" tool to combine binaries of | ||
* multiple architectures). | ||
*/ | ||
private static final SafeImplicitOutputsFunction LIPOBIN = fromTemplates("%{name}_lipobin"); | ||
|
||
@Override | ||
public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { | ||
return builder | ||
.requiresConfigurationFragments(ObjcConfiguration.class, J2ObjcConfiguration.class, | ||
AppleConfiguration.class) | ||
.add(attr("$is_executable", BOOLEAN).value(true) | ||
.nonconfigurable("Called from RunCommand.isExecutable, which takes a Target")) | ||
.override(attr("deps", LABEL_LIST) | ||
.cfg(IosApplication.SPLIT_ARCH_TRANSITION) | ||
.direct_compile_time_input() | ||
.allowedRuleClasses(ObjcRuleClasses.CompilingRule.ALLOWED_DEPS_RULE_CLASSES) | ||
.allowedFileTypes()) | ||
.override(attr("non_propagated_deps", LABEL_LIST) | ||
.direct_compile_time_input() | ||
.cfg(IosApplication.SPLIT_ARCH_TRANSITION) | ||
.allowedRuleClasses(ObjcRuleClasses.CompilingRule.ALLOWED_DEPS_RULE_CLASSES) | ||
.allowedFileTypes()) | ||
.override(attr("srcs", LABEL_LIST) | ||
.direct_compile_time_input() | ||
.cfg(IosApplication.SPLIT_ARCH_TRANSITION) | ||
.allowedFileTypes(ObjcRuleClasses.SRCS_TYPE)) | ||
// This is currently a hack to obtain all child configurations regardless of the attribute | ||
// values of this rule -- this rule does not currently use the actual info provided by | ||
// this attribute. | ||
.add(attr(":cc_toolchain", LABEL) | ||
.cfg(IosApplication.SPLIT_ARCH_TRANSITION) | ||
.value(ObjcRuleClasses.APPLE_TOOLCHAIN)) | ||
.setImplicitOutputsFunction( | ||
ImplicitOutputsFunction.fromFunctions(LIPOBIN)) | ||
.build(); | ||
} | ||
|
||
@Override | ||
public Metadata getMetadata() { | ||
return RuleDefinition.Metadata.builder() | ||
.name("apple_binary") | ||
.factoryClass(AppleBinary.class) | ||
.ancestors(BaseRuleClasses.BaseRule.class, ObjcRuleClasses.LinkingRule.class, | ||
ObjcRuleClasses.XcodegenRule.class, ObjcRuleClasses.SimulatorRule.class) | ||
.build(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
src/main/java/com/google/devtools/build/lib/rules/objc/LipoSupport.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// 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.devtools.build.lib.actions.Artifact; | ||
import com.google.devtools.build.lib.analysis.RuleContext; | ||
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; | ||
import com.google.devtools.build.lib.collect.nestedset.NestedSet; | ||
import com.google.devtools.build.lib.rules.apple.Platform; | ||
|
||
/** | ||
* Support for registering actions using the Apple tool "lipo", which combines artifacts of | ||
* different architectures to make multi-architecture artifacts. | ||
*/ | ||
public class LipoSupport { | ||
private final RuleContext ruleContext; | ||
|
||
public LipoSupport(RuleContext ruleContext) { | ||
this.ruleContext = ruleContext; | ||
} | ||
|
||
/** | ||
* Registers an action to invoke "lipo" on all artifacts in {@code inputBinaries} to create the | ||
* {@code outputBinary} multi-architecture artifact, built for platform {@code platform}. | ||
*/ | ||
public void registerCombineArchitecturesAction(NestedSet<Artifact> inputBinaries, | ||
Artifact outputBinary, Platform platform) { | ||
|
||
ruleContext.registerAction(ObjcRuleClasses.spawnAppleEnvActionBuilder(ruleContext, platform) | ||
.setMnemonic("ObjcCombiningArchitectures") | ||
.addTransitiveInputs(inputBinaries) | ||
.addOutput(outputBinary) | ||
.setExecutable(CompilationSupport.xcrunwrapper(ruleContext)) | ||
.setCommandLine(CustomCommandLine.builder() | ||
.add(ObjcRuleClasses.LIPO) | ||
.addExecPaths("-create", inputBinaries) | ||
.addExecPath("-o", outputBinary) | ||
.build()) | ||
.build(ruleContext)); | ||
} | ||
} |
Oops, something went wrong.