// 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.BUNDLE_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.GENERAL_RESOURCE_DIR; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.GENERAL_RESOURCE_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STRINGS; import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_BUNDLE_ID_ATTR; import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_DEFAULT_PROVISIONING_PROFILE_ATTR; import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_ENTITLEMENTS_ATTR; import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_INFOPLISTS_ATTR; import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_PROVISIONING_PROFILE_ATTR; import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_RESOURCES_ATTR; import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_STRINGS_ATTR; import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_STRUCTURED_RESOURCES_ATTR; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.rules.apple.AppleConfiguration; import com.google.devtools.build.lib.rules.apple.Platform.PlatformType; import com.google.devtools.build.lib.rules.objc.ReleaseBundlingSupport.LinkedBinary; import com.google.devtools.build.lib.syntax.Type; import javax.annotation.Nullable; /** * Contains support methods to build watch extension bundle - does normal bundle processing - * compiling and linking the binary, resources, plists and creates a final (signed if necessary) * bundle. * * @deprecated The native bundling rules have been deprecated. This class will be removed in the * future. */ @Deprecated public class Watch2ExtensionSupport { private final RuleContext ruleContext; private final IntermediateArtifacts intermediateArtifacts; private final String bundleName; private final Attributes attributes; /** * @param ruleContext the current rule context * @param intermediateArtifacts the utility object to obtain namespacing for intermediate bundling * artifacts * @param bundleName the name of the bundle */ Watch2ExtensionSupport( RuleContext ruleContext, IntermediateArtifacts intermediateArtifacts, String bundleName) { this.ruleContext = ruleContext; this.intermediateArtifacts = intermediateArtifacts; this.bundleName = bundleName; this.attributes = new Attributes(ruleContext); } /** * Registers actions to create a watchOS2 extension bundle and zip it into an {@code .ipa}. * * @param ipaArtifact an .ipa artifact containing to extension bundle; this is the output artifact * of the bundling */ void createBundle(Artifact ipaArtifact, NestedSetBuilder<Artifact> extensionFilesToBuild, ObjcProvider.Builder exposedObjcProviderBuilder) throws InterruptedException { ObjcProvider.Builder releaseBundlingObjcProviderBuilder = new ObjcProvider.Builder(); releaseBundlingObjcProviderBuilder.addTransitiveAndPropagate(attributes.binaryDependencies()); releaseBundlingObjcProviderBuilder .addAll(GENERAL_RESOURCE_FILE, attributes.resources()) .addAll(GENERAL_RESOURCE_FILE, attributes.strings()) .addAll( GENERAL_RESOURCE_DIR, ObjcCommon.xcodeStructuredResourceDirs(attributes.structuredResources())) .addAll(BUNDLE_FILE, BundleableFile.flattenedRawResourceFiles(attributes.resources())) .addAll( BUNDLE_FILE, BundleableFile.structuredRawResourceFiles(attributes.structuredResources())) .addAll(STRINGS, attributes.strings()); ObjcProvider releaseBundlingObjcProvider = releaseBundlingObjcProviderBuilder.build(); ReleaseBundling.Builder releaseBundling = new ReleaseBundling.Builder() .setIpaArtifact(ipaArtifact) .setBundleId(attributes.bundleId()) .setProvisioningProfile(attributes.provisioningProfile()) .setProvisioningProfileAttributeName(WATCH_EXT_PROVISIONING_PROFILE_ATTR) .setTargetDeviceFamilies(ImmutableSet.of(TargetDeviceFamily.WATCH)) .setIntermediateArtifacts(intermediateArtifacts) .setInfoPlistsFromRule(attributes.infoPlists()) .setEntitlements(attributes.entitlements()); if (attributes.isBundleIdExplicitySpecified()) { releaseBundling.setPrimaryBundleId(attributes.bundleId()); } else { releaseBundling.setFallbackBundleId(attributes.bundleId()); } AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class); ReleaseBundlingSupport releaseBundlingSupport = new ReleaseBundlingSupport( ruleContext, releaseBundlingObjcProvider, LinkedBinary.DEPENDENCIES_ONLY, ReleaseBundlingSupport.EXTENSION_BUNDLE_DIR_FORMAT, bundleName, appleConfiguration.getMinimumOsForPlatformType(PlatformType.WATCHOS), releaseBundling.build(), appleConfiguration.getMultiArchPlatform(PlatformType.WATCHOS)); releaseBundlingSupport .registerActions(DsymOutputType.APP) .addFilesToBuild(extensionFilesToBuild, Optional.of(DsymOutputType.APP)) .validateResources() .validateAttributes() .addExportedDebugArtifacts(exposedObjcProviderBuilder, DsymOutputType.APP); } /** Rule attributes used for creating watch application bundle. */ private static class Attributes { private final RuleContext ruleContext; private Attributes(RuleContext ruleContext) { this.ruleContext = ruleContext; } @Nullable Artifact provisioningProfile() { Artifact explicitProvisioningProfile = getPrerequisiteArtifact(WATCH_EXT_PROVISIONING_PROFILE_ATTR); if (explicitProvisioningProfile != null) { return explicitProvisioningProfile; } return getPrerequisiteArtifact(WATCH_EXT_DEFAULT_PROVISIONING_PROFILE_ATTR); } String bundleId() { Preconditions.checkState( !Strings.isNullOrEmpty( ruleContext.attributes().get(WATCH_EXT_BUNDLE_ID_ATTR, Type.STRING)), "requires a bundle_id value"); return ruleContext.attributes().get(WATCH_EXT_BUNDLE_ID_ATTR, Type.STRING); } ImmutableList<Artifact> infoPlists() { return getPrerequisiteArtifacts(WATCH_EXT_INFOPLISTS_ATTR); } ImmutableList<Artifact> strings() { return getPrerequisiteArtifacts(WATCH_EXT_STRINGS_ATTR); } ImmutableList<Artifact> resources() { return getPrerequisiteArtifacts(WATCH_EXT_RESOURCES_ATTR); } ImmutableList<Artifact> structuredResources() { return getPrerequisiteArtifacts(WATCH_EXT_STRUCTURED_RESOURCES_ATTR); } Iterable<ObjcProvider> binaryDependencies() { TransitiveInfoCollection info = ruleContext.getPrerequisite("binary", Mode.TARGET); AppleExecutableBinaryProvider binaryProvider = (AppleExecutableBinaryProvider) info.get( AppleExecutableBinaryProvider.SKYLARK_CONSTRUCTOR.getKey()); return ImmutableList.of(binaryProvider.getDepsObjcProvider()); } @Nullable Artifact entitlements() { return getPrerequisiteArtifact(WATCH_EXT_ENTITLEMENTS_ATTR); } private boolean isBundleIdExplicitySpecified() { return ruleContext.attributes().isAttributeValueExplicitlySpecified(WATCH_EXT_BUNDLE_ID_ATTR); } private ImmutableList<Artifact> getPrerequisiteArtifacts(String attribute) { return ruleContext.getPrerequisiteArtifacts(attribute, Mode.TARGET).list(); } @Nullable private Artifact getPrerequisiteArtifact(String attribute) { return ruleContext.getPrerequisiteArtifact(attribute, Mode.TARGET); } } }