// Copyright 2014 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.base.Optional; 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.RuleConfiguredTargetBuilder; import com.google.devtools.build.lib.analysis.RuleContext; 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.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.rules.apple.AppleConfiguration; import com.google.devtools.build.lib.rules.apple.AppleConfiguration.ConfigurationDistinguisher; import com.google.devtools.build.lib.rules.apple.DottedVersion; 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.rules.test.InstrumentedFilesCollector; import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; import javax.annotation.Nullable; /** * Base class for rules that bundle releases. * * @deprecated The native bundling rules have been deprecated. This class will be removed in the * future. */ @Deprecated public abstract class ReleaseBundlingTargetFactory implements RuleConfiguredTargetFactory { private final String bundleDirFormat; private final XcodeProductType xcodeProductType; private final ImmutableSet<Attribute> dependencyAttributes; private final ConfigurationDistinguisher configurationDistinguisher; /** * @param bundleDirFormat format string representing the bundle's directory with a single * placeholder for the target name (e.g. {@code "Payload/%s.app"}) * @param dependencyAttributes all attributes that contain dependencies of this rule. Any * dependency so listed must expose {@link XcodeProvider} and {@link ObjcProvider}. * @param configurationDistinguisher distinguisher used for cases where inputs from dependencies * of this bundle may need distinguishing because they come from configurations that are only * different by this value */ public ReleaseBundlingTargetFactory( String bundleDirFormat, XcodeProductType xcodeProductType, ImmutableSet<Attribute> dependencyAttributes, ConfigurationDistinguisher configurationDistinguisher) { this.bundleDirFormat = bundleDirFormat; this.xcodeProductType = xcodeProductType; this.dependencyAttributes = dependencyAttributes; this.configurationDistinguisher = configurationDistinguisher; } @Override public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException, RuleErrorException { ruleContext.ruleWarning( "This rule is deprecated. Please use the new Apple build rules " + "(https://github.com/bazelbuild/rules_apple) to build Apple targets."); validateAttributes(ruleContext); ObjcCommon common = common(ruleContext); XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder(); NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.stableOrder(); AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class); ReleaseBundlingSupport releaseBundlingSupport = new ReleaseBundlingSupport( ruleContext, common.getObjcProvider(), LinkedBinary.DEPENDENCIES_ONLY, bundleDirFormat, bundleName(ruleContext), bundleMinimumOsVersion(ruleContext), appleConfiguration.getMultiArchPlatform(PlatformType.IOS)); releaseBundlingSupport .registerActions(DsymOutputType.APP) .addXcodeSettings(xcodeProviderBuilder) .addFilesToBuild(filesToBuild, Optional.of(DsymOutputType.APP)) .validateResources() .validateAttributes(); XcodeSupport xcodeSupport = new XcodeSupport(ruleContext) .addFilesToBuild(filesToBuild) .addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), xcodeProductType, ruleContext.getFragment(AppleConfiguration.class).getDependencySingleArchitecture(), configurationDistinguisher) .addDummySource(xcodeProviderBuilder); for (Attribute attribute : dependencyAttributes) { xcodeSupport.addDependencies(xcodeProviderBuilder, attribute); } xcodeSupport.registerActions(xcodeProviderBuilder.build()); RuleConfiguredTargetBuilder targetBuilder = ObjcRuleClasses.ruleConfiguredTarget(ruleContext, filesToBuild.build()) .addProvider(XcTestAppProvider.class, releaseBundlingSupport.xcTestAppProvider()) .addProvider(XcodeProvider.class, xcodeProviderBuilder.build()) .addProvider( InstrumentedFilesProvider.class, InstrumentedFilesCollector.forward(ruleContext, "binary")); ObjcProvider exposedObjcProvider = exposedObjcProvider(ruleContext, releaseBundlingSupport); if (exposedObjcProvider != null) { targetBuilder.addProvider(ObjcProvider.class, exposedObjcProvider); } configureTarget(targetBuilder, ruleContext, releaseBundlingSupport); return targetBuilder.build(); } /** * Validates application-related attributes set on this rule and registers any errors with the * rule context. Default implemenation does nothing; subclasses may override it. */ protected void validateAttributes(RuleContext ruleContext) {} /** * Returns the minimum OS version this bundle's plist and resources should be generated for * (<b>not</b> the minimum OS version its binary is compiled with, that needs to be set in the * configuration). */ protected DottedVersion bundleMinimumOsVersion(RuleContext ruleContext) { return ruleContext.getFragment(AppleConfiguration.class) .getMinimumOsForPlatformType(PlatformType.IOS); } /** * Performs additional configuration of the target. The default implementation does nothing, but * subclasses may override it to add logic. * @throws InterruptedException */ protected void configureTarget(RuleConfiguredTargetBuilder target, RuleContext ruleContext, ReleaseBundlingSupport releaseBundlingSupport) throws InterruptedException {} /** * Returns the name of this target's bundle. */ protected String bundleName(RuleContext ruleContext) { return ruleContext.getLabel().getName(); } /** * Returns an exposed {@code ObjcProvider} object. * @throws InterruptedException */ @Nullable protected ObjcProvider exposedObjcProvider( RuleContext ruleContext, ReleaseBundlingSupport releaseBundlingSupport) throws InterruptedException { return null; } private ObjcCommon common(RuleContext ruleContext) { ObjcCommon.Builder builder = new ObjcCommon.Builder(ruleContext) .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)); for (Attribute attribute : dependencyAttributes) { builder.addDepObjcProviders( ruleContext.getPrerequisites( attribute.getName(), attribute.getAccessMode(), ObjcProvider.class)); } return builder.build(); } }