diff options
author | 2017-06-24 00:00:45 +0200 | |
---|---|---|
committer | 2017-06-26 18:35:25 +0200 | |
commit | 4bb735376958c3198fa664ca5247c93d9a3efcfb (patch) | |
tree | 4af3d349bd0b323c9dcbf7a753ea253ddfee8362 /src | |
parent | aacacfa05038884e2b13898c8152d7d4c12d4e03 (diff) |
Add apple_stub_binary rule.
This rule will be used by the Skylark bundling rules for product types that use
stub binaries copied out of the SDK instead of user-built binaries.
RELNOTES: None.
PiperOrigin-RevId: 159998782
Diffstat (limited to 'src')
6 files changed, 366 insertions, 42 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java index 530a677674..ff1542b565 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java @@ -121,6 +121,7 @@ import com.google.devtools.build.lib.rules.java.proto.JavaProtoSkylarkCommon; import com.google.devtools.build.lib.rules.objc.AppleBinaryRule; import com.google.devtools.build.lib.rules.objc.AppleSkylarkCommon; import com.google.devtools.build.lib.rules.objc.AppleStaticLibraryRule; +import com.google.devtools.build.lib.rules.objc.AppleStubBinaryRule; import com.google.devtools.build.lib.rules.objc.AppleWatch1ExtensionRule; import com.google.devtools.build.lib.rules.objc.AppleWatch2ExtensionRule; import com.google.devtools.build.lib.rules.objc.AppleWatchExtensionBinaryRule; @@ -563,6 +564,7 @@ public class BazelRuleClassProvider { builder.addNativeAspectClass(objcProtoAspect); builder.addRuleDefinition(new AppleBinaryRule(objcProtoAspect)); builder.addRuleDefinition(new AppleStaticLibraryRule(objcProtoAspect)); + builder.addRuleDefinition(new AppleStubBinaryRule()); builder.addRuleDefinition(new ObjcProtoLibraryRule(objcProtoAspect)); builder.addRuleDefinition(new AppleCcToolchainRule()); @@ -588,6 +590,7 @@ public class BazelRuleClassProvider { builder.addRuleDefinition(new ObjcRuleClasses.SimulatorRule()); builder.addRuleDefinition(new ObjcRuleClasses.CompilingRule()); builder.addRuleDefinition(new ObjcRuleClasses.LinkingRule(objcProtoAspect)); + builder.addRuleDefinition(new ObjcRuleClasses.PlatformRule()); builder.addRuleDefinition(new ObjcRuleClasses.MultiArchPlatformRule()); builder.addRuleDefinition(new ObjcRuleClasses.ResourcesRule()); builder.addRuleDefinition(new ObjcRuleClasses.AlwaysLinkRule()); diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinaryRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinaryRule.java index 372aa6f851..bfe8193cce 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinaryRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinaryRule.java @@ -16,7 +16,6 @@ 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.ImplicitOutputsFunction.fromTemplates; import static com.google.devtools.build.lib.syntax.Type.BOOLEAN; import static com.google.devtools.build.lib.syntax.Type.STRING; @@ -26,7 +25,6 @@ import com.google.devtools.build.lib.analysis.RuleDefinition; import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; import com.google.devtools.build.lib.packages.Attribute.AllowedValueSet; 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.packages.SkylarkProviderIdentifier; @@ -52,12 +50,6 @@ 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"); - - /** * There are 3 classes of fully linked binaries in Mach: executable, dynamic library, and * loadable bundle. * @@ -89,7 +81,9 @@ public class AppleBinaryRule implements RuleDefinition { new MultiArchSplitTransitionProvider(); return builder .requiresConfigurationFragments( - ObjcConfiguration.class, J2ObjcConfiguration.class, AppleConfiguration.class, + ObjcConfiguration.class, + J2ObjcConfiguration.class, + AppleConfiguration.class, CppConfiguration.class) .add( attr("$is_executable", BOOLEAN) @@ -123,8 +117,10 @@ public class AppleBinaryRule implements RuleDefinition { This attribute is deprecated and will be removed soon. It currently has no effect. "Extension-safe" link options may be added using the <code>linkopts</code> attribute. <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ - .add(attr(EXTENSION_SAFE_ATTR_NAME, BOOLEAN).value(false) - .nonconfigurable("Determines the configuration transition on deps")) + .add( + attr(EXTENSION_SAFE_ATTR_NAME, BOOLEAN) + .value(false) + .nonconfigurable("Determines the configuration transition on deps")) .add( attr(BUNDLE_LOADER_ATTR_NAME, LABEL) .direct_compile_time_input() @@ -143,7 +139,8 @@ public class AppleBinaryRule implements RuleDefinition { binary. All transitive dependencies and <code>srcs</code> are linked.</li> </ul> <!-- #END_BLAZE_RULE.IMPLICIT_OUTPUTS -->*/ - .setImplicitOutputsFunction(ImplicitOutputsFunction.fromFunctions(LIPOBIN)) + .setImplicitOutputsFunction( + ImplicitOutputsFunction.fromFunctions(ObjcRuleClasses.LIPOBIN_OUTPUT)) .cfg(AppleCrosstoolTransition.APPLE_CROSSTOOL_TRANSITION) .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStubBinary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStubBinary.java new file mode 100644 index 0000000000..537cb9e561 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStubBinary.java @@ -0,0 +1,198 @@ +// Copyright 2017 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.MULTI_ARCH_LINKED_BINARIES; +import static com.google.devtools.build.lib.syntax.Type.STRING; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.ConfigurationMakeVariableContext; +import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.FilesToRunProvider; +import com.google.devtools.build.lib.analysis.MakeVariableExpander; +import com.google.devtools.build.lib.analysis.MakeVariableExpander.ExpansionException; +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.actions.CustomCommandLine; +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.apple.AppleToolchain; +import com.google.devtools.build.lib.rules.apple.Platform; +import com.google.devtools.build.lib.rules.apple.Platform.PlatformType; +import com.google.devtools.build.lib.util.StringUtil; +import com.google.devtools.build.lib.vfs.PathFragment; + +/** Implementation for the "apple_stub_binary" rule. */ +public class AppleStubBinary implements RuleConfiguredTargetFactory { + + /** Provides substitutions for the make variables that can be used in an xcenv_based_path */ + private static class XcenvBasedPathVariableContext extends ConfigurationMakeVariableContext { + private final RuleContext ruleContext; + + /** The platform used to build $(PLATFORM_DIR). */ + private final Platform platform; + + /** The complete set of variables that may be used in paths. */ + public static final ImmutableList<String> DEFINED_VARS = + ImmutableList.of("$(SDKROOT)", "$(PLATFORM_DIR)"); + + public XcenvBasedPathVariableContext(RuleContext ruleContext, Platform platform) { + super( + ImmutableMap.<String, String>of(), + ruleContext.getRule().getPackage(), + ruleContext.getConfiguration()); + this.ruleContext = ruleContext; + this.platform = platform; + } + + /** Throws an exception if the given path is not rooted at a defined Make variable. */ + public void validatePathRoot(String path) throws RuleErrorException { + for (String var : DEFINED_VARS) { + if (path.startsWith(var)) { + return; + } + } + + throw ruleContext.throwWithAttributeError( + AppleStubBinaryRule.XCENV_BASED_PATH_ATTR, + String.format( + PATH_INCORRECTLY_ROOTED_ERROR_FORMAT, + StringUtil.joinEnglishList(XcenvBasedPathVariableContext.DEFINED_VARS, "or"))); + } + + @Override + public String lookupMakeVariable(String var) throws ExpansionException { + if (var.equals("SDKROOT")) { + return "__BAZEL_XCODE_SDKROOT__"; + } + if (var.equals("PLATFORM_DIR")) { + return AppleToolchain.platformDir(platform.getNameInPlist()); + } + // Intentionally do not call super, because we only want to allow these specific variables and + // discard any that might be inherited from toolchains and other contexts. + throw new MakeVariableExpander.ExpansionException("$(" + var + ") not defined"); + } + } + + @VisibleForTesting + public static final String PATH_INCORRECTLY_ROOTED_ERROR_FORMAT = + "The stub binary path must be rooted at %s"; + + @VisibleForTesting + public static final String PATH_NOT_NORMALIZED_ERROR = + "The stub binary path must be normalized (i.e., not contain \".\" or \"..\")"; + + @Override + public final ConfiguredTarget create(RuleContext ruleContext) + throws InterruptedException, RuleErrorException { + MultiArchSplitTransitionProvider.validateMinimumOs(ruleContext); + PlatformType platformType = MultiArchSplitTransitionProvider.getPlatformType(ruleContext); + + AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class); + + Platform platform = appleConfiguration.getMultiArchPlatform(platformType); + ImmutableListMultimap<BuildConfiguration, ObjcProvider> configurationToDepsMap = + ruleContext.getPrerequisitesByConfiguration("deps", Mode.SPLIT, ObjcProvider.class); + + Artifact outputArtifact = + ObjcRuleClasses.intermediateArtifacts(ruleContext).combinedArchitectureBinary(); + + registerActions(ruleContext, appleConfiguration, platform, outputArtifact); + + NestedSetBuilder<Artifact> filesToBuild = + NestedSetBuilder.<Artifact>stableOrder().add(outputArtifact); + RuleConfiguredTargetBuilder targetBuilder = + ObjcRuleClasses.ruleConfiguredTarget(ruleContext, filesToBuild.build()); + + ObjcProvider.Builder objcProviderBuilder = new ObjcProvider.Builder(); + for (ObjcProvider depProvider : configurationToDepsMap.values()) { + objcProviderBuilder.addTransitiveAndPropagate(depProvider); + } + objcProviderBuilder.add(MULTI_ARCH_LINKED_BINARIES, outputArtifact); + + ObjcProvider objcProvider = objcProviderBuilder.build(); + // TODO(cparsons): Stop propagating ObjcProvider directly from this rule. + targetBuilder.addProvider(ObjcProvider.class, objcProvider); + + targetBuilder.addNativeDeclaredProvider( + new AppleExecutableBinaryProvider(outputArtifact, objcProvider)); + + return targetBuilder.build(); + } + + private static FilesToRunProvider xcrunwrapper(RuleContext ruleContext) { + return ruleContext.getExecutablePrerequisite("$xcrunwrapper", Mode.HOST); + } + + /** Registers the actions that copy the stub binary to the target's output. */ + private static void registerActions( + RuleContext ruleContext, + AppleConfiguration appleConfiguration, + Platform platform, + Artifact outputBinary) + throws RuleErrorException { + CustomCommandLine copyCommandLine = + new CustomCommandLine.Builder() + .add("/bin/cp") + .add(resolveXcenvBasedPath(ruleContext, platform)) + .addExecPaths(ImmutableList.of(outputBinary)) + .build(); + + ruleContext.registerAction( + ObjcRuleClasses.spawnAppleEnvActionBuilder(appleConfiguration, platform) + .setExecutable(xcrunwrapper(ruleContext)) + .setCommandLine(copyCommandLine) + .setMnemonic("CopyStubExecutable") + .addOutput(outputBinary) + .disableSandboxing() + .build(ruleContext)); + } + + /** + * Returns the value of the xcenv_based_path attribute, emitting an error if its format is + * invalid. + * + * @param ruleContext the rule context + * @param platform the Apple platform + * @return the path string, if it was valid + * @throws RuleErrorException If the path string was invalid because it was not rooted at one of + * the allowed environment variables or it was not normalized + */ + private static String resolveXcenvBasedPath(RuleContext ruleContext, Platform platform) + throws RuleErrorException { + String pathString = + ruleContext.attributes().get(AppleStubBinaryRule.XCENV_BASED_PATH_ATTR, STRING); + XcenvBasedPathVariableContext makeVariableContext = + new XcenvBasedPathVariableContext(ruleContext, platform); + + makeVariableContext.validatePathRoot(pathString); + + PathFragment pathFragment = PathFragment.create(pathString); + if (!pathFragment.isNormalized()) { + throw ruleContext.throwWithAttributeError( + AppleStubBinaryRule.XCENV_BASED_PATH_ATTR, PATH_NOT_NORMALIZED_ERROR); + } + + return ruleContext.expandMakeVariables( + AppleStubBinaryRule.XCENV_BASED_PATH_ATTR, pathString, makeVariableContext); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStubBinaryRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStubBinaryRule.java new file mode 100644 index 0000000000..f2e2c59a2d --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStubBinaryRule.java @@ -0,0 +1,95 @@ +// Copyright 2017 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_LIST; +import static com.google.devtools.build.lib.syntax.Type.STRING; + +import com.google.common.collect.ImmutableList; +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.analysis.TransitiveInfoProvider; +import com.google.devtools.build.lib.packages.ImplicitOutputsFunction; +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_stub_binary. */ +public class AppleStubBinaryRule implements RuleDefinition { + + public static final String XCENV_BASED_PATH_ATTR = "xcenv_based_path"; + + @Override + public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { + MultiArchSplitTransitionProvider splitTransitionProvider = + new MultiArchSplitTransitionProvider(); + return builder + .requiresConfigurationFragments(ObjcConfiguration.class, AppleConfiguration.class) + /* <!-- #BLAZE_RULE(apple_stub_binary).ATTRIBUTE(xcenv_based_path) --> + The path to the stub executable within an Xcode platform or SDK bundle. This path must be + rooted at either <code>$(SDKROOT)</code> or <code>$(PLATFORM_DIR)</code> (written with + parentheses, as they are "Make" variables, not shell variables). + <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/ + .add(attr(XCENV_BASED_PATH_ATTR, STRING)) + /* <!-- #BLAZE_RULE(apple_stub_binary).ATTRIBUTE(deps) --> + The list of targets whose resources will be included in the final bundle. + <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/ + .add( + attr("deps", LABEL_LIST) + .direct_compile_time_input() + .mandatoryNativeProviders( + ImmutableList.<Class<? extends TransitiveInfoProvider>>of(ObjcProvider.class)) + .allowedFileTypes() + .cfg(splitTransitionProvider)) + /*<!-- #BLAZE_RULE(apple_stub_binary).IMPLICIT_OUTPUTS --> + <ul> + <li><code><var>name</var></code>: the stub executable copied from the Xcode + platform/SDK location.</li> + </ul> + <!-- #END_BLAZE_RULE.IMPLICIT_OUTPUTS -->*/ + .setImplicitOutputsFunction( + ImplicitOutputsFunction.fromFunctions(ObjcRuleClasses.LIPOBIN_OUTPUT)) + .build(); + } + + @Override + public Metadata getMetadata() { + return RuleDefinition.Metadata.builder() + .name("apple_stub_binary") + .factoryClass(AppleStubBinary.class) + .ancestors( + BaseRuleClasses.BaseRule.class, + ObjcRuleClasses.PlatformRule.class, + ObjcRuleClasses.XcrunRule.class) + .build(); + } +} + +/*<!-- #BLAZE_RULE (NAME = apple_stub_binary, TYPE = BINARY, FAMILY = Objective-C) --> + +<p>This rule copies a stub executable (such as that used by a watchOS application or an iMessage +sticker pack) from a location in an Xcode platform or SDK bundle to the output.</p> + +<p>This rule is meant to be used internally by the Apple bundling rules and does has limited use +outside of that. Its purpose is to provide target uniformity across all Apple bundles whether they +contain a user binary or a stub binary and to ensure that the platform transition is still present +for those stubs so that platform selection works as expected in downstream resource dependencies. +</p> + +${IMPLICIT_OUTPUTS} + +<!-- #END_BLAZE_RULE -->*/ diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/MultiArchSplitTransitionProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/MultiArchSplitTransitionProvider.java index 49f2dcaeaa..8c72933334 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/MultiArchSplitTransitionProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/MultiArchSplitTransitionProvider.java @@ -33,7 +33,7 @@ import com.google.devtools.build.lib.rules.apple.AppleConfiguration.Configuratio import com.google.devtools.build.lib.rules.apple.DottedVersion; import com.google.devtools.build.lib.rules.apple.Platform; import com.google.devtools.build.lib.rules.apple.Platform.PlatformType; -import com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.MultiArchPlatformRule; +import com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.PlatformRule; import java.util.List; /** @@ -63,11 +63,12 @@ public class MultiArchSplitTransitionProvider implements SplitTransitionProvider */ public static PlatformType getPlatformType(RuleContext ruleContext) throws RuleErrorException { String attributeValue = - ruleContext.attributes().get(MultiArchPlatformRule.PLATFORM_TYPE_ATTR_NAME, STRING); + ruleContext.attributes().get(PlatformRule.PLATFORM_TYPE_ATTR_NAME, STRING); try { return getPlatformType(attributeValue); } catch (IllegalArgumentException exception) { - throw ruleContext.throwWithAttributeError(MultiArchPlatformRule.PLATFORM_TYPE_ATTR_NAME, + throw ruleContext.throwWithAttributeError( + PlatformRule.PLATFORM_TYPE_ATTR_NAME, String.format(UNSUPPORTED_PLATFORM_TYPE_ERROR_FORMAT, attributeValue)); } } @@ -79,18 +80,19 @@ public class MultiArchSplitTransitionProvider implements SplitTransitionProvider * an invalid value */ public static void validateMinimumOs(RuleContext ruleContext) throws RuleErrorException { - String attributeValue = - ruleContext.attributes().get(MultiArchPlatformRule.MINIMUM_OS_VERSION, STRING); + String attributeValue = ruleContext.attributes().get(PlatformRule.MINIMUM_OS_VERSION, STRING); // TODO(b/37096178): This should be a mandatory attribute. if (!Strings.isNullOrEmpty(attributeValue)) { try { DottedVersion minimumOsVersion = DottedVersion.fromString(attributeValue); if (minimumOsVersion.hasAlphabeticCharacters() || minimumOsVersion.numComponents() > 2) { - throw ruleContext.throwWithAttributeError(MultiArchPlatformRule.MINIMUM_OS_VERSION, + throw ruleContext.throwWithAttributeError( + PlatformRule.MINIMUM_OS_VERSION, String.format(INVALID_VERSION_STRING_ERROR_FORMAT, attributeValue)); } } catch (IllegalArgumentException exception) { - throw ruleContext.throwWithAttributeError(MultiArchPlatformRule.MINIMUM_OS_VERSION, + throw ruleContext.throwWithAttributeError( + PlatformRule.MINIMUM_OS_VERSION, String.format(INVALID_VERSION_STRING_ERROR_FORMAT, attributeValue)); } } @@ -116,10 +118,8 @@ public class MultiArchSplitTransitionProvider implements SplitTransitionProvider @Override public SplitTransition<?> apply(Rule fromRule) { NonconfigurableAttributeMapper attrMapper = NonconfigurableAttributeMapper.of(fromRule); - String platformTypeString = - attrMapper.get(MultiArchPlatformRule.PLATFORM_TYPE_ATTR_NAME, STRING); - String minimumOsVersionString = - attrMapper.get(MultiArchPlatformRule.MINIMUM_OS_VERSION, STRING); + String platformTypeString = attrMapper.get(PlatformRule.PLATFORM_TYPE_ATTR_NAME, STRING); + String minimumOsVersionString = attrMapper.get(PlatformRule.MINIMUM_OS_VERSION, STRING); PlatformType platformType; Optional<DottedVersion> minimumOsVersion; try { diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java index eef0a42b8c..163704f760 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java @@ -19,6 +19,7 @@ import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTran 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 static com.google.devtools.build.lib.syntax.Type.STRING; import static com.google.devtools.build.lib.syntax.Type.STRING_LIST; @@ -44,6 +45,7 @@ import com.google.devtools.build.lib.packages.Attribute; import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel; import com.google.devtools.build.lib.packages.AttributeMap; import com.google.devtools.build.lib.packages.BuildType; +import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder; @@ -830,6 +832,12 @@ public class ObjcRuleClasses { static final String PROTOBUF_WELL_KNOWN_TYPES = "$protobuf_well_known_types"; /** + * Template for the fat binary output (using Apple's "lipo" tool to combine binaries of multiple + * architectures). + */ + static final SafeImplicitOutputsFunction LIPOBIN_OUTPUT = fromTemplates("%{name}_lipobin"); + + /** * Common attributes for {@code objc_*} rules that link sources and dependencies. */ public static class LinkingRule implements RuleDefinition { @@ -884,16 +892,16 @@ public class ObjcRuleClasses { } /** - * Common attributes for apple rules that build multi-architecture outputs for a given platform - * type (such as ios or watchos). + * Common attributes for apple rules that produce outputs for a given platform type (such as ios + * or watchos). */ - public static class MultiArchPlatformRule implements RuleDefinition { + public static class PlatformRule implements RuleDefinition { /** * Attribute name for apple platform type (e.g. ios or watchos). */ static final String PLATFORM_TYPE_ATTR_NAME = "platform_type"; - + /** * Attribute name for the minimum OS version (e.g. "7.3"). */ @@ -901,16 +909,8 @@ public class ObjcRuleClasses { @Override public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { - MultiArchSplitTransitionProvider splitTransitionProvider = - new MultiArchSplitTransitionProvider(); return builder - // 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(CHILD_CONFIG_ATTR, LABEL) - .cfg(splitTransitionProvider) - .value(ObjcRuleClasses.APPLE_TOOLCHAIN)) - /* <!-- #BLAZE_RULE($apple_multiarch_rule).ATTRIBUTE(platform_type) --> + /* <!-- #BLAZE_RULE($apple_platform_rule).ATTRIBUTE(platform_type) --> The type of platform for which to create artifacts in this rule. This dictates which Apple platform SDK is used for compilation/linking and which flag is @@ -935,13 +935,14 @@ public class ObjcRuleClasses { </ul> <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/ // TODO(b/37635370): Remove the "ios" default and make this mandatory. - .add(attr(PLATFORM_TYPE_ATTR_NAME, STRING) - .value(PlatformType.IOS.toString()) - .nonconfigurable("Determines the configuration transition on deps")) - /* <!-- #BLAZE_RULE($apple_multiarch_rule).ATTRIBUTE(minimum_os) --> + .add( + attr(PLATFORM_TYPE_ATTR_NAME, STRING) + .value(PlatformType.IOS.toString()) + .nonconfigurable("Determines the configuration transition on deps")) + /* <!-- #BLAZE_RULE($apple_platform_rule).ATTRIBUTE(minimum_os) --> The minimum OS version that this target and its dependencies should be built for. - This should be a dotted version string such as "7.3". + This should be a dotted version string such as "7.3". <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/ // TODO(b/37096178): This should be a mandatory attribute. .add( @@ -953,9 +954,39 @@ public class ObjcRuleClasses { @Override public Metadata getMetadata() { return RuleDefinition.Metadata.builder() + .name("$apple_platform_rule") + .type(RuleClassType.ABSTRACT) + .build(); + } + } + + /** + * Common attributes for apple rules that build multi-architecture outputs for a given platform + * type (such as ios or watchos). + */ + public static class MultiArchPlatformRule implements RuleDefinition { + + @Override + public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { + MultiArchSplitTransitionProvider splitTransitionProvider = + new MultiArchSplitTransitionProvider(); + return builder + // 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(CHILD_CONFIG_ATTR, LABEL) + .cfg(splitTransitionProvider) + .value(ObjcRuleClasses.APPLE_TOOLCHAIN)) + .build(); + } + + @Override + public Metadata getMetadata() { + return RuleDefinition.Metadata.builder() .name("$apple_multiarch_rule") .type(RuleClassType.ABSTRACT) - .ancestors(CrosstoolRule.class) + .ancestors(PlatformRule.class, CrosstoolRule.class) .build(); } } |