diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java | 107 |
1 files changed, 91 insertions, 16 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java index 325c7bfc86..017d245b81 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java @@ -14,10 +14,14 @@ package com.google.devtools.build.lib.rules.objc; +import static com.google.devtools.build.lib.syntax.Type.STRING; + import com.google.common.annotations.VisibleForTesting; 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.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; @@ -29,6 +33,7 @@ import com.google.devtools.build.lib.analysis.config.BuildOptions; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.packages.Attribute.SplitTransition; import com.google.devtools.build.lib.packages.Attribute.SplitTransitionProvider; +import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper; import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions; @@ -59,9 +64,17 @@ public class AppleBinary implements RuleConfiguredTargetFactory { static final String REQUIRES_AT_LEAST_ONE_SOURCE_FILE = "At least one source file is required (srcs, non_arc_srcs, or precompiled_srcs)."; + @VisibleForTesting + static final String UNSUPPORTED_PLATFORM_TYPE_ERROR_FORMAT = + "Unsupported platform type \"%s\""; + + private static final ImmutableSet<PlatformType> SUPPORTED_APPLE_BINARY_PLATFORM_TYPES = + ImmutableSet.of(PlatformType.IOS, PlatformType.WATCHOS); + @Override public final ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException, RuleErrorException { + PlatformType platformType = getPlatformType(ruleContext); ImmutableListMultimap<BuildConfiguration, ObjcProvider> configurationToNonPropagatedObjcMap = ruleContext.getPrerequisitesByConfiguration("non_propagated_deps", Mode.SPLIT, ObjcProvider.class); @@ -143,11 +156,11 @@ public class AppleBinary implements RuleConfiguredTargetFactory { .registerCombineArchitecturesAction( binariesToLipo.build(), ruleIntermediateArtifacts.combinedArchitectureBinary(), - appleConfiguration.getMultiArchPlatform(PlatformType.IOS)) + appleConfiguration.getMultiArchPlatform(platformType)) .registerCombineArchitecturesAction( archivesToLipo.build(), ruleContext.getImplicitOutputArtifact(AppleBinaryRule.LIPO_ARCHIVE), - appleConfiguration.getMultiArchPlatform(PlatformType.IOS)); + appleConfiguration.getMultiArchPlatform(platformType)); RuleConfiguredTargetBuilder targetBuilder = ObjcRuleClasses.ruleConfiguredTarget(ruleContext, filesToBuild.build()); @@ -205,22 +218,59 @@ public class AppleBinary implements RuleConfiguredTargetFactory { return configToProvider.keySet(); } + private static PlatformType getPlatformType(RuleContext ruleContext) throws RuleErrorException { + try { + return getPlatformType( + ruleContext.attributes().get(AppleBinaryRule.PLATFORM_TYPE_ATTR_NAME, STRING)); + } catch (IllegalArgumentException exception) { + throw ruleContext.throwWithAttributeError(AppleBinaryRule.PLATFORM_TYPE_ATTR_NAME, + String.format(UNSUPPORTED_PLATFORM_TYPE_ERROR_FORMAT, + ruleContext.attributes().get(AppleBinaryRule.PLATFORM_TYPE_ATTR_NAME, STRING))); + } + } + + private static PlatformType getPlatformType(String platformTypeString) { + PlatformType platformType = PlatformType.fromString(platformTypeString); + + if (!SUPPORTED_APPLE_BINARY_PLATFORM_TYPES.contains(platformType)) { + throw new IllegalArgumentException( + String.format(UNSUPPORTED_PLATFORM_TYPE_ERROR_FORMAT, platformTypeString)); + } else { + return platformType; + } + } + /** * {@link SplitTransitionProvider} implementation for the apple binary rule. */ public static class AppleBinaryTransitionProvider implements SplitTransitionProvider { - private static final IosMultiCpusTransition IOS_MULTI_CPUS_SPLIT_TRANSITION = - new IosMultiCpusTransition(); + private static final ImmutableMap<PlatformType, AppleBinaryTransition> + SPLIT_TRANSITIONS_BY_TYPE = ImmutableMap.<PlatformType, AppleBinaryTransition>builder() + .put(PlatformType.IOS, new AppleBinaryTransition(PlatformType.IOS)) + .put(PlatformType.WATCHOS, new AppleBinaryTransition(PlatformType.WATCHOS)) + .build(); @Override public SplitTransition<?> apply(Rule fromRule) { - // TODO(cparsons): Support different split transitions based on rule attribute. - return IOS_MULTI_CPUS_SPLIT_TRANSITION; + String platformTypeString = NonconfigurableAttributeMapper.of(fromRule) + .get(AppleBinaryRule.PLATFORM_TYPE_ATTR_NAME, STRING); + PlatformType platformType; + try { + platformType = getPlatformType(platformTypeString); + } catch (IllegalArgumentException exception) { + // There's no opportunity to propagate exception information up cleanly at the transition + // provider level. This will later be registered as a rule error during the initialization + // of the apple_binary target. + platformType = PlatformType.IOS; + } + + return SPLIT_TRANSITIONS_BY_TYPE.get(platformType); } public List<SplitTransition<BuildOptions>> getPotentialSplitTransitions() { - return ImmutableList.<SplitTransition<BuildOptions>>of(IOS_MULTI_CPUS_SPLIT_TRANSITION); + return ImmutableList.<SplitTransition<BuildOptions>>copyOf( + SPLIT_TRANSITIONS_BY_TYPE.values()); } } @@ -228,29 +278,54 @@ public class AppleBinary implements RuleConfiguredTargetFactory { * Transition that results in one configured target per architecture specified in {@code * --ios_multi_cpus}. */ - protected static class IosMultiCpusTransition implements SplitTransition<BuildOptions> { + protected static class AppleBinaryTransition implements SplitTransition<BuildOptions> { + + private final PlatformType platformType; + + public AppleBinaryTransition(PlatformType platformType) { + this.platformType = platformType; + } @Override public final List<BuildOptions> split(BuildOptions buildOptions) { - List<String> iosMultiCpus = buildOptions.get(AppleCommandLineOptions.class).iosMultiCpus; + List<String> cpus; + ConfigurationDistinguisher configurationDistinguisher; + switch (platformType) { + case IOS: + cpus = buildOptions.get(AppleCommandLineOptions.class).iosMultiCpus; + configurationDistinguisher = ConfigurationDistinguisher.APPLEBIN_IOS; + break; + case WATCHOS: + cpus = buildOptions.get(AppleCommandLineOptions.class).watchosCpus; + if (cpus.isEmpty()) { + cpus = ImmutableList.of(AppleCommandLineOptions.DEFAULT_WATCHOS_CPU); + } + configurationDistinguisher = ConfigurationDistinguisher.APPLEBIN_WATCHOS; + break; + default: + throw new IllegalArgumentException("Unsupported platform type " + platformType); + } ImmutableList.Builder<BuildOptions> splitBuildOptions = ImmutableList.builder(); - for (String iosCpu : iosMultiCpus) { + for (String cpu : cpus) { BuildOptions splitOptions = buildOptions.clone(); - splitOptions.get(AppleCommandLineOptions.class).iosMultiCpus = ImmutableList.of(); - splitOptions.get(AppleCommandLineOptions.class).applePlatformType = PlatformType.IOS; - splitOptions.get(AppleCommandLineOptions.class).appleSplitCpu = iosCpu; - splitOptions.get(AppleCommandLineOptions.class).iosCpu = iosCpu; + splitOptions.get(AppleCommandLineOptions.class).applePlatformType = platformType; + splitOptions.get(AppleCommandLineOptions.class).appleSplitCpu = cpu; + // Set for backwards compatibility with rules that depend on this flag, even when + // ios is not the platform type. + // TODO(b/28958783): Clean this up. + splitOptions.get(AppleCommandLineOptions.class).iosCpu = cpu; if (splitOptions.get(ObjcCommandLineOptions.class).enableCcDeps) { // Only set the (CC-compilation) CPU for dependencies if explicitly required by the user. // This helps users of the iOS rules who do not depend on CC rules as these CPU values // require additional flags to work (e.g. a custom crosstool) which now only need to be // set if this feature is explicitly requested. - splitOptions.get(BuildConfiguration.Options.class).cpu = "ios_" + iosCpu; + splitOptions.get(BuildConfiguration.Options.class).cpu = + String.format("%s_%s", platformType, cpu); } splitOptions.get(AppleCommandLineOptions.class).configurationDistinguisher = - ConfigurationDistinguisher.APPLEBIN_IOS; + configurationDistinguisher; splitBuildOptions.add(splitOptions); } return splitBuildOptions.build(); |