From 86fdf0b2495888fc2c3e8c84e0b2f02f566187f9 Mon Sep 17 00:00:00 2001 From: kaipi Date: Thu, 25 Jan 2018 09:43:38 -0800 Subject: Remove ios_test from Bazel. ios_test is an old rule and this removal is part of the final steps of the migration process into Skylark. If you were using ios_test, please take a look at ios_unit_test provided by the github.com/bazelbuild/rules_apple project. PiperOrigin-RevId: 183251623 --- .../lib/bazel/rules/BazelRuleClassProvider.java | 6 - .../build/lib/rules/objc/AppleSkylarkCommon.java | 43 - .../lib/rules/objc/AppleStaticLibraryRule.java | 3 +- .../build/lib/rules/objc/CompilationSupport.java | 11 +- .../devtools/build/lib/rules/objc/IosTest.java | 288 ----- .../devtools/build/lib/rules/objc/IosTestRule.java | 157 --- .../build/lib/rules/objc/ObjcBundleLibrary.java | 12 +- .../build/lib/rules/objc/ObjcRuleClasses.java | 273 ----- .../build/lib/rules/objc/ReleaseBundling.java | 395 ------- .../lib/rules/objc/ReleaseBundlingSupport.java | 1250 -------------------- .../devtools/build/lib/rules/objc/Storyboards.java | 76 -- .../devtools/build/lib/rules/objc/TestSupport.java | 329 ------ .../build/lib/rules/objc/XcTestAppProvider.java | 101 -- 13 files changed, 13 insertions(+), 2931 deletions(-) delete mode 100644 src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java delete mode 100644 src/main/java/com/google/devtools/build/lib/rules/objc/IosTestRule.java delete mode 100644 src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundling.java delete mode 100644 src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java delete mode 100644 src/main/java/com/google/devtools/build/lib/rules/objc/Storyboards.java delete mode 100644 src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java delete mode 100644 src/main/java/com/google/devtools/build/lib/rules/objc/XcTestAppProvider.java (limited to 'src/main/java/com/google') 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 0e7782c7f7..76df32e66d 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 @@ -135,7 +135,6 @@ 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.IosDeviceRule; -import com.google.devtools.build.lib.rules.objc.IosTestRule; import com.google.devtools.build.lib.rules.objc.J2ObjcAspect; import com.google.devtools.build.lib.rules.objc.J2ObjcCommandLineOptions; import com.google.devtools.build.lib.rules.objc.J2ObjcConfiguration; @@ -552,7 +551,6 @@ public class BazelRuleClassProvider { builder.addRuleDefinition(new AppleCcToolchainRule()); builder.addRuleDefinition(new AppleToolchain.RequiresXcodeConfigRule(toolsRepository)); builder.addRuleDefinition(new IosDeviceRule()); - builder.addRuleDefinition(new IosTestRule()); builder.addRuleDefinition(new ObjcBundleRule()); builder.addRuleDefinition(new ObjcBundleLibraryRule()); builder.addRuleDefinition(new ObjcFrameworkRule()); @@ -561,8 +559,6 @@ public class BazelRuleClassProvider { builder.addRuleDefinition(new ObjcRuleClasses.CoptsRule()); builder.addRuleDefinition(new ObjcRuleClasses.BundlingRule()); builder.addRuleDefinition(new ObjcRuleClasses.DylibDependingRule(objcProtoAspect)); - builder.addRuleDefinition(new ObjcRuleClasses.ReleaseBundlingRule()); - builder.addRuleDefinition(new ObjcRuleClasses.SimulatorRule()); builder.addRuleDefinition(new ObjcRuleClasses.CompilingRule()); builder.addRuleDefinition(new ObjcRuleClasses.LinkingRule(objcProtoAspect)); builder.addRuleDefinition(new ObjcRuleClasses.PlatformRule()); @@ -574,8 +570,6 @@ public class BazelRuleClassProvider { builder.addRuleDefinition(new ObjcRuleClasses.ResourceToolsRule()); builder.addRuleDefinition(new ObjcRuleClasses.XcrunRule()); builder.addRuleDefinition(new ObjcRuleClasses.LibtoolRule()); - builder.addRuleDefinition(new ObjcRuleClasses.IpaRule()); - builder.addRuleDefinition(new ObjcRuleClasses.ReleaseBundlingToolsRule()); builder.addRuleDefinition(new ObjcRuleClasses.CrosstoolRule()); builder.addRuleDefinition(new XcodeConfigRule()); builder.addRuleDefinition(new XcodeConfigAliasRule()); diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java index ff81e4cac2..d72a550377 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java @@ -403,49 +403,6 @@ public class AppleSkylarkCommon { } }; - @SkylarkSignature( - name = "new_xctest_app_provider", - objectType = AppleSkylarkCommon.class, - returnType = XcTestAppProvider.class, - doc = "Creates a new XcTestAppProvider instance.", - parameters = { - @Param(name = "self", type = AppleSkylarkCommon.class, doc = "The apple_common instance."), - @Param( - name = "bundle_loader", - type = Artifact.class, - named = true, - positional = false, - doc = "The bundle loader for the test. Corresponds to the binary inside the test IPA." - ), - @Param( - name = "ipa", - type = Artifact.class, - named = true, - positional = false, - doc = "The test IPA." - ), - @Param( - name = "objc_provider", - type = ObjcProvider.class, - named = true, - positional = false, - doc = "An ObjcProvider that should be included by tests using this test bundle." - ) - } - ) - public static final BuiltinFunction NEW_XCTEST_APP_PROVIDER = - new BuiltinFunction("new_xctest_app_provider") { - @SuppressWarnings("unused") - // This method is registered statically for skylark, and never called directly. - public XcTestAppProvider invoke( - AppleSkylarkCommon self, - Artifact bundleLoader, - Artifact ipa, - ObjcProvider objcProvider) { - return new XcTestAppProvider(bundleLoader, ipa, objcProvider); - } - }; - @SkylarkSignature( name = "new_dynamic_framework_provider", objectType = AppleSkylarkCommon.class, diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStaticLibraryRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStaticLibraryRule.java index 36ad180077..082ba3fbdd 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStaticLibraryRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleStaticLibraryRule.java @@ -116,8 +116,7 @@ public class AppleStaticLibraryRule implements RuleDefinition { return RuleDefinition.Metadata.builder() .name("apple_static_library") .factoryClass(AppleStaticLibrary.class) - .ancestors(BaseRuleClasses.BaseRule.class, ObjcRuleClasses.MultiArchPlatformRule.class, - ObjcRuleClasses.SimulatorRule.class) + .ancestors(BaseRuleClasses.BaseRule.class, ObjcRuleClasses.MultiArchPlatformRule.class) .build(); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java index 6eadae643e..6f574abe67 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java @@ -977,7 +977,7 @@ public class CompilationSupport { INSTRUMENTATION_SPEC, new ObjcCoverageMetadataCollector(), oFiles.build(), - getGcovForObjectiveCIfNeeded(), + NestedSetBuilder.emptySet(Order.STABLE_ORDER), // The COVERAGE_GCOV_PATH environment variable is added in TestSupport#getExtraProviders() NestedSetBuilder.>emptySet(Order.COMPILE_ORDER), !isTestRule); @@ -1721,15 +1721,6 @@ public class CompilationSupport { .build(ruleContext)); } - private NestedSet getGcovForObjectiveCIfNeeded() { - if (ruleContext.getConfiguration().isCodeCoverageEnabled() - && ruleContext.attributes().has(IosTest.OBJC_GCOV_ATTR, BuildType.LABEL)) { - return PrerequisiteArtifacts.nestedSet(ruleContext, IosTest.OBJC_GCOV_ATTR, Mode.HOST); - } else { - return NestedSetBuilder.emptySet(Order.STABLE_ORDER); - } - } - private CompilationSupport registerGenerateUmbrellaHeaderAction( Artifact umbrellaHeader, Iterable publicHeaders) { ruleContext.registerAction( diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java deleted file mode 100644 index bb888f0f90..0000000000 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java +++ /dev/null @@ -1,288 +0,0 @@ -// 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 static com.google.devtools.build.lib.rules.objc.ObjcProvider.STORYBOARD; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XCDATAMODEL; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.devtools.build.lib.actions.Artifact; -import com.google.devtools.build.lib.actions.ExecutionRequirements; -import com.google.devtools.build.lib.analysis.ConfiguredTarget; -import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; -import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory; -import com.google.devtools.build.lib.analysis.RuleContext; -import com.google.devtools.build.lib.analysis.Runfiles; -import com.google.devtools.build.lib.analysis.RunfilesProvider; -import com.google.devtools.build.lib.analysis.RunfilesSupport; -import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; -import com.google.devtools.build.lib.analysis.test.ExecutionInfo; -import com.google.devtools.build.lib.analysis.test.InstrumentedFilesProvider; -import com.google.devtools.build.lib.collect.nestedset.NestedSet; -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.ApplePlatform.PlatformType; -import com.google.devtools.build.lib.rules.apple.XcodeConfig; -import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs; -import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes; -import com.google.devtools.build.lib.rules.objc.ReleaseBundlingSupport.LinkedBinary; -import com.google.devtools.build.lib.rules.proto.ProtoSourcesProvider; - -/** Implementation for {@code ios_test} rule in Bazel. */ -public final class IosTest implements RuleConfiguredTargetFactory { - - private static final ImmutableList AUTOMATIC_SDK_FRAMEWORKS_FOR_XCTEST = - ImmutableList.of(new SdkFramework("XCTest")); - - // Attributes for IosTest rules. - // Documentation on usage is in {@link IosTestRule@}. - static final String OBJC_GCOV_ATTR = "$objc_gcov"; - static final String DEVICE_ARG_ATTR = "ios_device_arg"; - static final String IS_XCTEST_ATTR = "xctest"; - static final String MEMLEAKS_DEP_ATTR = "$memleaks_dep"; - static final String MEMLEAKS_PLUGIN_ATTR = "$memleaks_plugin"; - static final String PLUGINS_ATTR = "plugins"; - static final String TARGET_DEVICE = "target_device"; - static final String TEST_RUNNER_ATTR = "$test_runner"; - static final String TEST_TARGET_DEVICE_ATTR = "ios_test_target_device"; - static final String TEST_TEMPLATE_ATTR = "$test_template"; - static final String XCTEST_APP_ATTR = "xctest_app"; - static final String MCOV_TOOL_ATTR = ":mcov"; - - @VisibleForTesting - public static final String REQUIRES_SOURCE_ERROR = - "ios_test requires at least one source file in srcs or non_arc_srcs"; - - @VisibleForTesting - public static final String NO_MULTI_CPUS_ERROR = - "ios_test cannot be built for multiple CPUs at the same time"; - - /** - * {@inheritDoc} - * - *

Creates a target, including registering actions, just as {@link #create(RuleContext)} does. - * The difference between {@link #create(RuleContext)} and this method is that this method does - * only what is needed to support tests on the environment besides build the app and test {@code - * .ipa}s. The {@link #create(RuleContext)} method delegates to this method. - */ - @Override - public final 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."); - - Iterable objcProtoProviders = - ruleContext.getPrerequisites("deps", Mode.TARGET, ObjcProtoProvider.SKYLARK_CONSTRUCTOR); - - ProtobufSupport protoSupport = - new ProtobufSupport( - ruleContext, - ruleContext.getConfiguration(), - ImmutableList.of(), - objcProtoProviders, - ProtobufSupport.getTransitivePortableProtoFilters(objcProtoProviders)) - .registerGenerationActions() - .registerCompilationActions(); - Optional protosObjcProvider = protoSupport.getObjcProvider(); - - ObjcCommon common = common(ruleContext, protosObjcProvider); - - if (!common.getCompilationArtifacts().get().getArchive().isPresent()) { - ruleContext.ruleError(REQUIRES_SOURCE_ERROR); - } - - if (!ruleContext.getFragment(AppleConfiguration.class).getIosMultiCpus().isEmpty()) { - ruleContext.ruleError(NO_MULTI_CPUS_ERROR); - } - - NestedSetBuilder filesToBuild = NestedSetBuilder.stableOrder(); - addResourceFilesToBuild(ruleContext, common.getObjcProvider(), filesToBuild); - - ExtraLinkArgs extraLinkArgs; - Iterable extraLinkInputs; - String bundleFormat; - XcTestAppProvider testApp = xcTestAppProvider(ruleContext); - Artifact bundleLoader = testApp.getBundleLoader(); - - // -bundle causes this binary to be linked as a bundle and not require an entry point - // (i.e. main()) - // -bundle_loader causes the code in this test to have access to the symbols in the test rig, - // or more specifically, the flag causes ld to consider the given binary when checking for - // missing symbols. - // -rpath @loader_path/Frameworks allows test bundles to load dylibs from the app's - // Frameworks directory. - extraLinkArgs = - new ExtraLinkArgs( - "-bundle", - "-bundle_loader", - bundleLoader.getExecPathString(), - "-Xlinker", - "-rpath", - "-Xlinker", - "@loader_path/Frameworks"); - - extraLinkInputs = ImmutableList.of(bundleLoader); - bundleFormat = ReleaseBundlingSupport.XCTEST_BUNDLE_DIR_FORMAT; - - filesToBuild.add(testApp.getIpa()); - - J2ObjcMappingFileProvider j2ObjcMappingFileProvider = - J2ObjcMappingFileProvider.union( - ruleContext.getPrerequisites("deps", Mode.TARGET, J2ObjcMappingFileProvider.class)); - J2ObjcEntryClassProvider j2ObjcEntryClassProvider = - new J2ObjcEntryClassProvider.Builder() - .addTransitive( - ruleContext.getPrerequisites("deps", Mode.TARGET, J2ObjcEntryClassProvider.class)) - .build(); - - CompilationSupport compilationSupport = - new CompilationSupport.Builder().setRuleContext(ruleContext).setIsTestRule().build(); - - compilationSupport - .registerLinkActions( - common.getObjcProvider(), - j2ObjcMappingFileProvider, - j2ObjcEntryClassProvider, - extraLinkArgs, - extraLinkInputs, - DsymOutputType.TEST) - .registerCompileAndArchiveActions(common) - .registerFullyLinkAction( - common.getObjcProvider(), - ruleContext.getImplicitOutputArtifact(CompilationSupport.FULLY_LINKED_LIB)) - .validateAttributes(); - - AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class); - new ReleaseBundlingSupport( - ruleContext, - common.getObjcProvider(), - LinkedBinary.LOCAL_AND_DEPENDENCIES, - bundleFormat, - XcodeConfig.getMinimumOsForPlatformType(ruleContext, PlatformType.IOS), - appleConfiguration.getMultiArchPlatform(PlatformType.IOS)) - .registerActions(DsymOutputType.TEST) - .addFilesToBuild(filesToBuild, Optional.of(DsymOutputType.TEST)) - .validateResources() - .validateAttributes(); - - new ResourceSupport(ruleContext).validateAttributes(); - - NestedSet filesToBuildSet = filesToBuild.build(); - - Runfiles.Builder runfilesBuilder = - new Runfiles.Builder( - ruleContext.getWorkspaceName(), - ruleContext.getConfiguration().legacyExternalRunfiles()) - .addRunfiles(ruleContext, RunfilesProvider.DEFAULT_RUNFILES); - - NestedSetBuilder filesToBuildBuilder = - NestedSetBuilder.stableOrder().addTransitive(filesToBuildSet); - - InstrumentedFilesProvider instrumentedFilesProvider = - new CompilationSupport.Builder() - .setRuleContext(ruleContext) - .build() - .getInstrumentedFilesProvider(common); - - TestSupport testSupport = - new TestSupport(ruleContext) - .registerTestRunnerActions() - .addRunfiles(runfilesBuilder, instrumentedFilesProvider) - .addFilesToBuild(filesToBuildBuilder); - - Artifact executable = testSupport.generatedTestScript(); - - Runfiles runfiles = runfilesBuilder.build(); - RunfilesSupport runfilesSupport = - RunfilesSupport.withExecutable(ruleContext, runfiles, executable); - - ImmutableMap.Builder execInfoMapBuilder = new ImmutableMap.Builder<>(); - execInfoMapBuilder.put(ExecutionRequirements.REQUIRES_DARWIN, ""); - if (ruleContext.getFragment(ObjcConfiguration.class).runMemleaks()) { - execInfoMapBuilder.put("nosandbox", ""); - } - - return new RuleConfiguredTargetBuilder(ruleContext) - .setFilesToBuild(filesToBuildBuilder.build()) - .addProvider(RunfilesProvider.simple(runfiles)) - .addNativeDeclaredProvider(new ExecutionInfo(execInfoMapBuilder.build())) - .addNativeDeclaredProviders(testSupport.getExtraProviders()) - .addProvider(InstrumentedFilesProvider.class, instrumentedFilesProvider) - .setRunfilesSupport(runfilesSupport, executable) - .build(); - } - - private void addResourceFilesToBuild( - RuleContext ruleContext, ObjcProvider objcProvider, NestedSetBuilder filesToBuild) { - IntermediateArtifacts intermediateArtifacts = - ObjcRuleClasses.intermediateArtifacts(ruleContext); - - Iterable xcdatamodels = - Xcdatamodels.xcdatamodels(intermediateArtifacts, objcProvider.get(XCDATAMODEL)); - filesToBuild.addAll(Xcdatamodel.outputZips(xcdatamodels)); - - for (Artifact storyboard : objcProvider.get(STORYBOARD)) { - filesToBuild.add(intermediateArtifacts.compiledStoryboardZip(storyboard)); - } - } - - /** Constructs an {@link ObjcCommon} instance based on the attributes. */ - private ObjcCommon common(RuleContext ruleContext, Optional protosObjcProvider) { - CompilationArtifacts compilationArtifacts = - CompilationSupport.compilationArtifacts(ruleContext); - - ObjcCommon.Builder builder = - new ObjcCommon.Builder(ruleContext) - .setCompilationAttributes( - CompilationAttributes.Builder.fromRuleContext(ruleContext).build()) - .setCompilationArtifacts(compilationArtifacts) - .setResourceAttributes(new ResourceAttributes(ruleContext)) - .addDefines(ruleContext.getExpander().withDataLocations().tokenized("defines")) - .addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET)) - .addRuntimeDeps(ruleContext.getPrerequisites("runtime_deps", Mode.TARGET)) - .addDeps(ruleContext.getPrerequisites("bundles", Mode.TARGET)) - .addDepObjcProviders(protosObjcProvider.asSet()) - .addNonPropagatedDepObjcProviders( - ruleContext.getPrerequisites( - "non_propagated_deps", Mode.TARGET, ObjcProvider.SKYLARK_CONSTRUCTOR)) - .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) - .setHasModuleMap(); - - builder - .addExtraSdkFrameworks(AUTOMATIC_SDK_FRAMEWORKS_FOR_XCTEST) - .addDepObjcProviders(ImmutableList.of(xcTestAppProvider(ruleContext).getObjcProvider())); - - // Add the memleaks library if the --ios_memleaks flag is true. The library pauses the test - // after all tests have been executed so that leaks can be run. - ObjcConfiguration config = ruleContext.getFragment(ObjcConfiguration.class); - if (config.runMemleaks()) { - builder.addDepObjcProviders( - ruleContext.getPrerequisites( - MEMLEAKS_DEP_ATTR, Mode.TARGET, ObjcProvider.SKYLARK_CONSTRUCTOR)); - } - - return builder.build(); - } - - /** Returns the {@link XcTestAppProvider} of the {@code xctest_app} attribute. */ - protected static XcTestAppProvider xcTestAppProvider(RuleContext ruleContext) { - return ruleContext.getPrerequisite( - XCTEST_APP_ATTR, Mode.TARGET, XcTestAppProvider.SKYLARK_CONSTRUCTOR); - } -} diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTestRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosTestRule.java deleted file mode 100644 index 892da8535c..0000000000 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTestRule.java +++ /dev/null @@ -1,157 +0,0 @@ -// 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 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.syntax.Type.BOOLEAN; -import static com.google.devtools.build.lib.syntax.Type.STRING_LIST; - -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.config.BuildConfiguration; -import com.google.devtools.build.lib.analysis.config.HostTransition; -import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; -import com.google.devtools.build.lib.packages.RuleClass; -import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; -import com.google.devtools.build.lib.rules.apple.AppleConfiguration; -import com.google.devtools.build.lib.rules.cpp.CppConfiguration; -import com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.BundlingRule; -import com.google.devtools.build.lib.util.FileType; - -/** - * Rule definition for {@code ios_test} rule in Bazel. - */ -public class IosTestRule implements RuleDefinition { - - @Override - public RuleClass build(RuleClass.Builder builder, final RuleDefinitionEnvironment env) { - final Label mcov = env.getToolsLabel("//tools/objc:mcov"); - return builder - .requiresConfigurationFragments( - ObjcConfiguration.class, - J2ObjcConfiguration.class, - AppleConfiguration.class, - CppConfiguration.class) - /* -

    -
  • name.ipa: the test bundle as an - .ipa file -
- */ - .setImplicitOutputsFunction(ReleaseBundlingSupport.IPA) - /* - The device against which to run the test. - */ - .add( - attr(IosTest.TARGET_DEVICE, LABEL) - .allowedFileTypes() - .allowedRuleClasses("ios_device") - .value(env.getToolsLabel("//tools/objc/sim_devices:default"))) - /* - Deprecated. Does not affect how the test is built. - */ - .add(attr(IosTest.IS_XCTEST_ATTR, BOOLEAN).value(true)) - /* - An ios_application target that contains the app bundle to test against with - XCTest. This attribute is only valid if xctest is true. - */ - .add( - attr(IosTest.XCTEST_APP_ATTR, LABEL) - .value(env.getLabel("//tools/objc:xctest_app")) - .allowedFileTypes() - .mandatoryProviders(XcTestAppProvider.SKYLARK_CONSTRUCTOR.id())) - .override( - attr(BundlingRule.INFOPLIST_ATTR, LABEL) - .value(env.getLabel("//tools/objc:xctest_infoplist")) - .allowedFileTypes(ObjcRuleClasses.PLIST_TYPE)) - /* - The device against how to run the test. If this attribute is defined, the test will run on - the lab device. Otherwise, the test will run on simulator. - */ - .add( - attr(IosTest.TEST_TARGET_DEVICE_ATTR, LABEL) - .allowedFileTypes() - .allowedRuleClasses("ios_lab_device")) - /* - Extra arguments to pass to the ios_test_target_device's binary. They should be - in the form KEY=VALUE or simply KEY (check your device's documentation for allowed - parameters). - */ - .add(attr(IosTest.DEVICE_ARG_ATTR, STRING_LIST)) - /* - Plugins to pass to the test runner. - */ - .add(attr(IosTest.PLUGINS_ATTR, LABEL_LIST).allowedFileTypes(FileType.of("_deploy.jar"))) - .add( - attr(IosTest.TEST_TEMPLATE_ATTR, LABEL) - .value(env.getToolsLabel("//tools/objc:ios_test.sh.bazel_template"))) - .add( - attr(IosTest.TEST_RUNNER_ATTR, LABEL) - .value(env.getToolsLabel("//tools/objc:testrunner"))) - .add( - attr(IosTest.MEMLEAKS_DEP_ATTR, LABEL) - .value(env.getToolsLabel("//tools/objc/memleaks:memleaks"))) - .add( - attr(IosTest.MEMLEAKS_PLUGIN_ATTR, LABEL) - .value(env.getToolsLabel("//tools/objc:memleaks_plugin"))) - .add( - attr(IosTest.OBJC_GCOV_ATTR, LABEL) - .cfg(HostTransition.INSTANCE) - .value(env.getToolsLabel("//tools/objc:gcov"))) - // TODO(b/65746853): provide a way to do this without passing the entire configuration - .add( - attr(IosTest.MCOV_TOOL_ATTR, LABEL) - .cfg(HostTransition.INSTANCE) - .value( - LateBoundDefault.fromTargetConfiguration( - BuildConfiguration.class, - mcov, - (rule, attributes, configuration) -> - configuration.isCodeCoverageEnabled() ? mcov : null))) - .cfg(AppleCrosstoolTransition.APPLE_CROSSTOOL_TRANSITION) - .build(); - } - - @Override - public Metadata getMetadata() { - return RuleDefinition.Metadata.builder() - .name("ios_test") - .type(RuleClassType.TEST) - .ancestors( - BaseRuleClasses.BaseRule.class, - BaseRuleClasses.TestBaseRule.class, - ObjcRuleClasses.ReleaseBundlingRule.class, - ObjcRuleClasses.LinkingRule.class, - ObjcRuleClasses.SimulatorRule.class) - .factoryClass(IosTest.class) - .build(); - } -} - -/* - -

This rule is deprecated. Please use the new Apple build rules -(https://github.com/bazelbuild/rules_apple) -to build Apple targets.

- -

This rule provides a way to build iOS unit tests written in the XCTest test framework -on both iOS simulator and real devices. -

- -*/ diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java index 1a30d4b889..328b212045 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java @@ -17,6 +17,7 @@ package com.google.devtools.build.lib.rules.objc; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.NESTED_BUNDLE; import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.BundlingRule.FAMILIES_ATTR; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.ConfiguredTarget; @@ -24,6 +25,7 @@ import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; 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.apple.AppleConfiguration; import com.google.devtools.build.lib.rules.apple.ApplePlatform.PlatformType; import com.google.devtools.build.lib.rules.apple.XcodeConfig; @@ -39,6 +41,14 @@ import java.util.List; */ public class ObjcBundleLibrary implements RuleConfiguredTargetFactory { + @VisibleForTesting + static final String INVALID_FAMILIES_ERROR = + "Expected one or two strings from the list 'iphone', 'ipad'"; + + @VisibleForTesting + static final String NO_ASSET_CATALOG_ERROR_FORMAT = + "a value was specified (%s), but this app does not have any asset catalogs"; + @Override public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException, RuleErrorException { @@ -93,7 +103,7 @@ public class ObjcBundleLibrary implements RuleConfiguredTargetFactory { } if (families.isEmpty()) { - ruleContext.attributeError(FAMILIES_ATTR, ReleaseBundling.INVALID_FAMILIES_ERROR); + ruleContext.attributeError(FAMILIES_ATTR, INVALID_FAMILIES_ERROR); } return new Bundling.Builder() 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 20f8757863..c43821c084 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 @@ -14,7 +14,6 @@ package com.google.devtools.build.lib.rules.objc; -import static com.google.devtools.build.lib.packages.Attribute.ANY_RULE; 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; @@ -40,9 +39,7 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.HostTransition; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSet; -import com.google.devtools.build.lib.packages.Attribute; import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault; -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.RuleClass; @@ -51,7 +48,6 @@ import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier; import com.google.devtools.build.lib.rules.apple.AppleConfiguration; import com.google.devtools.build.lib.rules.apple.ApplePlatform; -import com.google.devtools.build.lib.rules.apple.ApplePlatform.PlatformType; import com.google.devtools.build.lib.rules.apple.AppleToolchain; import com.google.devtools.build.lib.rules.apple.AppleToolchain.RequiresXcodeConfigRule; import com.google.devtools.build.lib.rules.apple.XcodeConfigProvider; @@ -1158,275 +1154,6 @@ public class ObjcRuleClasses { } } - /** - * Common attributes for {@code objc_*} rules that create a bundle meant for release (e.g. - * application or extension). - */ - public static class ReleaseBundlingRule implements RuleDefinition { - static final String APP_ICON_ATTR = "app_icon"; - static final String BUNDLE_ID_ATTR = "bundle_id"; - static final String DEFAULT_PROVISIONING_PROFILE_ATTR = ":default_provisioning_profile"; - static final String ENTITLEMENTS_ATTR = "entitlements"; - static final String EXTRA_ENTITLEMENTS_ATTR = ":extra_entitlements"; - static final String DEBUG_ENTITLEMENTS_ATTR = "$device_debug_entitlements"; - static final String LAUNCH_IMAGE_ATTR = "launch_image"; - static final String LAUNCH_STORYBOARD_ATTR = "launch_storyboard"; - static final String PROVISIONING_PROFILE_ATTR = "provisioning_profile"; - - @Override - public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { - return builder - /* - The entitlements file required for device builds of this application. - - See - the apple documentation - for more information. If absent, the default entitlements from the - provisioning profile will be used. -

- The following variables are substituted: $(CFBundleIdentifier) with the - bundle id and $(AppIdentifierPrefix) with the value of the - ApplicationIdentifierPrefix key from this target's provisioning profile (or - the default provisioning profile, if none is specified). -

- Bazel does not currently support adding entitlements to simulator builds. This - means that if you rely on behavior which must be specified in entitlements (like App - Groups) it will only work on a device. You can work around this by inlining the - entitlements into your binary. e.g. -


-            #if TARGET_OS_SIMULATOR
-            __asm(".section __TEXT,__entitlements");
-            __asm(".ascii \""
-            "<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\n"
-            "<!DOCTYPE plist PUBLIC \\\"-//Apple//DTD PLIST 1.0//EN\\\" "
-                "\\\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\\\">"
-             "<plist version=\\\"1.0\\\">"
-            "<dict>"
-            "<key>com.apple.security.application-groups</key>"
-            "<array>"
-            "<string>group.com.your.company</string>"
-            "</array>"
-            "</dict>"
-            "</plist>"
-            "\"
-            #endif
-          
- */ - .add(attr(ENTITLEMENTS_ATTR, LABEL).allowedFileTypes(ENTITLEMENTS_TYPE)) - .add( - attr(EXTRA_ENTITLEMENTS_ATTR, LABEL) - .singleArtifact() - .cfg(HostTransition.INSTANCE) - .value( - LateBoundDefault.fromTargetConfiguration( - ObjcConfiguration.class, - null, - (rule, attributes, objcConfig) -> objcConfig.getExtraEntitlements())) - .allowedFileTypes(ENTITLEMENTS_TYPE)) - .add( - attr(DEBUG_ENTITLEMENTS_ATTR, LABEL) - .singleArtifact() - .cfg(HostTransition.INSTANCE) - .value(env.getToolsLabel("//tools/objc:device_debug_entitlements.plist"))) - /* - The provisioning profile (.mobileprovision file) to use when bundling - the application. - - This is only used for non-simulator builds. - */ - .add( - attr(PROVISIONING_PROFILE_ATTR, LABEL) - .singleArtifact() - .allowedFileTypes(FileType.of(".mobileprovision"))) - // Will be used if provisioning_profile is null. - .add( - attr(DEFAULT_PROVISIONING_PROFILE_ATTR, LABEL) - .singleArtifact() - .allowedFileTypes(FileType.of(".mobileprovision")) - .value( - LateBoundDefault.fromTargetConfiguration( - AppleConfiguration.class, - null, - (rule, attributes, appleConfig) -> { - if (appleConfig.getMultiArchPlatform(PlatformType.IOS) - != ApplePlatform.IOS_DEVICE) { - return null; - } - if (attributes.isAttributeValueExplicitlySpecified( - PROVISIONING_PROFILE_ATTR)) { - return null; - } - return appleConfig.getDefaultProvisioningProfileLabel(); - }))) - /* - The name of the application icon. - - The icon should be in one of the asset catalogs of this target or - a (transitive) dependency. In a new project, this is initialized - to "AppIcon" by Xcode. -

- If the application icon is not in an asset catalog, do not use this - attribute. Instead, add a CFBundleIcons entry to the Info.plist file. - */ - .add(attr(APP_ICON_ATTR, STRING)) - /* - The name of the launch image. - - The icon should be in one of the asset catalogs of this target or - a (transitive) dependency. In a new project, this is initialized - to "LaunchImage" by Xcode. -

- If the launch image is not in an asset catalog, do not use this - attribute. Instead, add an appropriately-named image resource to the - bundle. -

- */ - .add(attr(LAUNCH_IMAGE_ATTR, STRING)) - /* - The location of the launch storyboard (.xib or .storyboard). - - The provided storyboard will be compiled to the appropriate format - (.nib or .storyboardc respectively) and placed in the root of the - final package. If the storyboard's immediate containing directory is - named *.lproj (e.g. en.lproj, Base.lproj), it will be placed under a - directory of that name in the final bundle. This allows for - localizable UI. -

- The generated storyboard is registered in the final bundle's - Info.plist under the key - UILaunchStoryboardName. -

- */ - .add( - attr(LAUNCH_STORYBOARD_ATTR, LABEL) - .direct_compile_time_input() - .allowedFileTypes(FileTypeSet.of(XIB_TYPE, STORYBOARD_TYPE))) - /* - The bundle ID (reverse-DNS path followed by app name) of the binary. - - If specified, it will override the bundle ID specified in the associated plist file. If - no bundle ID is specified on either this attribute or in the plist file, a junk value - will be used. - */ - .add( - attr(BUNDLE_ID_ATTR, STRING) - .value( - new Attribute.ComputedDefault() { - @Override - public Object getDefault(AttributeMap rule) { - // For tests and similar, we don't want to force people to explicitly - // specify throw-away data. - return "example." + rule.getName(); - } - })) - .build(); - } - @Override - public Metadata getMetadata() { - return RuleDefinition.Metadata.builder() - .name("$objc_release_bundling_rule") - .type(RuleClassType.ABSTRACT) - .ancestors(BundlingRule.class, ReleaseBundlingToolsRule.class) - .build(); - } - } - - /** - * Common attributes for rules that require tools to create a bundle meant for - * release (e.g. application or extension). Specifically, for rules which use the - * {@link ReleaseBundlingSupport} helper class. - */ - public static class ReleaseBundlingToolsRule implements RuleDefinition { - @Override - public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { - return builder - .add( - attr("$bundlemerge", LABEL) - .cfg(HostTransition.INSTANCE) - .exec() - .value(env.getToolsLabel("//tools/objc:bundlemerge"))) - .add( - attr("$environment_plist", LABEL) - .cfg(HostTransition.INSTANCE) - .exec() - .value(env.getToolsLabel("//tools/objc:environment_plist"))) - .add( - attr("$swiftstdlibtoolwrapper", LABEL) - .cfg(HostTransition.INSTANCE) - .exec() - .value(env.getToolsLabel("//tools/objc:swiftstdlibtoolwrapper"))) - .build(); - } - @Override - public Metadata getMetadata() { - return RuleDefinition.Metadata.builder() - .name("$release_bundling_tools_rule") - .type(RuleClassType.ABSTRACT) - .build(); - } - } - - /** - * Common attributes for {@code objc_*} rules that create a signed IPA. - */ - public static class IpaRule implements RuleDefinition { - @Override - public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { - return builder - /* - A tool that edits this target's IPA output after it is assembled but before it is - (optionally) signed. -

- The tool is invoked with a single positional argument which represents the path to a - directory containing the unzipped contents of the IPA. The only entry in this directory - will be the Payload root directory of the IPA (for an ios_application) or - the PlugIns root directory (for an ios_extension). Any changes made by the - tool must be made in this directory, whose contents will be (optionally) signed and then - zipped up as the final IPA after the tool terminates. -

- The tool's execution must be hermetic given these inputs to ensure that its result can be - safely cached. - */ - .add( - attr("ipa_post_processor", LABEL) - .allowedRuleClasses(ANY_RULE) - .allowedFileTypes(FileTypeSet.ANY_FILE) - .exec()) - .build(); - } - - @Override - public Metadata getMetadata() { - return RuleDefinition.Metadata.builder() - .name("$objc_ipa_rule") - .type(RuleClassType.ABSTRACT) - .build(); - } - } - - /** - * Common attributes for {@code objc_*} rules that use the iOS simulator. - */ - public static class SimulatorRule implements RuleDefinition { - static final String STD_REDIRECT_DYLIB_ATTR = "$std_redirect_dylib"; - - @Override - public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { - return builder - // Needed to run the binary in the simulator. - .add(attr(STD_REDIRECT_DYLIB_ATTR, LABEL).cfg(HostTransition.INSTANCE).exec() - .value(env.getToolsLabel("//tools/objc:StdRedirect.dylib"))) - .build(); - } - @Override - public Metadata getMetadata() { - return RuleDefinition.Metadata.builder() - .name("$objc_simulator_rule") - .type(RuleClassType.ABSTRACT) - .build(); - } - } - /** * Common attributes for {@code objc_*} rules that need to call xcrun. */ diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundling.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundling.java deleted file mode 100644 index 509661d421..0000000000 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundling.java +++ /dev/null @@ -1,395 +0,0 @@ -// 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.ObjcRuleClasses.BundlingRule.FAMILIES_ATTR; -import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.APP_ICON_ATTR; -import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.BUNDLE_ID_ATTR; -import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.DEFAULT_PROVISIONING_PROFILE_ATTR; -import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.LAUNCH_IMAGE_ATTR; -import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.LAUNCH_STORYBOARD_ATTR; -import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.PROVISIONING_PROFILE_ATTR; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableSet; -import com.google.devtools.build.lib.actions.Artifact; -import com.google.devtools.build.lib.analysis.RuleContext; -import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; -import com.google.devtools.build.lib.collect.nestedset.NestedSet; -import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; -import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; -import com.google.devtools.build.lib.rules.objc.TargetDeviceFamily.InvalidFamilyNameException; -import com.google.devtools.build.lib.rules.objc.TargetDeviceFamily.RepeatedFamilyNameException; -import com.google.devtools.build.lib.syntax.Type; -import java.util.List; - -/** - * Contains information regarding the creation of a released bundle such as an application or - * extension. The information which generally includes app icons, launch image, targeted devices and - * other data for potential signing is used to create a releasable bundle out of the bundle created - * using {@link Bundling} object. - * - * @deprecated The native bundling rules have been deprecated. This class will be removed in the - * future. - */ -@Deprecated -@Immutable -final class ReleaseBundling { - static final class Builder { - private Artifact ipaArtifact; - private String bundleId; - private String primaryBundleId; - private String fallbackBundleId; - private String appIcon; - private String launchImage; - private Artifact launchStoryboard; - private Artifact provisioningProfile; - private String provisioningProfileAttributeName; - private final NestedSetBuilder infoplistInputs = NestedSetBuilder.stableOrder(); - private Iterable infoPlistsFromRule; - private ImmutableSet families; - private IntermediateArtifacts intermediateArtifacts; - private String artifactPrefix; - private Artifact entitlements; - private Artifact extraEntitlements; - - public Builder setIpaArtifact(Artifact ipaArtifact) { - this.ipaArtifact = ipaArtifact; - return this; - } - - public Builder setBundleId(String bundleId) { - this.bundleId = bundleId; - return this; - } - - public Builder setPrimaryBundleId(String primaryId) { - this.primaryBundleId = primaryId; - return this; - } - - public Builder setFallbackBundleId(String fallbackId) { - this.fallbackBundleId = fallbackId; - return this; - } - - public Builder setAppIcon(String appIcon) { - this.appIcon = appIcon; - return this; - } - - public Builder setLaunchImage(String launchImage) { - this.launchImage = launchImage; - return this; - } - - public Builder setLaunchStoryboard(Artifact launchStoryboard) { - this.launchStoryboard = launchStoryboard; - return this; - } - - public Builder setProvisioningProfile(Artifact provisioningProfile) { - this.provisioningProfile = provisioningProfile; - return this; - } - - public Builder setProvisioningProfileAttributeName(String provisioningProfileAttributeName) { - this.provisioningProfileAttributeName = provisioningProfileAttributeName; - return this; - } - - public Builder addInfoplistInput(Artifact infoPlist) { - this.infoplistInputs.add(infoPlist); - return this; - } - - public Builder addInfoplistInputs(Iterable infoplists) { - this.infoplistInputs.addAll(infoplists); - return this; - } - - public Builder setInfoPlistsFromRule(Iterable infoPlistsFromRule) { - this.infoPlistsFromRule = infoPlistsFromRule; - return this; - } - - public Builder setIntermediateArtifacts(IntermediateArtifacts intermediateArtifacts) { - this.intermediateArtifacts = intermediateArtifacts; - return this; - } - - public Builder setTargetDeviceFamilies(ImmutableSet families) { - this.families = families; - return this; - } - - public Builder setArtifactPrefix(String artifactPrefix) { - this.artifactPrefix = artifactPrefix; - return this; - } - - public Builder setEntitlements(Artifact entitlements) { - this.entitlements = entitlements; - return this; - } - - public ReleaseBundling build() { - Preconditions.checkNotNull(intermediateArtifacts, "intermediateArtifacts"); - Preconditions.checkNotNull(families, FAMILIES_ATTR); - return new ReleaseBundling( - ipaArtifact, - bundleId, - primaryBundleId, - fallbackBundleId, - appIcon, - launchImage, - launchStoryboard, - provisioningProfile, - provisioningProfileAttributeName, - infoplistInputs.build(), - infoPlistsFromRule, - families, - intermediateArtifacts, - artifactPrefix, - entitlements, - extraEntitlements); - } - } - - /** - * Returns a {@link ReleaseBundling} object constructed using the information available in given - * context. - */ - public static ReleaseBundling releaseBundling(RuleContext ruleContext) - throws InterruptedException { - Preconditions.checkState(!Strings.isNullOrEmpty( - ruleContext.attributes().get(BUNDLE_ID_ATTR, Type.STRING)), - "requires a bundle_id value"); - String primaryBundleId = null; - String fallbackBundleId = null; - Artifact provisioningProfile; - - if (ruleContext.attributes().isAttributeValueExplicitlySpecified(BUNDLE_ID_ATTR)) { - primaryBundleId = ruleContext.attributes().get(BUNDLE_ID_ATTR, Type.STRING); - } else { - fallbackBundleId = ruleContext.attributes().get(BUNDLE_ID_ATTR, Type.STRING); - } - - Artifact explicitProvisioningProfile = - ruleContext.getPrerequisiteArtifact(PROVISIONING_PROFILE_ATTR, Mode.TARGET); - if (explicitProvisioningProfile != null) { - provisioningProfile = explicitProvisioningProfile; - } else { - provisioningProfile = ruleContext.getPrerequisiteArtifact(DEFAULT_PROVISIONING_PROFILE_ATTR, - Mode.TARGET); - } - - ImmutableSet families = null; - List rawFamilies = ruleContext.attributes().get(FAMILIES_ATTR, Type.STRING_LIST); - try { - families = ImmutableSet.copyOf(TargetDeviceFamily.fromNamesInRule(rawFamilies)); - } catch (InvalidFamilyNameException | RepeatedFamilyNameException e) { - families = ImmutableSet.of(); - } - - if (families.isEmpty()) { - ruleContext.attributeError(FAMILIES_ATTR, INVALID_FAMILIES_ERROR); - } - - return new ReleaseBundling.Builder() - .setIpaArtifact(ruleContext.getImplicitOutputArtifact(ReleaseBundlingSupport.IPA)) - .setBundleId(ruleContext.attributes().get(BUNDLE_ID_ATTR, Type.STRING)) - .setPrimaryBundleId(primaryBundleId) - .setFallbackBundleId(fallbackBundleId) - .setAppIcon(Strings.emptyToNull(ruleContext.attributes().get(APP_ICON_ATTR, Type.STRING))) - .setLaunchImage(Strings.emptyToNull( - ruleContext.attributes().get(LAUNCH_IMAGE_ATTR, Type.STRING))) - .setLaunchStoryboard( - ruleContext.getPrerequisiteArtifact(LAUNCH_STORYBOARD_ATTR, Mode.TARGET)) - .setProvisioningProfile(provisioningProfile) - .setProvisioningProfileAttributeName(PROVISIONING_PROFILE_ATTR) - .setTargetDeviceFamilies(families) - .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) - .setEntitlements(ruleContext.getPrerequisiteArtifact("entitlements", Mode.TARGET)) - .build(); - } - - @VisibleForTesting - static final String INVALID_FAMILIES_ERROR = - "Expected one or two strings from the list 'iphone', 'ipad'"; - private final Artifact ipaArtifact; - private final String bundleId; - private final String fallbackBundleId; - private final String primaryBundleId; - private final String appIcon; - private final String launchImage; - private final Artifact launchStoryboard; - private final Artifact provisioningProfile; - private final String provisioningProfileAttributeName; - private final NestedSet infoplistInputs; - private final ImmutableSet families; - private final IntermediateArtifacts intermediateArtifacts; - private final Iterable infoPlistsFromRule; - private final String artifactPrefix; - private final Artifact entitlements; - - private ReleaseBundling( - Artifact ipaArtifact, - String bundleId, - String primaryBundleId, - String fallbackBundleId, - String appIcon, - String launchImage, - Artifact launchStoryboard, - Artifact provisioningProfile, - String provisioningProfileAttributeName, - NestedSet infoplistInputs, - Iterable infoPlistsFromRule, - ImmutableSet families, - IntermediateArtifacts intermediateArtifacts, - String artifactPrefix, - Artifact entitlements, - Artifact extraEntitlements) { - this.ipaArtifact = Preconditions.checkNotNull(ipaArtifact); - this.bundleId = bundleId; - this.primaryBundleId = primaryBundleId; - this.fallbackBundleId = fallbackBundleId; - this.appIcon = appIcon; - this.launchImage = launchImage; - this.launchStoryboard = launchStoryboard; - this.provisioningProfile = provisioningProfile; - this.provisioningProfileAttributeName = - Preconditions.checkNotNull(provisioningProfileAttributeName); - this.infoplistInputs = Preconditions.checkNotNull(infoplistInputs); - this.infoPlistsFromRule = infoPlistsFromRule; - this.families = Preconditions.checkNotNull(families); - this.intermediateArtifacts = Preconditions.checkNotNull(intermediateArtifacts); - this.artifactPrefix = artifactPrefix; - this.entitlements = entitlements; - } - - /** - * Returns the {@link Artifact} containing the final ipa bundle. - */ - public Artifact getIpaArtifact() { - return ipaArtifact; - } - - /** - * Returns the identifier of this bundle. - */ - public String getBundleId() { - return bundleId; - } - - /** - * Returns primary bundle ID to use, can be null. - */ - public String getPrimaryBundleId() { - return primaryBundleId; - } - - /** - * Returns fallback bundle ID to use when primary isn't set. - */ - public String getFallbackBundleId() { - return fallbackBundleId; - } - - /** - * Returns the app icon name for this bundle, can be null. - */ - public String getAppIcon() { - return appIcon; - } - - /** - * Returns the launch image name for this bundle, can be null. - */ - public String getLaunchImage() { - return launchImage; - } - - /** - * Returns an {@link Artifact} containing launch storyboard for this bundle, can be null. - */ - public Artifact getLaunchStoryboard() { - return launchStoryboard; - } - - /** - * Returns an {@link Artifact} containing provisioning profile used to sign this bundle, - * can be null. - */ - public Artifact getProvisioningProfile() { - return provisioningProfile; - } - - /** - * Returns the list of plists to be merged to final bundle. - */ - public NestedSet getInfoplistInputs() { - return infoplistInputs; - } - - /** - * Returns the list of {@link TargetDeviceFamily} values this bundle is targeting. - * If empty, the default values specified by {@link FAMILIES_ATTR} will be used. - */ - public ImmutableSet getTargetDeviceFamilies() { - return families; - } - - /** - * Returns {@link IntermediateArtifacts} used to create this bundle. - */ - public IntermediateArtifacts getIntermediateArtifacts() { - return intermediateArtifacts; - } - - /** - * Returns the name of the attribute which is used to specifiy the provisioning profile. - */ - public String getProvisioningProfileAttrName() { - return provisioningProfileAttributeName; - } - - /** - * Adds any info plists specified in the given rule's {@code infoplists} attribute as inputs to - * this bundle's {@code Info.plist} (which is merged from any such added plists plus some - * additional information). - */ - public Iterable getInfoPlistsFromRule() { - return infoPlistsFromRule; - } - - /** - * Returns the prefix to be added to all generated artifact names, can be null. This is useful - * to disambiguate artifacts for multiple bundles created with different names withing same rule. - */ - public String getArtifactPrefix() { - return artifactPrefix; - } - - /** - * Returns an {@link Artifact} containing the entitlements used to sign this bundle for - * non-simulator builds; can be null. - */ - public Artifact getEntitlements() { - return entitlements; - } -} diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java deleted file mode 100644 index b73b8cbe4c..0000000000 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java +++ /dev/null @@ -1,1250 +0,0 @@ -// Copyright 2015 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.common.base.Preconditions.checkNotNull; -import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fromTemplates; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_SWIFT; -import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.APP_ICON_ATTR; -import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.DEBUG_ENTITLEMENTS_ATTR; -import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.EXTRA_ENTITLEMENTS_ATTR; - -import com.dd.plist.NSArray; -import com.dd.plist.NSDictionary; -import com.dd.plist.NSObject; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; -import com.google.devtools.build.lib.actions.Artifact; -import com.google.devtools.build.lib.analysis.BuildInfo; -import com.google.devtools.build.lib.analysis.FilesToRunProvider; -import com.google.devtools.build.lib.analysis.RuleContext; -import com.google.devtools.build.lib.analysis.Runfiles; -import com.google.devtools.build.lib.analysis.RunfilesSupport; -import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; -import com.google.devtools.build.lib.analysis.actions.BinaryFileWriteAction; -import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; -import com.google.devtools.build.lib.analysis.actions.FileWriteAction; -import com.google.devtools.build.lib.analysis.actions.SpawnAction; -import com.google.devtools.build.lib.analysis.actions.SymlinkAction; -import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction; -import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution; -import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; -import com.google.devtools.build.lib.collect.nestedset.NestedSet; -import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; -import com.google.devtools.build.lib.collect.nestedset.Order; -import com.google.devtools.build.lib.packages.BuildType; -import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; -import com.google.devtools.build.lib.rules.apple.AppleConfiguration; -import com.google.devtools.build.lib.rules.apple.ApplePlatform; -import com.google.devtools.build.lib.rules.apple.ApplePlatform.PlatformType; -import com.google.devtools.build.lib.rules.apple.DottedVersion; -import com.google.devtools.build.lib.rules.apple.XcodeConfig; -import com.google.devtools.build.lib.rules.apple.XcodeConfigProvider; -import com.google.devtools.build.lib.rules.objc.BundleSupport.ExtraActoolArgs; -import com.google.devtools.build.lib.rules.objc.Bundling.Builder; -import com.google.devtools.build.lib.shell.ShellUtils; -import java.util.List; -import java.util.Map.Entry; -import javax.annotation.Nullable; - -/** - * Support for released bundles, such as an application or extension. Such a bundle is generally - * composed of a top-level {@link BundleSupport bundle}, potentially signed, as well as some debug - * information, if {@link ObjcConfiguration#generateDsym() requested}. - * - *

Contains actions, validation logic and provider value generation. - * - *

Methods on this class can be called in any order without impacting the result. - * - * @deprecated The native bundling rules have been deprecated. This class will be removed in the - * future. - */ -@Deprecated -public final class ReleaseBundlingSupport { - - /** - * Template for the containing application folder. - */ - public static final SafeImplicitOutputsFunction IPA = fromTemplates("%{name}.ipa"); - - @VisibleForTesting - static final String NO_ASSET_CATALOG_ERROR_FORMAT = - "a value was specified (%s), but this app does not have any asset catalogs"; - @VisibleForTesting - static final String DEVICE_NO_PROVISIONING_PROFILE = - "Provisioning profile must be set for device build"; - - @VisibleForTesting - static final String PROVISIONING_PROFILE_BUNDLE_FILE = "embedded.mobileprovision"; - @VisibleForTesting - static final String APP_BUNDLE_DIR_FORMAT = "Payload/%s.app"; - @VisibleForTesting - static final String XCTEST_BUNDLE_DIR_FORMAT = "Payload/%s.xctest"; - @VisibleForTesting - static final String EXTENSION_BUNDLE_DIR_FORMAT = "PlugIns/%s.appex"; - @VisibleForTesting - static final String FRAMEWORK_BUNDLE_DIR_FORMAT = "Frameworks/%s.framework"; - - /** - * Command string for "sed" that tries to extract the application version number from a larger - * string. For example, from "foo_1.2.3_RC00" this would extract "1.2.3". This regex looks for - * versions of the format "x.y" or "x.y.z", which may be preceded and/or followed by other text, - * such as a project name or release candidate number. - * - *

This command also preserves double quotes around the string, if any. - */ - private static final String EXTRACT_VERSION_NUMBER_SED_COMMAND = - "s#\\(\"\\)\\{0,1\\}\\(.*_\\)\\{0,1\\}\\([0-9][0-9]*\\(\\.[0-9][0-9]*\\)\\{1,2\\}\\)" - + "\\(_[^\"]*\\)\\{0,1\\}\\(\"\\)\\{0,1\\}#\\1\\3\\6#"; - - private final Attributes attributes; - private final BundleSupport bundleSupport; - private final RuleContext ruleContext; - private final Bundling bundling; - private final ObjcProvider objcProvider; - private final LinkedBinary linkedBinary; - private final IntermediateArtifacts intermediateArtifacts; - private final ReleaseBundling releaseBundling; - private final ApplePlatform platform; - - /** - * Indicator as to whether this rule generates a binary directly or whether only dependencies - * should be considered. - */ - enum LinkedBinary { - /** - * This rule generates its own binary which should be included as well as dependency-generated - * binaries. - */ - LOCAL_AND_DEPENDENCIES, - - /** - * This rule does not generate its own binary, only consider binaries from dependencies. - */ - DEPENDENCIES_ONLY - } - - /** - * Creates a new release bundling support within the given rule context. - * - * @param ruleContext context for the application-generating rule - * @param objcProvider provider containing all dependencies' information as well as some of this - * rule's - * @param linkedBinary whether to look for a linked binary from this rule and dependencies or just - * the latter - * @param bundleDirFormat format string representing the bundle's directory with a single - * placeholder for the target name (e.g. {@code "Payload/%s.app"}) - * @param bundleName name of the bundle, used with bundleDirFormat - * @param bundleMinimumOsVersion the minimum OS version this bundle's plist should be generated - * for (not the minimum OS version its binary is compiled with, that needs to be set - * through the configuration) - * @param releaseBundling the {@link ReleaseBundling} containing information for creating a - * releaseable bundle. - * @param platform the platform that bundles will be created for using this support - */ - ReleaseBundlingSupport( - RuleContext ruleContext, - ObjcProvider objcProvider, - LinkedBinary linkedBinary, - String bundleDirFormat, - String bundleName, - DottedVersion bundleMinimumOsVersion, - ReleaseBundling releaseBundling, - ApplePlatform platform) { - this.platform = platform; - this.linkedBinary = linkedBinary; - this.attributes = new Attributes(ruleContext); - this.ruleContext = ruleContext; - this.objcProvider = objcProvider; - this.releaseBundling = releaseBundling; - this.intermediateArtifacts = releaseBundling.getIntermediateArtifacts(); - this.bundling = bundling(ruleContext, objcProvider, bundleDirFormat, bundleName, - bundleMinimumOsVersion); - // TODO(cparsons): Take the rule configuration as a param instead of inferring. - bundleSupport = new BundleSupport(ruleContext, - ruleContext.getFragment(AppleConfiguration.class), platform, - bundling, extraActoolArgs()); - } - - /** - * Creates a new application support within the given rule context. - * - * @param ruleContext context for the application-generating rule - * @param objcProvider provider containing all dependencies' information as well as some of this - * rule's - * @param linkedBinary whether to look for a linked binary from this rule and dependencies or just - * the latter - * @param bundleDirFormat format string representing the bundle's directory with a single - * placeholder for the target name (e.g. {@code "Payload/%s.app"}) - * @param bundleName name of the bundle, used with bundleDirFormat - * @param platform the platform that bundles will be created for using this support - */ - ReleaseBundlingSupport( - RuleContext ruleContext, - ObjcProvider objcProvider, - LinkedBinary linkedBinary, - String bundleDirFormat, - String bundleName, - DottedVersion bundleMinimumOsVersion, - ApplePlatform platform) - throws InterruptedException { - this( - ruleContext, - objcProvider, - linkedBinary, - bundleDirFormat, - bundleName, - bundleMinimumOsVersion, - ReleaseBundling.releaseBundling(ruleContext), - platform); - } - - /** - * Creates a new application support within the given rule context. - * - *

{@code bundleName} defaults to label name - * - * @param ruleContext context for the application-generating rule - * @param objcProvider provider containing all dependencies' information as well as some of this - * rule's - * @param linkedBinary whether to look for a linked binary from this rule and dependencies or just - * the latter - * @param bundleDirFormat format string representing the bundle's directory with a single - * placeholder for the target name (e.g. {@code "Payload/%s.app"}) - * @param bundleMinimumOsVersion the minimum OS version this bundle's plist should be generated - * for (not the minimum OS version its binary is compiled with, that needs to be set - * through the configuration) - * @param platform the platform that bundles will be created for using this support - * @throws InterruptedException - */ - ReleaseBundlingSupport( - RuleContext ruleContext, - ObjcProvider objcProvider, - LinkedBinary linkedBinary, - String bundleDirFormat, - DottedVersion bundleMinimumOsVersion, - ApplePlatform platform) - throws InterruptedException { - this(ruleContext, objcProvider, linkedBinary, bundleDirFormat, ruleContext.getLabel().getName(), - bundleMinimumOsVersion, platform); - } - - /** - * Validates application-related attributes set on this rule and registers any errors with the - * rule context. - * - * @return this application support - */ - ReleaseBundlingSupport validateAttributes() { - // No asset catalogs. That means you cannot specify app_icon or - // launch_image attributes, since they must not exist. However, we don't - // run actool in this case, which means it does not do validity checks, - // and we MUST raise our own error somehow... - if (!objcProvider.hasAssetCatalogs()) { - if (releaseBundling.getAppIcon() != null) { - ruleContext.attributeError(APP_ICON_ATTR, - String.format(NO_ASSET_CATALOG_ERROR_FORMAT, releaseBundling.getAppIcon())); - } - if (releaseBundling.getLaunchImage() != null) { - ruleContext.attributeError("launch_image", - String.format(NO_ASSET_CATALOG_ERROR_FORMAT, releaseBundling.getLaunchImage())); - } - } - - if (releaseBundling.getProvisioningProfile() == null && platform.isDevice()) { - ruleContext.attributeError(releaseBundling.getProvisioningProfileAttrName(), - DEVICE_NO_PROVISIONING_PROFILE); - } - - return this; - } - - /** - * Validates that resources defined in this rule and its dependencies and written to this bundle - * are legal. - * - * @return this release bundling support - */ - ReleaseBundlingSupport validateResources() { - bundleSupport - .validatePlatform() - .validateResources(objcProvider); - return this; - } - - /** - * Registers actions required to build an application. This includes any - * {@link BundleSupport#registerActions(ObjcProvider) bundle} and bundle merge actions, signing - * this application if appropriate and combining several single-architecture binaries into one - * multi-architecture binary. - * - * @param dsymOutputType the file type of the dSYM bundle to be generated - * - * @return this application support - */ - ReleaseBundlingSupport registerActions(DsymOutputType dsymOutputType) - throws InterruptedException { - bundleSupport.registerActions(objcProvider); - - Artifact combinedArchBinary = prepareCombinedArchitecturesArtifact(); - registerCopyDsymFilesAction(dsymOutputType); - registerCopyDsymPlistAction(dsymOutputType); - registerCopyLinkmapFilesAction(); - registerSwiftStdlibActionsIfNecessary(combinedArchBinary); - registerSwiftSupportActionsIfNecessary(combinedArchBinary); - - registerEmbedLabelPlistAction(); - registerEnvironmentPlistAction(); - registerAutomaticPlistAction(); - - if (releaseBundling.getLaunchStoryboard() != null) { - registerLaunchStoryboardPlistAction(); - } - - registerBundleMergeActions(); - registerPostProcessAndSigningActions(); - - return this; - } - - private void registerEmbedLabelPlistAction() throws InterruptedException { - Artifact buildInfo = Iterables.getOnlyElement( - ruleContext.getBuildInfo(ObjcBuildInfoFactory.KEY)); - String generatedVersionPlistPath = getGeneratedVersionPlist().getShellEscapedExecPathString(); - String shellCommand = "VERSION=\"$(" - + "grep \"^" + BuildInfo.BUILD_EMBED_LABEL + "\" " - + buildInfo.getShellEscapedExecPathString() - + " | cut -d' ' -f2- | sed -e '" + EXTRACT_VERSION_NUMBER_SED_COMMAND + "' | " - + "sed -e 's#\"#\\\"#g')\" && " - + "cat >" + generatedVersionPlistPath + " <\n" - + "\n" - + "\n" - + "\n" - + "EOF\n" - - + "if [[ -n \"${VERSION}\" ]]; then\n" - + " for KEY in CFBundleVersion CFBundleShortVersionString; do\n" - + " echo \" ${KEY}\n\" >> " - + generatedVersionPlistPath + "\n" - + " echo \" ${VERSION}\n\" >> " - + generatedVersionPlistPath + "\n" - + " done\n" - + "fi\n" - - + "cat >>" + generatedVersionPlistPath + " <\n" - + "\n" - + "EOF\n"; - ruleContext.registerAction(new SpawnAction.Builder() - .setMnemonic("ObjcVersionPlist") - .setShellCommand(shellCommand) - .addInput(buildInfo) - .addOutput(getGeneratedVersionPlist()) - .build(ruleContext)); - } - - private void registerLaunchStoryboardPlistAction() { - String launchStoryboard = releaseBundling.getLaunchStoryboard().getFilename(); - String launchStoryboardName = launchStoryboard.substring(0, launchStoryboard.lastIndexOf('.')); - NSDictionary result = new NSDictionary(); - result.put("UILaunchStoryboardName", launchStoryboardName); - String contents = result.toGnuStepASCIIPropertyList(); - ruleContext.registerAction( - FileWriteAction.create(ruleContext, getLaunchStoryboardPlist(), contents, false)); - } - - private void registerEnvironmentPlistAction() { - // Generates a .plist that contains environment values (such as the SDK used to build, the Xcode - // version, etc), which are parsed from various .plist files of the OS, namely Xcodes' and - // Platforms' plists. - // The resulting file is meant to be merged with the final bundle. - String platformWithVersion = - String.format( - "%s%s", - platform.getLowerCaseNameInPlist(), - XcodeConfig.getSdkVersionForPlatform(ruleContext, platform)); - ruleContext.registerAction( - ObjcRuleClasses.spawnAppleEnvActionBuilder( - XcodeConfigProvider.fromRuleContext(ruleContext), platform) - .setMnemonic("EnvironmentPlist") - .setExecutable(attributes.environmentPlist()) - .addOutput(getGeneratedEnvironmentPlist()) - .addCommandLine( - CustomCommandLine.builder() - .add("--platform", platformWithVersion) - .addExecPath("--output", getGeneratedEnvironmentPlist()) - .build()) - .build(ruleContext)); - } - - private void registerAutomaticPlistAction() { - ruleContext.registerAction( - FileWriteAction.create( - ruleContext, - getGeneratedAutomaticPlist(), - automaticEntries().toGnuStepASCIIPropertyList(), - /*makeExecutable=*/ false)); - } - - /** - * Returns a map containing entries that should be added to the merged plist. These are usually - * generated by Xcode automatically during the build process. - */ - private NSDictionary automaticEntries() { - List uiDeviceFamily = - TargetDeviceFamily.UI_DEVICE_FAMILY_VALUES.get(bundleSupport.targetDeviceFamilies()); - NSDictionary result = new NSDictionary(); - - if (uiDeviceFamily != null) { - result.put("UIDeviceFamily", uiDeviceFamily.toArray()); - } - result.put("DTPlatformName", platform.getLowerCaseNameInPlist()); - result.put( - "DTSDKName", - platform.getLowerCaseNameInPlist() - + XcodeConfig.getSdkVersionForPlatform(ruleContext, platform)); - result.put("CFBundleSupportedPlatforms", new NSArray(NSObject.wrap(platform.getNameInPlist()))); - result.put("MinimumOSVersion", bundling.getMinimumOsVersion().toString()); - - return result; - } - - /** - * Registers all actions necessary to create a processed and signed IPA from the initial merged - * IPA. - * - *

Includes user-provided actions to process IPA contents (via {@code ipa_post_processor}), - * and signing actions if the IPA is being built for device architectures. If signing is necessary - * also includes entitlements generation and processing actions. - * - *

Note that multiple "actions" on the IPA contents may be run in a single blaze action to - * avoid excessive zipping/unzipping of IPA contents. - */ - private void registerPostProcessAndSigningActions() { - Artifact processedIpa = releaseBundling.getIpaArtifact(); - Artifact unprocessedIpa = intermediateArtifacts.unprocessedIpa(); - - NestedSetBuilder inputs = - NestedSetBuilder.stableOrder().add(unprocessedIpa); - - String actionCommandLine = - "set -e && " - + "t=$(mktemp -d \"${TMPDIR:-/tmp}/signing_intermediate.XXXXXX\") && " - + "trap \"rm -rf ${t}\" EXIT && " - // Get an absolute path since we need to cd into the temp directory for zip. - + "signed_ipa=${PWD}/" - + processedIpa.getShellEscapedExecPathString() - + " && " - + "/usr/bin/unzip -qq " - + unprocessedIpa.getShellEscapedExecPathString() - + " -d ${t} && "; - - FilesToRunProvider processor = attributes.ipaPostProcessor(); - if (processor != null) { - actionCommandLine += processor.getExecutable().getShellEscapedExecPathString() + " ${t} && "; - } - - if (platform.isDevice()) { - actionCommandLine += deviceSigningCommandLine(); - - registerEntitlementsActions(); - inputs.add(releaseBundling.getProvisioningProfile()) - .add(intermediateArtifacts.entitlements()); - } else { - actionCommandLine += simulatorSigningCommandLine(); - } - - actionCommandLine += "cd ${t} && /usr/bin/zip -q -r \"${signed_ipa}\" ."; - - SpawnAction.Builder processAction = - ObjcRuleClasses.spawnBashOnDarwinActionBuilder(actionCommandLine) - .setEnvironment( - ObjcRuleClasses.appleToolchainEnvironment( - XcodeConfigProvider.fromRuleContext(ruleContext), platform)) - .setMnemonic("ObjcProcessIpa") - .setProgressMessage("Processing iOS IPA: %s", ruleContext.getLabel()) - .disableSandboxing() - .addTransitiveInputs(inputs.build()) - .addOutput(processedIpa); - - if (processor != null) { - processAction.addTool(processor); - } - - ruleContext.registerAction(processAction.build(ruleContext)); - } - - private String deviceSigningCommandLine() { - StringBuilder codesignCommandLineBuilder = new StringBuilder(); - for (String dir : getDirsToSign()) { - codesignCommandLineBuilder.append(deviceCodesignCommand("${t}/" + dir)).append(" && "); - } - return codesignCommandLineBuilder.toString(); - } - - private String simulatorSigningCommandLine() { - StringBuilder codesignCommandLineBuilder = new StringBuilder(); - for (String dir : getDirsToSign()) { - codesignCommandLineBuilder - .append("/usr/bin/codesign --force --sign \"-\" ${t}/") - .append(dir) - .append(" && "); - } - return codesignCommandLineBuilder.toString(); - } - - private ImmutableList getDirsToSign() { - // The order here is important. The innermost code must signed first. - ImmutableList.Builder dirsToSign = new ImmutableList.Builder<>(); - String bundleDir = ShellUtils.shellEscape(bundling.getBundleDir()); - - // Explicitly sign the frameworks (raw .dylib files and .framework directories in Frameworks/). - // Unfortunately the --deep option on codesign doesn't do this automatically. - if (objcProvider.is(USES_SWIFT) - || !objcProvider.get(ObjcProvider.DYNAMIC_FRAMEWORK_FILE).isEmpty()) { - dirsToSign.add(bundleDir + "/Frameworks/*"); - } - dirsToSign.add(bundleDir); - - return dirsToSign.build(); - } - - /** - * Creates entitlement actions such that an entitlements file is generated in - * {@link IntermediateArtifacts#entitlements()} which can be used for signing in this bundle. - * - *

Entitlements are generated based on a plist-format entitlements file passed to this bundle's - * {@code entitlements} attribute or, if that is not set, entitlements extracted from the provided - * mobile provisioning profile. The team prefix is extracted from the provisioning profile and - * the following substitutions performed (assuming the prefix extracted was {@code PREFIX}): - *

    - *
  1. "PREFIX.*" -> "PREFIX.BUNDLE_ID" (where BUNDLE_ID is this bundle's id) - *
  2. "$(AppIdentifierPrefix)" -> "PREFIX." - *
  3. "$(CFBundleIdentifier)" -> "BUNDLE_ID" (where BUNDLE_ID is this bundle's id) - *
- * - *

Finally, if an entitlements file was provided via {@code --extra_entitlements} it is merged - * into the substituted entitlements. - */ - private void registerEntitlementsActions() { - Artifact teamPrefixFile = - intermediateArtifacts.appendExtensionForEntitlementArtifact(".team_prefix_file"); - registerExtractTeamPrefixAction(teamPrefixFile); - - Artifact entitlementsNeedingSubstitution = releaseBundling.getEntitlements(); - if (entitlementsNeedingSubstitution == null) { - entitlementsNeedingSubstitution = - intermediateArtifacts.appendExtensionForEntitlementArtifact( - ".entitlements_with_variables"); - registerExtractEntitlementsAction(entitlementsNeedingSubstitution); - } - - Artifact substitutedEntitlements = intermediateArtifacts.entitlements(); - if (attributes.extraEntitlements() != null || includeDebugEntitlements()) { - substitutedEntitlements = - intermediateArtifacts.appendExtensionForEntitlementArtifact(".substituted"); - - NestedSetBuilder entitlements = - NestedSetBuilder.stableOrder().add(substitutedEntitlements); - if (attributes.extraEntitlements() != null) { - entitlements.add(attributes.extraEntitlements()); - } - if (includeDebugEntitlements()) { - entitlements.add(attributes.deviceDebugEntitlements()); - } - - registerMergeEntitlementsAction(entitlements.build()); - } - - registerEntitlementsVariableSubstitutionAction( - entitlementsNeedingSubstitution, teamPrefixFile, substitutedEntitlements); - } - - private boolean includeDebugEntitlements() { - return attributes.deviceDebugEntitlements() != null - && ObjcRuleClasses.objcConfiguration(ruleContext).useDeviceDebugEntitlements(); - } - - private void registerMergeEntitlementsAction(NestedSet entitlements) { - PlMergeControlBytes controlBytes = - PlMergeControlBytes.fromPlists( - entitlements, - intermediateArtifacts.entitlements(), - PlMergeControlBytes.OutputFormat.XML); - - Artifact plMergeControlArtifact = ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, - artifactName(".merge-entitlements-control")); - - ruleContext.registerAction( - new BinaryFileWriteAction( - ruleContext.getActionOwner(), - plMergeControlArtifact, - controlBytes, - /*makeExecutable=*/ false)); - - ruleContext.registerAction( - new SpawnAction.Builder() - .setMnemonic("MergeEntitlementsFiles") - .setExecutable(attributes.plmerge()) - .addTransitiveInputs(entitlements) - .addOutput(intermediateArtifacts.entitlements()) - .addInput(plMergeControlArtifact) - .addCommandLine( - CustomCommandLine.builder() - .addExecPath("--control", plMergeControlArtifact) - .build()) - .build(ruleContext)); - } - - /** - * Adds any files to the given nested set builder that should be built if this application is the - * top level target in a blaze invocation. - * - * @param filesToBuild a collection of files to be built, where new artifacts to be built are - * going to be placed - * @param dsymOutputType the file type of the dSYM bundle to be built, or absent if no - * dSYM should be built for this bundle. A dSYM bundle will only be created if both this - * is present and the configuration values dictate dSYM is enabled - * - * @return this application support - */ - ReleaseBundlingSupport addFilesToBuild( - NestedSetBuilder filesToBuild, Optional dsymOutputType) { - NestedSetBuilder debugSymbolBuilder = NestedSetBuilder.stableOrder(); - - for (Artifact linkmapFile : getLinkmapFiles().values()) { - filesToBuild.add(linkmapFile); - } - - if (ObjcRuleClasses.objcConfiguration(ruleContext).generateDsym() - && dsymOutputType.isPresent()) { - filesToBuild.addAll(getDsymFiles(dsymOutputType.get()).values()); - - // TODO(bazel-team): Remove the 'if' when the objc_binary rule does not generate a bundle any - // more. The reason this 'if' is here is because the plist is obtained from the ObjcProvider. - // Since objc_binary is the rule that adds this file to the provider, and not before, when - // running this the provider does not have the plist yet. This gets called again when running - // the *_application targets, and since they depend on objc_binaries, the provider has the - // files configured. When objc_binary stops bundling ipas as output, the bundling methods will - // only get called by *_application rules, with the plist configured in the provider. - Artifact cpuPlist = getAnyCpuSpecificDsymPlist(); - if (cpuPlist != null) { - filesToBuild.add(intermediateArtifacts.dsymPlist(dsymOutputType.get())); - } - - if (linkedBinary == LinkedBinary.LOCAL_AND_DEPENDENCIES) { - debugSymbolBuilder - .add(intermediateArtifacts.dsymPlist(dsymOutputType.get())) - .add(intermediateArtifacts.dsymSymbol(dsymOutputType.get())); - } - } - - filesToBuild - .add(releaseBundling.getIpaArtifact()) - .addTransitive(debugSymbolBuilder.build()) - .addTransitive(objcProvider.get(ObjcProvider.EXPORTED_DEBUG_ARTIFACTS)); - - return this; - } - - /** - * Adds dSYM artifacts (plist, arch-speficic binaries) to the {@link ObjcProvider} for export. - */ - public void addExportedDebugArtifacts( - ObjcProvider.Builder objcBuilder, DsymOutputType dsymOutputType) { - if (ObjcRuleClasses.objcConfiguration(ruleContext).generateDsym()) { - objcBuilder - .addAll(ObjcProvider.EXPORTED_DEBUG_ARTIFACTS, getDsymFiles(dsymOutputType).values()) - .add( - ObjcProvider.EXPORTED_DEBUG_ARTIFACTS, - intermediateArtifacts.dsymPlist(dsymOutputType)); - } - } - - /** - * Registers an action to generate a runner script based on a template. - */ - ReleaseBundlingSupport registerGenerateRunnerScriptAction(Artifact runnerScript, - Artifact ipaInput) { - ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); - String escapedSimDevice = ShellUtils.shellEscape(objcConfiguration.getIosSimulatorDevice()); - String escapedSdkVersion = - ShellUtils.shellEscape(objcConfiguration.getIosSimulatorVersion().toString()); - ImmutableList substitutions = ImmutableList.of( - Substitution.of("%app_name%", ruleContext.getLabel().getName()), - Substitution.of("%ipa_file%", ipaInput.getRunfilesPathString()), - Substitution.of("%sim_device%", escapedSimDevice), - Substitution.of("%sdk_version%", escapedSdkVersion), - Substitution.of("%std_redirect_dylib_path%", - attributes.stdRedirectDylib().getRunfilesPathString())); - - ruleContext.registerAction( - new TemplateExpansionAction(ruleContext.getActionOwner(), attributes.runnerScriptTemplate(), - runnerScript, substitutions, true)); - return this; - } - - /** - * Returns a {@link RunfilesSupport} that uses the provided runner script as the executable. - */ - RunfilesSupport runfilesSupport(Artifact runnerScript) { - Runfiles runfiles = new Runfiles.Builder( - ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles()) - .addArtifact(releaseBundling.getIpaArtifact()) - .addArtifact(runnerScript) - .addArtifact(attributes.stdRedirectDylib()) - .build(); - return RunfilesSupport.withExecutable(ruleContext, runfiles, runnerScript); - } - - private ExtraActoolArgs extraActoolArgs() { - ImmutableList.Builder extraArgs = ImmutableList.builder(); - if (releaseBundling.getAppIcon() != null) { - extraArgs.add("--app-icon", releaseBundling.getAppIcon()); - } - if (releaseBundling.getLaunchImage() != null) { - extraArgs.add("--launch-image", releaseBundling.getLaunchImage()); - } - return new ExtraActoolArgs(extraArgs.build()); - } - - private Bundling bundling( - RuleContext ruleContext, - ObjcProvider objcProvider, - String bundleDirFormat, - String bundleName, - DottedVersion minimumOsVersion) { - ImmutableList extraBundleFiles; - AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class); - if (platform.isDevice()) { - extraBundleFiles = ImmutableList.of(new BundleableFile( - releaseBundling.getProvisioningProfile(), PROVISIONING_PROFILE_BUNDLE_FILE)); - } else { - extraBundleFiles = ImmutableList.of(); - } - - Bundling.Builder bundling = - new Builder() - .setName(bundleName) - .setExecutableName(bundleName) - // Architecture that determines which nested bundles are kept. - .setArchitecture(appleConfiguration.getDependencySingleArchitecture()) - .setBundleDirFormat(bundleDirFormat) - .addExtraBundleFiles(extraBundleFiles) - .setObjcProvider(objcProvider) - .setIntermediateArtifacts(intermediateArtifacts) - .setPrimaryBundleId(releaseBundling.getPrimaryBundleId()) - .setFallbackBundleId(releaseBundling.getFallbackBundleId()) - .setMinimumOsVersion(minimumOsVersion) - .setArtifactPrefix(releaseBundling.getArtifactPrefix()) - .setTargetDeviceFamilies(releaseBundling.getTargetDeviceFamilies()); - - // Add plists from rule first. - if (releaseBundling.getInfoPlistsFromRule() != null) { - bundling.addInfoplistInputs(releaseBundling.getInfoPlistsFromRule()); - } else { - bundling.addInfoplistInputFromRule(ruleContext); - } - - // Add generated plists next so that generated values can override the default values in the - // plists from rule. - bundling.setAutomaticEntriesInfoplistInput(getGeneratedAutomaticPlist()) - .addInfoplistInput(getGeneratedVersionPlist()) - .addInfoplistInput(getGeneratedEnvironmentPlist()) - .addInfoplistInputs(releaseBundling.getInfoplistInputs()); - - if (releaseBundling.getLaunchStoryboard() != null) { - bundling.addInfoplistInput(getLaunchStoryboardPlist()); - } - - return bundling.build(); - } - - private Artifact prepareCombinedArchitecturesArtifact() { - Artifact dependentMultiArchBinary = attributes.dependentMultiArchBinary(); - if (dependentMultiArchBinary != null) { - return dependentMultiArchBinary; - } - - Artifact resultingLinkedBinary = intermediateArtifacts.combinedArchitectureBinary(); - - new LipoSupport(ruleContext).registerCombineArchitecturesAction(linkedBinaries(), - resultingLinkedBinary, platform); - return resultingLinkedBinary; - } - - private NestedSet linkedBinaries() { - NestedSetBuilder linkedBinariesBuilder = NestedSetBuilder.stableOrder() - .addTransitive(attributes.dependentLinkedBinaries()); - if (linkedBinary == LinkedBinary.LOCAL_AND_DEPENDENCIES) { - linkedBinariesBuilder.add(intermediateArtifacts.strippedSingleArchitectureBinary()); - } - return linkedBinariesBuilder.build(); - } - - private void registerBundleMergeActions() { - Artifact bundleMergeControlArtifact = ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, - artifactName(".ipa-control")); - - BundleMergeControlBytes controlBytes = - new BundleMergeControlBytes( - bundling, - intermediateArtifacts.unprocessedIpa(), - XcodeConfig.getSdkVersionForPlatform(ruleContext, ApplePlatform.IOS_DEVICE), - ruleContext.getFragment(AppleConfiguration.class) - .getMultiArchPlatform(PlatformType.IOS)); - - ruleContext.registerAction( - new BinaryFileWriteAction( - ruleContext.getActionOwner(), bundleMergeControlArtifact, controlBytes, - /*makeExecutable=*/false)); - - ruleContext.registerAction( - new SpawnAction.Builder() - .setMnemonic("IosBundle") - .setProgressMessage("Bundling iOS application: %s", ruleContext.getLabel()) - .setExecutable(attributes.bundleMergeExecutable()) - .addInput(bundleMergeControlArtifact) - .addTransitiveInputs(bundling.getBundleContentArtifacts()) - .addOutput(intermediateArtifacts.unprocessedIpa()) - .addCommandLine( - CustomCommandLine.builder().addExecPath(bundleMergeControlArtifact).build()) - .build(ruleContext)); - } - - private void registerCopyLinkmapFilesAction() { - for (Entry linkmapFile : getLinkmapFiles().entrySet()) { - ruleContext.registerAction( - new SymlinkAction(ruleContext.getActionOwner(), linkmapFile.getKey(), - linkmapFile.getValue(), String.format("Copying Linkmap %s", - linkmapFile.getValue().prettyPrint()))); - } - } - - /** - * Registers the actions that copy the debug symbol files from the CPU-specific binaries that are - * part of this application. The only one step executed is that he dsym files have to be renamed - * to include their corresponding CPU architecture as a suffix. - * - * @param dsymOutputType the file type of the dSYM bundle to be copied - */ - private void registerCopyDsymFilesAction(DsymOutputType dsymOutputType) { - for (Entry dsymFiles : getDsymFiles(dsymOutputType).entrySet()) { - ruleContext.registerAction( - new SymlinkAction( - ruleContext.getActionOwner(), - dsymFiles.getKey(), - dsymFiles.getValue(), - "Symlinking dSYM files")); - } - } - - /** - * Registers the action that copies the debug symbol plist from the binary. - * - * @param dsymOutputType the file type of the dSYM bundle to be copied - */ - private void registerCopyDsymPlistAction(DsymOutputType dsymOutputType) { - Artifact dsymPlist = getAnyCpuSpecificDsymPlist(); - if (dsymPlist != null) { - ruleContext.registerAction( - new SymlinkAction( - ruleContext.getActionOwner(), - dsymPlist, - intermediateArtifacts.dsymPlist(dsymOutputType), - "Symlinking dSYM plist")); - } - } - - /** - * Returns a map of input dsym artifacts from the CPU-specific binaries built for this - * ios_application to the new output dsym artifacts. - * - * @param dsymOutputType the file type of the dSYM bundle to be generated - */ - private ImmutableMap getDsymFiles(DsymOutputType dsymOutputType) { - ImmutableMap.Builder results = ImmutableMap.builder(); - for (Entry dsymFile : attributes.cpuSpecificDsymFiles().entrySet()) { - Artifact destDsym = intermediateArtifacts.dsymSymbol(dsymOutputType, dsymFile.getKey()); - results.put(dsymFile.getValue(), destDsym); - } - return results.build(); - } - - /** - * Returns any available CPU specific dSYM plist file. - */ - @Nullable - private Artifact getAnyCpuSpecificDsymPlist() { - for (Artifact dsymPlist : attributes.cpuSpecificDsymPlists().values()) { - // The plist files generated by the dsym tool are all equal, and don't really have any - // useful information. For now, just retrieving any one is OK, but ideally all of them should - // be merged. - return dsymPlist; - } - return null; - } - - /** - * Returns a map of input linkmap artifacts from the CPU-specific binaries built for this - * ios_application to the new output linkmap artifacts. - */ - private ImmutableMap getLinkmapFiles() { - ImmutableMap.Builder results = ImmutableMap.builder(); - for (Entry linkmapFile : attributes.cpuSpecificLinkmapFiles().entrySet()) { - Artifact destLinkMap = intermediateArtifacts.linkmap(linkmapFile.getKey()); - results.put(linkmapFile.getValue(), destLinkMap); - } - return results.build(); - } - - private void registerExtractTeamPrefixAction(Artifact teamPrefixFile) { - String shellCommand = "set -e && " - + "PLIST=$(mktemp -t teamprefix.plist) && trap \"rm ${PLIST}\" EXIT && " - + extractPlistCommand(releaseBundling.getProvisioningProfile()) + " > ${PLIST} && " - + "/usr/libexec/PlistBuddy -c 'Print ApplicationIdentifierPrefix:0' ${PLIST} > " - + teamPrefixFile.getShellEscapedExecPathString(); - ruleContext.registerAction( - ObjcRuleClasses.spawnBashOnDarwinActionBuilder(shellCommand) - .setMnemonic("ExtractIosTeamPrefix") - .disableSandboxing() - .addInput(releaseBundling.getProvisioningProfile()) - .addOutput(teamPrefixFile) - .build(ruleContext)); - } - - private ReleaseBundlingSupport registerExtractEntitlementsAction(Artifact entitlements) { - // See Apple Glossary (http://goo.gl/EkhXOb) - // An Application Identifier is constructed as: TeamID.BundleID - // TeamID is extracted from the provisioning profile. - // BundleID consists of a reverse-DNS string to identify the app, where the last component - // is the application name, and is specified as an attribute. - String shellCommand = "set -e && " - + "PLIST=$(mktemp -t entitlements.plist) && trap \"rm ${PLIST}\" EXIT && " - + extractPlistCommand(releaseBundling.getProvisioningProfile()) + " > ${PLIST} && " - + "/usr/libexec/PlistBuddy -x -c 'Print Entitlements' ${PLIST} > " - + entitlements.getShellEscapedExecPathString(); - ruleContext.registerAction( - ObjcRuleClasses.spawnBashOnDarwinActionBuilder(shellCommand) - .setMnemonic("ExtractIosEntitlements") - .disableSandboxing() - .setProgressMessage("Extracting entitlements: %s", ruleContext.getLabel()) - .addInput(releaseBundling.getProvisioningProfile()) - .addOutput(entitlements) - .build(ruleContext)); - - return this; - } - - private void registerEntitlementsVariableSubstitutionAction( - Artifact inputEntitlements, Artifact prefix, Artifact substitutedEntitlements) { - String escapedBundleId = ShellUtils.shellEscape(releaseBundling.getBundleId()); - String shellCommand = - "set -e && " - + "PREFIX=\"$(cat " - + prefix.getShellEscapedExecPathString() - + ")\" && " - + "sed " - // Replace .* from default entitlements file with bundle ID where suitable. - + "-e \"s#${PREFIX}\\.\\*#${PREFIX}." - + escapedBundleId - + "#g\" " - - // Replace some variables that people put in their own entitlements files - + "-e \"s#\\$(AppIdentifierPrefix)#${PREFIX}.#g\" " - + "-e \"s#\\$(CFBundleIdentifier)#" - + escapedBundleId - + "#g\" " - + inputEntitlements.getShellEscapedExecPathString() - + " > " - + substitutedEntitlements.getShellEscapedExecPathString(); - ruleContext.registerAction( - new SpawnAction.Builder() - .setMnemonic("SubstituteIosEntitlements") - .setShellCommand(shellCommand) - .addInput(inputEntitlements) - .addInput(prefix) - .addOutput(substitutedEntitlements) - .build(ruleContext)); - } - - /** Registers an action to copy Swift standard library dylibs into app bundle. */ - private void registerSwiftStdlibActionsIfNecessary(Artifact combinedArchBinary) { - if (!objcProvider.is(USES_SWIFT)) { - return; - } - - - CustomCommandLine.Builder commandLine = CustomCommandLine.builder(); - - commandLine - .add("--output_zip_path") - .addPath(intermediateArtifacts.swiftFrameworksFileZip().getExecPath()) - .add("--bundle_path") - .add("Frameworks") - .add("--platform") - .addDynamicString(platform.getLowerCaseNameInPlist()) - .addExecPath("--scan-executable", combinedArchBinary); - - ruleContext.registerAction( - ObjcRuleClasses.spawnAppleEnvActionBuilder( - XcodeConfigProvider.fromRuleContext(ruleContext), platform) - .setMnemonic("SwiftStdlibCopy") - .setExecutable(attributes.swiftStdlibToolWrapper()) - .addCommandLine(commandLine.build()) - .addOutput(intermediateArtifacts.swiftFrameworksFileZip()) - .addInput(combinedArchBinary) - .build(ruleContext)); - } - - /** Registers an action to copy Swift standard library dylibs into SwiftSupport root directory. */ - private void registerSwiftSupportActionsIfNecessary(Artifact combinedArchBinary) { - if (!objcProvider.is(USES_SWIFT)) { - return; - } - - - CustomCommandLine.Builder commandLine = CustomCommandLine.builder(); - commandLine - .add("--output_zip_path") - .addPath(intermediateArtifacts.swiftSupportZip().getExecPath()) - .add("--bundle_path") - .addDynamicString("SwiftSupport/" + platform.getLowerCaseNameInPlist()) - .add("--platform") - .addDynamicString(platform.getLowerCaseNameInPlist()) - .addExecPath("--scan-executable", combinedArchBinary); - - ruleContext.registerAction( - ObjcRuleClasses.spawnAppleEnvActionBuilder( - XcodeConfigProvider.fromRuleContext(ruleContext), platform) - .setMnemonic("SwiftCopySwiftSupport") - .setExecutable(attributes.swiftStdlibToolWrapper()) - .addCommandLine(commandLine.build()) - .addOutput(intermediateArtifacts.swiftSupportZip()) - .addInput(combinedArchBinary) - .build(ruleContext)); - } - - private String extractPlistCommand(Artifact provisioningProfile) { - return "security cms -D -i " + ShellUtils.shellEscape(provisioningProfile.getExecPathString()); - } - - private String deviceCodesignCommand(String appDir) { - String signingCertName = ObjcRuleClasses.objcConfiguration(ruleContext).getSigningCertName(); - Artifact entitlements = intermediateArtifacts.entitlements(); - - final String identity; - if (signingCertName != null) { - identity = '"' + signingCertName + '"'; - } else { - // Extracts an identity hash from the configured provisioning profile. Note that this will use - // the first certificate identity in the profile, regardless of how many identities are - // configured in it (DeveloperCertificates:0). - identity = - "$(PLIST=$(mktemp -t cert.plist) && trap \"rm ${PLIST}\" EXIT && " - + extractPlistCommand(releaseBundling.getProvisioningProfile()) - + " > ${PLIST} && " - + "/usr/libexec/PlistBuddy -c 'Print DeveloperCertificates:0' ${PLIST} | " - + "openssl x509 -inform DER -noout -fingerprint | " - + "cut -d= -f2 | sed -e 's#:##g')"; - } - - return String.format( - "/usr/bin/codesign --force --sign %s --entitlements %s %s", - identity, - entitlements.getShellEscapedExecPathString(), - appDir); - } - - private Artifact getGeneratedVersionPlist() { - return ruleContext.getRelatedArtifact( - ruleContext.getUniqueDirectory("plists"), artifactName("-version.plist")); - } - - private Artifact getGeneratedEnvironmentPlist() { - return ruleContext.getRelatedArtifact( - ruleContext.getUniqueDirectory("plists"), artifactName("-environment.plist")); - } - - private Artifact getGeneratedAutomaticPlist() { - return ruleContext.getRelatedArtifact( - ruleContext.getUniqueDirectory("plists"), artifactName("-automatic.plist")); - } - - private Artifact getLaunchStoryboardPlist() { - return ruleContext.getRelatedArtifact( - ruleContext.getUniqueDirectory("plists"), artifactName("-launchstoryboard.plist")); - } - - /** - * Returns artifact name prefixed with prefix given in {@link ReleaseBundling} if available. - * This helps in creating unique artifact name when multiple bundles are created with a different - * name than the target name. - */ - private String artifactName(String artifactName) { - if (releaseBundling.getArtifactPrefix() != null) { - return String.format("-%s%s", releaseBundling.getArtifactPrefix(), artifactName); - } - return artifactName; - } - - /** - * Logic to access attributes to access tools required by application support. - * Attributes are required and guaranteed to return a value or throw unless they are annotated - * with {@link Nullable} in which case they can return {@code null} if no value is defined. - */ - private static class Attributes { - private final RuleContext ruleContext; - - private Attributes(RuleContext ruleContext) { - this.ruleContext = ruleContext; - } - - /** - * Returns this target's user-specified {@code ipa_post_processor} or null if not present. - */ - @Nullable - FilesToRunProvider ipaPostProcessor() { - if (!ruleContext.attributes().has("ipa_post_processor", BuildType.LABEL)) { - return null; - } - return ruleContext.getExecutablePrerequisite("ipa_post_processor", Mode.TARGET); - } - - /** - * Returns the multi-arch binary provided by the label under the "binary" attribute of the - * current rule, or null if there is no such binary available. - */ - @Nullable Artifact dependentMultiArchBinary() { - if (ruleContext.attributes().getAttributeDefinition("binary") == null) { - return null; - } - - for (ObjcProvider provider - : ruleContext.getPrerequisites( - "binary", Mode.DONT_CHECK, ObjcProvider.SKYLARK_CONSTRUCTOR)) { - if (!provider.get(ObjcProvider.MULTI_ARCH_LINKED_BINARIES).isEmpty()) { - return Iterables.getOnlyElement(provider.get(ObjcProvider.MULTI_ARCH_LINKED_BINARIES)); - } - } - return null; - } - - NestedSet dependentLinkedBinaries() { - if (ruleContext.attributes().getAttributeDefinition("binary") == null) { - return NestedSetBuilder.emptySet(Order.STABLE_ORDER); - } - - NestedSetBuilder linkedBinaries = NestedSetBuilder.stableOrder(); - for (ObjcProvider provider - : ruleContext.getPrerequisites( - "binary", Mode.DONT_CHECK, ObjcProvider.SKYLARK_CONSTRUCTOR)) { - linkedBinaries.addTransitive(provider.get(ObjcProvider.LINKED_BINARY)); - } - - return linkedBinaries.build(); - } - - FilesToRunProvider bundleMergeExecutable() { - return checkNotNull(ruleContext.getExecutablePrerequisite("$bundlemerge", Mode.HOST)); - } - - /** - * Returns a reference to the plmerge executable. - */ - FilesToRunProvider plmerge() { - return ruleContext.getExecutablePrerequisite("$plmerge", Mode.HOST); - } - - Artifact stdRedirectDylib() { - return checkNotNull(ruleContext.getPrerequisiteArtifact("$std_redirect_dylib", Mode.HOST)); - } - - Artifact runnerScriptTemplate() { - return checkNotNull( - ruleContext.getPrerequisiteArtifact("$runner_script_template", Mode.HOST)); - } - - /** Returns the location of the swiftstdlibtoolwrapper. */ - FilesToRunProvider swiftStdlibToolWrapper() { - return ruleContext.getExecutablePrerequisite("$swiftstdlibtoolwrapper", Mode.HOST); - } - - /** - * Returns the location of the environment_plist. - */ - FilesToRunProvider environmentPlist() { - return ruleContext.getExecutablePrerequisite("$environment_plist", Mode.HOST); - } - - /** - * Returns a plist specified by the user via {@code --extra_entitlements} or {@code null}. - */ - @Nullable - Artifact extraEntitlements() { - if (ruleContext.attributes().getAttributeDefinition(EXTRA_ENTITLEMENTS_ATTR) == null) { - return null; - } - return ruleContext.getPrerequisiteArtifact(EXTRA_ENTITLEMENTS_ATTR, Mode.HOST); - } - - /** - * Returns a plist containing entitlements that allow the signed IPA to be debugged. - */ - @Nullable - Artifact deviceDebugEntitlements() { - if (ruleContext.attributes().getAttributeDefinition(DEBUG_ENTITLEMENTS_ATTR) == null) { - return null; - } - return ruleContext.getPrerequisiteArtifact(DEBUG_ENTITLEMENTS_ATTR, Mode.HOST); - } - - ImmutableMap cpuSpecificDsymFiles() { - return cpuSpecificArtifacts(ObjcProvider.DEBUG_SYMBOLS); - } - - ImmutableMap cpuSpecificDsymPlists() { - return cpuSpecificArtifacts(ObjcProvider.DEBUG_SYMBOLS_PLIST); - } - - ImmutableMap cpuSpecificLinkmapFiles() { - return cpuSpecificArtifacts(ObjcProvider.LINKMAP_FILE); - } - - ImmutableMap cpuSpecificArtifacts(ObjcProvider.Key key) { - ImmutableMap.Builder results = ImmutableMap.builder(); - if (ruleContext.attributes().has("binary", BuildType.LABEL)) { - for (TransitiveInfoCollection prerequisite - : ruleContext.getPrerequisites("binary", Mode.DONT_CHECK)) { - ObjcProvider prerequisiteProvider = prerequisite.get(ObjcProvider.SKYLARK_CONSTRUCTOR); - if (prerequisiteProvider != null) { - Artifact sourceArtifact = Iterables.getOnlyElement(prerequisiteProvider.get(key), null); - if (sourceArtifact != null) { - String cpu = - prerequisite.getConfiguration().getFragment(AppleConfiguration.class).getIosCpu(); - results.put(cpu, sourceArtifact); - } - } - } - } - return results.build(); - } - } -} diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/Storyboards.java b/src/main/java/com/google/devtools/build/lib/rules/objc/Storyboards.java deleted file mode 100644 index cfa4d6c65a..0000000000 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/Storyboards.java +++ /dev/null @@ -1,76 +0,0 @@ -// 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.devtools.build.lib.actions.Artifact; -import com.google.devtools.build.lib.collect.nestedset.NestedSet; -import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; -import com.google.devtools.build.lib.collect.nestedset.Order; - -/** - * Contains information about storyboards for a single target. This does not include information - * about the transitive closure. A storyboard: - *

    - *
  • Is a single file with an extension of {@code .storyboard} in its uncompiled, checked-in - * form. - *
  • Can be in a localized {@code .lproj} directory, including {@code Base.lproj}. - *
  • Compiles with {@code ibtool} to a directory with extension {@code .storyboardc} (note the - * added "c") - *
- * - *

The {@link NestedSet}s stored in this class are only one level deep, and do not include the - * storyboards in the transitive closure. This is to facilitate structural sharing between copies - * of the sequences - the output zips can be added transitively to the inputs of the merge bundle - * action, as well as to the files to build set, and only one instance of the sequence exists for - * each set. - */ -final class Storyboards { - private final NestedSet outputZips; - private final NestedSet inputs; - - private Storyboards(NestedSet outputZips, NestedSet inputs) { - this.outputZips = outputZips; - this.inputs = inputs; - } - - public NestedSet getOutputZips() { - return outputZips; - } - - public NestedSet getInputs() { - return inputs; - } - - static Storyboards empty() { - return new Storyboards( - NestedSetBuilder.emptySet(Order.STABLE_ORDER), - NestedSetBuilder.emptySet(Order.STABLE_ORDER)); - } - - /** - * Generates a set of new instances given the raw storyboard inputs. - * @param inputs the {@code .storyboard} files. - * @param intermediateArtifacts the object used to determine the output zip {@link Artifact}s. - */ - static Storyboards fromInputs( - Iterable inputs, IntermediateArtifacts intermediateArtifacts) { - NestedSetBuilder outputZips = NestedSetBuilder.stableOrder(); - for (Artifact input : inputs) { - outputZips.add(intermediateArtifacts.compiledStoryboardZip(input)); - } - return new Storyboards(outputZips.build(), NestedSetBuilder.wrap(Order.STABLE_ORDER, inputs)); - } -} diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java deleted file mode 100644 index 6969bee9f6..0000000000 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2015 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.Joiner; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; -import com.google.devtools.build.lib.actions.Artifact; -import com.google.devtools.build.lib.analysis.FileProvider; -import com.google.devtools.build.lib.analysis.PrerequisiteArtifacts; -import com.google.devtools.build.lib.analysis.RuleContext; -import com.google.devtools.build.lib.analysis.Runfiles.Builder; -import com.google.devtools.build.lib.analysis.RunfilesProvider; -import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction; -import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution; -import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; -import com.google.devtools.build.lib.analysis.test.InstrumentedFilesProvider; -import com.google.devtools.build.lib.analysis.test.TestEnvironmentInfo; -import com.google.devtools.build.lib.collect.nestedset.NestedSet; -import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; -import com.google.devtools.build.lib.packages.Info; -import com.google.devtools.build.lib.rules.apple.AppleConfiguration; -import com.google.devtools.build.lib.rules.apple.DottedVersion; -import com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.SimulatorRule; -import com.google.devtools.build.lib.syntax.Type; -import com.google.devtools.build.lib.util.FileType; -import java.util.List; -import javax.annotation.Nullable; - -/** - * Support for running XcTests. - */ -public class TestSupport { - private final RuleContext ruleContext; - - public TestSupport(RuleContext ruleContext) { - this.ruleContext = ruleContext; - } - - /** - * Registers actions to create all files needed in order to actually run the test. - * - * @throws InterruptedException - */ - public TestSupport registerTestRunnerActions() throws InterruptedException { - registerTestScriptSubstitutionAction(); - return this; - } - - /** - * Returns the script which should be run in order to actually run the tests. - */ - public Artifact generatedTestScript() { - return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, "_test_script"); - } - - private void registerTestScriptSubstitutionAction() throws InterruptedException { - // testBundleIpa is the bundle actually containing the tests. - Artifact testBundleIpa = testBundleIpa(); - - String runMemleaks = - ruleContext.getFragment(ObjcConfiguration.class).runMemleaks() ? "true" : "false"; - - // TODO(ulfjack): This is missing the action environment, and the inherited parts from both. Is - // that intentional? We should either fix it, or clearly document why we're doing that. - ImmutableMap testEnv = - ruleContext.getConfiguration().getTestActionEnvironment().getFixedEnv(); - - // The substitutions below are common for simulator and lab device. - ImmutableList.Builder substitutions = - new ImmutableList.Builder() - .add(Substitution.of("%(memleaks)s", runMemleaks)) - .add(Substitution.of("%(test_app_ipa)s", testBundleIpa.getRootRelativePathString())) - .add(Substitution.of("%(test_app_name)s", baseNameWithoutIpa(testBundleIpa))) - .add(Substitution.of("%(test_bundle_path)s", testBundleIpa.getRootRelativePathString())) - .add( - Substitution.of("%(plugin_jars)s", Artifact.joinRootRelativePaths(":", plugins()))); - - substitutions.add(Substitution.ofSpaceSeparatedMap("%(test_env)s", testEnv)); - - // testHarnessIpa is the app being tested in the case where testBundleIpa is a .xctest bundle. - Optional testHarnessIpa = testHarnessIpa(); - if (testHarnessIpa.isPresent()) { - substitutions - .add(Substitution.of("%(xctest_app_ipa)s", - testHarnessIpa.get().getRootRelativePathString())) - .add(Substitution.of("%(xctest_app_name)s", baseNameWithoutIpa(testHarnessIpa.get()))) - .add(Substitution.of("%(test_host_path)s", - testHarnessIpa.get().getRootRelativePathString())); - } else { - substitutions - .add(Substitution.of("%(xctest_app_ipa)s", "")) - .add(Substitution.of("%(xctest_app_name)s", "")) - .add(Substitution.of("%(test_host_path)s", "")); - } - - substitutions.add(Substitution.of("%(test_type)s", "XCTEST")); - - Artifact template; - if (!runWithLabDevice()) { - substitutions.addAll(substitutionsForSimulator()); - template = ruleContext.getPrerequisiteArtifact(IosTest.TEST_TEMPLATE_ATTR, Mode.TARGET); - } else { - substitutions.addAll(substitutionsForLabDevice()); - template = testTemplateForLabDevice(); - } - - ruleContext.registerAction( - new TemplateExpansionAction( - ruleContext.getActionOwner(), - template, - generatedTestScript(), - substitutions.build(), - /* makeExecutable= */ true)); - } - - private boolean runWithLabDevice() { - return iosLabDeviceSubstitutions() != null; - } - - /** - * Gets the substitutions for simulator. - */ - private ImmutableList substitutionsForSimulator() { - ImmutableList.Builder substitutions = new ImmutableList.Builder() - .add(Substitution.of("%(std_redirect_dylib_path)s", - stdRedirectDylib().getRunfilesPathString())) - .addAll(deviceSubstitutions().getSubstitutionsForTestRunnerScript()); - - Optional testRunner = testRunner(); - if (testRunner.isPresent()) { - substitutions.add( - Substitution.of("%(testrunner_binary)s", testRunner.get().getRunfilesPathString())); - } - return substitutions.build(); - } - - private IosTestSubstitutionProvider deviceSubstitutions() { - return ruleContext.getPrerequisite( - IosTest.TARGET_DEVICE, Mode.TARGET, IosTestSubstitutionProvider.class); - } - - /* - * The IPA of the bundle that contains the tests. Typically will be a .xctest bundle, but in the - * case where the xctest attribute is false, it will be a .app bundle. - */ - private Artifact testBundleIpa() throws InterruptedException { - return ruleContext.getImplicitOutputArtifact(ReleaseBundlingSupport.IPA); - } - - /* - * The IPA of the testHarness in the case where the testBundleIpa is an .xctest bundle. - */ - private Optional testHarnessIpa() { - FileProvider fileProvider = - ruleContext.getPrerequisite(IosTest.XCTEST_APP_ATTR, Mode.TARGET, FileProvider.class); - if (fileProvider == null) { - return Optional.absent(); - } - List files = - Artifact.filterFiles(fileProvider.getFilesToBuild(), FileType.of(".ipa")); - if (files.size() == 0) { - return Optional.absent(); - } else if (files.size() == 1) { - return Optional.of(Iterables.getOnlyElement(files)); - } else { - throw new IllegalStateException("Expected 0 or 1 files in xctest_app, got: " + files); - } - } - - private Artifact stdRedirectDylib() { - return ruleContext.getPrerequisiteArtifact(SimulatorRule.STD_REDIRECT_DYLIB_ATTR, Mode.HOST); - } - - /** - * Gets the binary of the testrunner attribute, if there is one. - */ - private Optional testRunner() { - return Optional.fromNullable( - ruleContext.getPrerequisiteArtifact(IosTest.TEST_RUNNER_ATTR, Mode.TARGET)); - } - - /** - * Gets the substitutions for lab device. - */ - private ImmutableList substitutionsForLabDevice() { - return new ImmutableList.Builder() - .addAll(iosLabDeviceSubstitutions().getSubstitutionsForTestRunnerScript()) - .add(Substitution.of("%(ios_device_arg)s", Joiner.on(" ").join(iosDeviceArgs()))).build(); - } - - /** - * Gets the test template for lab devices. - */ - private Artifact testTemplateForLabDevice() { - return ruleContext - .getPrerequisite( - IosTest.TEST_TARGET_DEVICE_ATTR, Mode.TARGET, LabDeviceTemplateProvider.class) - .getLabDeviceTemplate(); - } - - @Nullable - private IosTestSubstitutionProvider iosLabDeviceSubstitutions() { - return ruleContext.getPrerequisite( - IosTest.TEST_TARGET_DEVICE_ATTR, Mode.TARGET, IosTestSubstitutionProvider.class); - } - - private List iosDeviceArgs() { - return ruleContext.attributes().get(IosTest.DEVICE_ARG_ATTR, Type.STRING_LIST); - } - - /** - * Adds all files needed to run this test to the passed Runfiles builder. - */ - public TestSupport addRunfiles( - Builder runfilesBuilder, InstrumentedFilesProvider instrumentedFilesProvider) - throws InterruptedException { - runfilesBuilder - .addArtifact(testBundleIpa()) - .addArtifacts(testHarnessIpa().asSet()) - .addArtifact(generatedTestScript()) - .addTransitiveArtifacts(plugins()); - if (!runWithLabDevice()) { - runfilesBuilder - .addArtifact(stdRedirectDylib()) - .addTransitiveArtifacts(deviceRunfiles()) - .addArtifacts(testRunner().asSet()); - } else { - runfilesBuilder.addTransitiveArtifacts(labDeviceRunfiles()); - } - - if (ruleContext.getConfiguration().isCodeCoverageEnabled()) { - runfilesBuilder.addArtifact(ruleContext.getHostPrerequisiteArtifact(IosTest.MCOV_TOOL_ATTR)); - runfilesBuilder.addTransitiveArtifacts(instrumentedFilesProvider.getInstrumentedFiles()); - } - - return this; - } - - /** - * Returns any additional providers that need to be exported to the rule context to the passed - * builder. - */ - public Iterable getExtraProviders() { - IosDeviceProvider deviceProvider = - ruleContext.getPrerequisite( - IosTest.TARGET_DEVICE, Mode.TARGET, IosDeviceProvider.SKYLARK_CONSTRUCTOR); - DottedVersion xcodeVersion = deviceProvider.getXcodeVersion(); - - ImmutableMap.Builder envBuilder = ImmutableMap.builder(); - - if (xcodeVersion != null) { - envBuilder.putAll(AppleConfiguration.getXcodeVersionEnv(xcodeVersion)); - } - - if (ruleContext.getConfiguration().isCodeCoverageEnabled()) { - envBuilder.put("COVERAGE_GCOV_PATH", - ruleContext.getHostPrerequisiteArtifact(IosTest.OBJC_GCOV_ATTR).getExecPathString()); - envBuilder.put("APPLE_COVERAGE", "1"); - } - - return ImmutableList.of(new TestEnvironmentInfo(envBuilder.build())); - } - - /** - * Jar files for plugins to the test runner. May be empty. - */ - private NestedSet plugins() { - NestedSetBuilder pluginArtifacts = NestedSetBuilder.stableOrder(); - pluginArtifacts.addTransitive( - PrerequisiteArtifacts.nestedSet(ruleContext, IosTest.PLUGINS_ATTR, Mode.TARGET)); - if (ruleContext.getFragment(ObjcConfiguration.class).runMemleaks()) { - pluginArtifacts.addTransitive( - PrerequisiteArtifacts.nestedSet(ruleContext, IosTest.MEMLEAKS_PLUGIN_ATTR, Mode.TARGET)); - } - return pluginArtifacts.build(); - } - - /** - * Runfiles required in order to use the specified target device. - */ - private NestedSet deviceRunfiles() { - return ruleContext.getPrerequisite(IosTest.TARGET_DEVICE, Mode.TARGET, RunfilesProvider.class) - .getDefaultRunfiles().getAllArtifacts(); - } - - /** - * Runfiles required in order to use the specified target device. - */ - private NestedSet labDeviceRunfiles() { - return ruleContext - .getPrerequisite(IosTest.TEST_TARGET_DEVICE_ATTR, Mode.TARGET, RunfilesProvider.class) - .getDefaultRunfiles().getAllArtifacts(); - } - - /** - * Adds files which must be built in order to run this test to builder. - */ - public TestSupport addFilesToBuild(NestedSetBuilder builder) - throws InterruptedException { - builder.add(testBundleIpa()).addAll(testHarnessIpa().asSet()); - return this; - } - - /** - * Returns the base name of the artifact, with the .ipa stuffix stripped. - */ - private static String baseNameWithoutIpa(Artifact artifact) { - String baseName = artifact.getExecPath().getBaseName(); - Preconditions.checkState(baseName.endsWith(".ipa"), - "%s should end in .ipa but doesn't", baseName); - return baseName.substring(0, baseName.length() - 4); - } -} diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/XcTestAppProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/XcTestAppProvider.java deleted file mode 100644 index 09bbad98dc..0000000000 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/XcTestAppProvider.java +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2015 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.Preconditions; -import com.google.common.collect.ImmutableMap; -import com.google.devtools.build.lib.actions.Artifact; -import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; -import com.google.devtools.build.lib.packages.NativeInfo; -import com.google.devtools.build.lib.packages.NativeProvider; -import com.google.devtools.build.lib.packages.NativeProvider.WithLegacySkylarkName; -import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; -import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; - -/** Supplies information needed when a dependency serves as an {@code xctest_app}. */ -@Immutable -@SkylarkModule( - name = "XcTestAppProvider", - category = SkylarkModuleCategory.PROVIDER, - doc = - "Deprecated. A provider for XCTest apps for testing. This is a legacy provider and should " - + "not be used." -) -public final class XcTestAppProvider extends NativeInfo { - /** - * The skylark struct key name for a rule implementation to use when exporting an ObjcProvider. - */ - public static final String XCTEST_APP_SKYLARK_PROVIDER_NAME = "xctest_app"; - - public static final NativeProvider SKYLARK_CONSTRUCTOR = new Constructor(); - - private final Artifact bundleLoader; - private final Artifact ipa; - private final ObjcProvider objcProvider; - - XcTestAppProvider(Artifact bundleLoader, Artifact ipa, ObjcProvider objcProvider) { - super(SKYLARK_CONSTRUCTOR, getSkylarkFields(bundleLoader, ipa, objcProvider)); - this.bundleLoader = Preconditions.checkNotNull(bundleLoader); - this.ipa = Preconditions.checkNotNull(ipa); - this.objcProvider = Preconditions.checkNotNull(objcProvider); - } - - /** The bundle loader, which corresponds to the test app's binary. */ - public Artifact getBundleLoader() { - return bundleLoader; - } - - /** The test app's IPA. */ - public Artifact getIpa() { - return ipa; - } - - /** - * An {@link ObjcProvider} that should be included by any test target that uses this app as its - * {@code xctest_app}. This is not a typical {@link ObjcProvider} - it has - * certain linker-releated keys omitted, such as {@link ObjcProvider#LIBRARY}, since XcTests have - * access to symbols in their test rig without linking them into the main test binary. - */ - public ObjcProvider getObjcProvider() { - return objcProvider; - } - - private static ImmutableMap getSkylarkFields( - Artifact bundleLoader, Artifact ipa, ObjcProvider objcProvider) { - return new ImmutableMap.Builder() - .put("bundle_loader", bundleLoader) - .put("ipa", ipa) - .put("objc", objcProvider) - .build(); - } - - private static class Constructor extends NativeProvider - implements WithLegacySkylarkName { - - private Constructor() { - super(XcTestAppProvider.class, "xctest_app_provider"); - } - - @Override - public String getSkylarkName() { - return XCTEST_APP_SKYLARK_PROVIDER_NAME; - } - - @Override - public String getErrorMessageFormatForUnknownField() { - return "XcTestAppProvider field '%s' could not be instantiated"; - } - } -} -- cgit v1.2.3