diff options
Diffstat (limited to 'src/main/java/com')
20 files changed, 345 insertions, 403 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java b/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java index 2608a9c0ab..67b4fb07de 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java @@ -98,6 +98,7 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory .registerActions() .addXcodeSettings(xcodeProviderBuilder) .addFilesToBuild(filesToBuild) + .validateResources() .validateAttributes(); xcTestAppProvider = Optional.of(releaseBundlingSupport.xcTestAppProvider()); if (ObjcRuleClasses.objcConfiguration(ruleContext).getPlatform() == Platform.SIMULATOR) { @@ -115,7 +116,6 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory } new ResourceSupport(ruleContext) - .registerActions(common.getStoryboards()) .validateAttributes() .addXcodeSettings(xcodeProviderBuilder); diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/BundleMergeControlBytes.java b/src/main/java/com/google/devtools/build/lib/rules/objc/BundleMergeControlBytes.java index 24c5f58660..38a1b332f3 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/BundleMergeControlBytes.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BundleMergeControlBytes.java @@ -16,7 +16,6 @@ package com.google.devtools.build.lib.rules.objc; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.BUNDLE_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.NESTED_BUNDLE; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XCDATAMODEL; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; @@ -80,12 +79,6 @@ final class BundleMergeControlBytes extends ByteSource { .build()); } - for (Xcdatamodel datamodel : objcProvider.get(XCDATAMODEL)) { - control.addMergeZip(MergeZip.newBuilder() - .setEntryNamePrefix(mergeZipPrefix) - .setSourcePath(datamodel.getOutputZip().getExecPathString()) - .build()); - } for (TargetDeviceFamily targetDeviceFamily : families) { control.addTargetDeviceFamily(targetDeviceFamily.name()); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/BundleSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/BundleSupport.java index 4e20ddc6ee..822f53b781 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/BundleSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BundleSupport.java @@ -14,14 +14,25 @@ package com.google.devtools.build.lib.rules.objc; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STRINGS; + import com.google.common.base.Optional; +import com.google.common.base.Verify; +import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.FilesToRunProvider; import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; +import com.google.devtools.build.lib.analysis.actions.SpawnAction; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.rules.objc.ObjcActionsBuilder.ExtraActoolArgs; import com.google.devtools.build.lib.rules.objc.XcodeProvider.Builder; +import com.google.devtools.build.lib.vfs.FileSystemUtils; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; import java.util.Set; /** @@ -36,6 +47,7 @@ final class BundleSupport { private final Set<TargetDeviceFamily> targetDeviceFamilies; private final ExtraActoolArgs extraActoolArgs; private final Bundling bundling; + private final Attributes attributes; /** * Returns merging instructions for a bundle's {@code Info.plist}. @@ -87,6 +99,7 @@ final class BundleSupport { this.targetDeviceFamilies = targetDeviceFamilies; this.extraActoolArgs = extraActoolArgs; this.bundling = bundling; + this.attributes = new Attributes(ruleContext); } /** @@ -94,10 +107,13 @@ final class BundleSupport { * Info.plist} files and generating asset catalogues. * * @param objcProvider source of information from this rule's attributes and its dependencies - * * @return this bundle support */ BundleSupport registerActions(ObjcProvider objcProvider) { + registerConvertStringsActions(objcProvider); + registerConvertXibsActions(objcProvider); + registerMomczipActions(objcProvider); + registerInterfaceBuilderActions(objcProvider); registerMergeInfoplistAction(); registerActoolActionIfNecessary(objcProvider); @@ -114,6 +130,153 @@ final class BundleSupport { return this; } + /** + * Validates that resources defined in this rule and its dependencies and written to this bundle + * are legal (for example that they are not mapped to the same bundle location). + * + * @return this bundle support + */ + BundleSupport validateResources(ObjcProvider objcProvider) { + Map<String, Artifact> bundlePathToFile = new HashMap<>(); + for (Artifact stringsFile : objcProvider.get(STRINGS)) { + String bundlePath = BundleableFile.flatBundlePath(stringsFile.getExecPath()); + + // Normally any two resources mapped to the same path in the bundle are illegal. However, we + // currently don't have a good solution for resources generated by a genrule in + // multi-architecture builds: They map to the same bundle path but have different owners (the + // genrules targets in the various configurations) and roots (one for each architecture). + // Since we know that architecture shouldn't matter for strings file generation we silently + // ignore cases like this and pick one of the outputs at random to put in the bundle (see also + // related filtering code in Bundling.Builder.build()). + if (bundlePathToFile.containsKey(bundlePath)) { + Artifact original = bundlePathToFile.get(bundlePath); + if (!Objects.equals(original.getOwner(), stringsFile.getOwner())) { + ruleContext.ruleError(String.format( + "Two string files map to the same path [%s] in this bundle but come from different " + + "locations: %s and %s", + bundlePath, original.getOwner(), stringsFile.getOwner())); + } else { + Verify.verify(!original.getRoot().equals(stringsFile.getRoot()), + "%s and %s should have different roots but have %s and %s", + original, stringsFile, original.getRoot(), stringsFile.getRoot()); + } + + } else { + bundlePathToFile.put(bundlePath, stringsFile); + } + } + + // TODO(bazel-team): Do the same validation for storyboards and datamodels which could also be + // generated by genrules or doubly defined. + + return this; + } + + private void registerInterfaceBuilderActions(ObjcProvider objcProvider) { + IntermediateArtifacts intermediateArtifacts = + ObjcRuleClasses.intermediateArtifacts(ruleContext); + ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); + String minimumOs = objcConfiguration.getMinimumOs(); + for (Artifact storyboardInput : objcProvider.get(ObjcProvider.STORYBOARD)) { + String archiveRoot = BundleableFile.flatBundlePath(storyboardInput.getExecPath()) + "c"; + Artifact zipOutput = intermediateArtifacts.compiledStoryboardZip(storyboardInput); + + ruleContext.registerAction( + ObjcActionsBuilder.spawnJavaOnDarwinActionBuilder(attributes.ibtoolzipDeployJar()) + .setMnemonic("StoryboardCompile") + .setCommandLine(CustomCommandLine.builder() + // The next three arguments are positional, + // i.e. they don't have flags before them. + .addPath(zipOutput.getExecPath()) + .add(archiveRoot) + .addPath(ObjcActionsBuilder.IBTOOL) + + .add("--minimum-deployment-target").add(minimumOs) + .addPath(storyboardInput.getExecPath()) + .build()) + .addOutput(zipOutput) + .addInput(storyboardInput) + .build(ruleContext)); + } + } + + private void registerMomczipActions(ObjcProvider objcProvider) { + ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); + IntermediateArtifacts intermediateArtifacts = + ObjcRuleClasses.intermediateArtifacts(ruleContext); + Iterable<Xcdatamodel> xcdatamodels = Xcdatamodels.xcdatamodels( + intermediateArtifacts, objcProvider.get(ObjcProvider.XCDATAMODEL)); + for (Xcdatamodel datamodel : xcdatamodels) { + Artifact outputZip = datamodel.getOutputZip(); + ruleContext.registerAction( + ObjcActionsBuilder.spawnJavaOnDarwinActionBuilder(attributes.momczipDeployJar()) + .setMnemonic("MomCompile") + .addOutput(outputZip) + .addInputs(datamodel.getInputs()) + .setCommandLine(CustomCommandLine.builder() + .addPath(outputZip.getExecPath()) + .add(datamodel.archiveRootForMomczip()) + .add(IosSdkCommands.MOMC_PATH) + .add(commonMomczipArguments(objcConfiguration)) + .add(datamodel.getContainer().getSafePathString()) + .build()) + .build(ruleContext)); + } + } + + static Iterable<String> commonMomczipArguments(ObjcConfiguration configuration) { + return ImmutableList.of( + "-XD_MOMC_SDKROOT=" + IosSdkCommands.sdkDir(configuration), + "-XD_MOMC_IOS_TARGET_VERSION=" + configuration.getMinimumOs(), + "-MOMC_PLATFORMS", configuration.getPlatform().getLowerCaseNameInPlist(), + "-XD_MOMC_TARGET_VERSION=10.6"); + } + + private void registerConvertXibsActions(ObjcProvider objcProvider) { + IntermediateArtifacts intermediateArtifacts = + ObjcRuleClasses.intermediateArtifacts(ruleContext); + ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); + for (Artifact original : objcProvider.get(ObjcProvider.XIB)) { + Artifact zipOutput = intermediateArtifacts.compiledXibFileZip(original); + String archiveRoot = BundleableFile.flatBundlePath( + FileSystemUtils.replaceExtension(original.getExecPath(), ".nib")); + ruleContext.registerAction( + ObjcActionsBuilder.spawnJavaOnDarwinActionBuilder(attributes.ibtoolzipDeployJar()) + .setMnemonic("XibCompile") + .setCommandLine(CustomCommandLine.builder() + // The next three arguments are positional, + // i.e. they don't have flags before them. + .addPath(zipOutput.getExecPath()) + .add(archiveRoot) + .addPath(ObjcActionsBuilder.IBTOOL) + + .add("--minimum-deployment-target").add(objcConfiguration.getMinimumOs()) + .addPath(original.getExecPath()) + .build()) + .addOutput(zipOutput) + .addInput(original) + .build(ruleContext)); + } + } + + private void registerConvertStringsActions(ObjcProvider objcProvider) { + IntermediateArtifacts intermediateArtifacts = + ObjcRuleClasses.intermediateArtifacts(ruleContext); + for (Artifact strings : objcProvider.get(ObjcProvider.STRINGS)) { + Artifact bundled = intermediateArtifacts.convertedStringsFile(strings); + ruleContext.registerAction(new SpawnAction.Builder() + .setMnemonic("ConvertStringsPlist") + .setExecutable(attributes.plmerge()) + .setCommandLine(CustomCommandLine.builder() + .addExecPath("--source_file", strings) + .addExecPath("--out_file", bundled) + .build()) + .addInput(strings) + .addOutput(bundled) + .build(ruleContext)); + } + } + private void registerMergeInfoplistAction() { // TODO(bazel-team): Move action implementation from InfoplistMerging to this class. ruleContext.registerAction(bundling.getInfoplistMerging().getMergeAction()); @@ -157,4 +320,35 @@ final class BundleSupport { } } + /** + * Common rule attributes used by a bundle support. + */ + private static class Attributes { + private final RuleContext ruleContext; + + private Attributes(RuleContext ruleContext) { + this.ruleContext = ruleContext; + } + + /** + * Returns a reference to the plmerge executable. + */ + FilesToRunProvider plmerge() { + return ruleContext.getExecutablePrerequisite("$plmerge", Mode.HOST); + } + + /** + * Returns the location of the ibtoolzip deploy jar. + */ + Artifact ibtoolzipDeployJar() { + return ruleContext.getPrerequisiteArtifact("$ibtoolzip_deploy", Mode.HOST); + } + + /** + * Returns the location of the momczip deploy jar. + */ + Artifact momczipDeployJar() { + return ruleContext.getPrerequisiteArtifact("$momczip_deploy", Mode.HOST); + } + } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/BundleableFile.java b/src/main/java/com/google/devtools/build/lib/rules/objc/BundleableFile.java index ab6d89874f..e82891e89e 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/BundleableFile.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BundleableFile.java @@ -139,10 +139,10 @@ public final class BundleableFile extends Value<BundleableFile> { } /** - * The artifact that is ultimately bundled. + * Returns the location into which this file should be put in, relative to the bundle root. */ - public Artifact getBundled() { - return bundled; + public String getBundlePath() { + return bundlePath; } /** diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/Bundling.java b/src/main/java/com/google/devtools/build/lib/rules/objc/Bundling.java index acf40675d8..8b5edfdabb 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/Bundling.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/Bundling.java @@ -20,11 +20,15 @@ import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIB import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.MERGE_ZIP; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.NESTED_BUNDLE; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STORYBOARD; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STRINGS; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XCDATAMODEL; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XIB; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.devtools.build.lib.actions.Artifact; @@ -33,7 +37,9 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.vfs.PathFragment; +import java.util.HashSet; import java.util.Map; +import java.util.Set; /** * Contains information regarding the creation of an iOS bundle. @@ -43,7 +49,8 @@ final class Bundling { static final class Builder { private String name; private String bundleDirFormat; - private ImmutableList<BundleableFile> extraBundleFiles = ImmutableList.of(); + private ImmutableList.Builder<BundleableFile> extraBundleFilesBuilder = + new ImmutableList.Builder<>(); private ObjcProvider objcProvider; private InfoplistMerging infoplistMerging; private IntermediateArtifacts intermediateArtifacts; @@ -70,8 +77,8 @@ final class Bundling { return this; } - public Builder setExtraBundleFiles(ImmutableList<BundleableFile> extraBundleFiles) { - this.extraBundleFiles = extraBundleFiles; + public Builder addExtraBundleFiles(ImmutableList<BundleableFile> extraBundleFiles) { + this.extraBundleFilesBuilder.addAll(extraBundleFiles); return this; } @@ -108,6 +115,21 @@ final class Bundling { return artifacts.build(); } + private NestedSet<Artifact> getMergeZips(Optional<Artifact> actoolzipOutput) { + NestedSetBuilder<Artifact> mergeZipBuilder = NestedSetBuilder.<Artifact>stableOrder() + .addAll(actoolzipOutput.asSet()) + .addAll(Xcdatamodel.outputZips( + Xcdatamodels.xcdatamodels(intermediateArtifacts, objcProvider.get(XCDATAMODEL)))) + .addTransitive(objcProvider.get(MERGE_ZIP)); + for (Artifact xibFile : objcProvider.get(XIB)) { + mergeZipBuilder.add(intermediateArtifacts.compiledXibFileZip(xibFile)); + } + for (Artifact storyboard : objcProvider.get(STORYBOARD)) { + mergeZipBuilder.add(intermediateArtifacts.compiledStoryboardZip(storyboard)); + } + return mergeZipBuilder.build(); + } + public Bundling build() { Preconditions.checkNotNull(intermediateArtifacts, "intermediateArtifacts"); @@ -123,23 +145,37 @@ final class Bundling { Optional.of(intermediateArtifacts.combinedArchitectureBinary()); } - NestedSet<Artifact> mergeZips = NestedSetBuilder.<Artifact>stableOrder() - .addAll(actoolzipOutput.asSet()) - .addTransitive(objcProvider.get(MERGE_ZIP)) - .build(); - NestedSet<Artifact> bundleContentArtifacts = NestedSetBuilder.<Artifact>stableOrder() - .addTransitive(nestedBundleContentArtifacts(objcProvider.get(NESTED_BUNDLE))) - .addAll(combinedArchitectureBinary.asSet()) - .addAll(infoplistMerging.getPlistWithEverything().asSet()) - .addTransitive(mergeZips) - .addAll(BundleableFile.toArtifacts(extraBundleFiles)) - .addAll(BundleableFile.toArtifacts(objcProvider.get(BUNDLE_FILE))) - .addAll(Xcdatamodel.outputZips(objcProvider.get(XCDATAMODEL))) - .build(); + NestedSet<Artifact> mergeZips = getMergeZips(actoolzipOutput); + NestedSetBuilder<Artifact> bundleContentArtifactsBuilder = + NestedSetBuilder.<Artifact>stableOrder() + .addTransitive(nestedBundleContentArtifacts(objcProvider.get(NESTED_BUNDLE))) + .addAll(combinedArchitectureBinary.asSet()) + .addAll(infoplistMerging.getPlistWithEverything().asSet()) + .addTransitive(mergeZips) + .addAll(BundleableFile.toArtifacts(objcProvider.get(BUNDLE_FILE))); + + Set<String> bundlePaths = new HashSet<>(); + for (Artifact stringsFile : objcProvider.get(STRINGS)) { + Artifact binaryStrings = intermediateArtifacts.convertedStringsFile(stringsFile); + BundleableFile bundleFile = new BundleableFile( + binaryStrings, BundleableFile.flatBundlePath(stringsFile.getExecPath())); + if (bundlePaths.add(bundleFile.getBundlePath())) { + // Filter files that would map to the same location. Files can have the same bundle path + // for various illegal reasons and errors are raised for that separately. Otherwise we + // only want a single file for a mapping in the bundle. See + // ReleaseBundlingSupport.validateResources for details. + extraBundleFilesBuilder.add(bundleFile); + bundleContentArtifactsBuilder.add(binaryStrings); + } + } + + ImmutableList<BundleableFile> extraBundleFiles = extraBundleFilesBuilder.build(); + + bundleContentArtifactsBuilder.addAll(BundleableFile.toArtifacts(extraBundleFiles)); return new Bundling(name, bundleDirFormat, combinedArchitectureBinary, extraBundleFiles, - objcProvider, infoplistMerging, actoolzipOutput, bundleContentArtifacts, mergeZips, - primaryBundleId, fallbackBundleId, architecture); + objcProvider, infoplistMerging, actoolzipOutput, bundleContentArtifactsBuilder.build(), + mergeZips, primaryBundleId, fallbackBundleId, architecture); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompiledResourceFile.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompiledResourceFile.java deleted file mode 100644 index df0d09b9f4..0000000000 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/CompiledResourceFile.java +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2014 Google Inc. 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.Function; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; -import com.google.devtools.build.lib.actions.Artifact; - -/** - * Represents a strings file. - */ -public class CompiledResourceFile { - private final Artifact original; - private final BundleableFile bundled; - - private CompiledResourceFile(Artifact original, BundleableFile bundled) { - this.original = Preconditions.checkNotNull(original); - this.bundled = Preconditions.checkNotNull(bundled); - } - - /** - * The checked-in version of the bundled file. - */ - public Artifact getOriginal() { - return original; - } - - public BundleableFile getBundled() { - return bundled; - } - - public static final Function<CompiledResourceFile, BundleableFile> TO_BUNDLED = - new Function<CompiledResourceFile, BundleableFile>() { - @Override - public BundleableFile apply(CompiledResourceFile input) { - return input.bundled; - } - }; - - /** - * Given a sequence of artifacts corresponding to {@code .strings} files, returns a sequence of - * the same length of instances of this class. The value returned by {@link #getBundled()} of each - * instance will be the plist file in binary form. - */ - public static Iterable<CompiledResourceFile> fromStringsFiles( - IntermediateArtifacts intermediateArtifacts, Iterable<Artifact> strings) { - ImmutableList.Builder<CompiledResourceFile> result = new ImmutableList.Builder<>(); - for (Artifact originalFile : strings) { - Artifact binaryFile = intermediateArtifacts.convertedStringsFile(originalFile); - result.add(new CompiledResourceFile( - originalFile, - new BundleableFile( - binaryFile, BundleableFile.flatBundlePath(originalFile.getExecPath())))); - } - return result.build(); - } -} 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 index 348e771fed..0b4e5d6032 100644 --- 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 @@ -14,6 +14,9 @@ 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; @@ -78,9 +81,8 @@ public abstract class IosTest implements RuleConfiguredTargetFactory { } XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder(); - NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.<Artifact>stableOrder() - .addTransitive(common.getStoryboards().getOutputZips()) - .addAll(Xcdatamodel.outputZips(common.getDatamodels())); + NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.stableOrder(); + addResourceFilesToBuild(ruleContext, common.getObjcProvider(), filesToBuild); XcodeProductType productType; ExtraLinkArgs extraLinkArgs; @@ -133,10 +135,10 @@ public abstract class IosTest implements RuleConfiguredTargetFactory { .registerActions() .addXcodeSettings(xcodeProviderBuilder) .addFilesToBuild(filesToBuild) + .validateResources() .validateAttributes(); new ResourceSupport(ruleContext) - .registerActions(common.getStoryboards()) .validateAttributes() .addXcodeSettings(xcodeProviderBuilder); @@ -151,6 +153,20 @@ public abstract class IosTest implements RuleConfiguredTargetFactory { return create(ruleContext, common, xcodeProviderBuilder.build(), filesToBuild.build()); } + private void addResourceFilesToBuild( + RuleContext ruleContext, ObjcProvider objcProvider, NestedSetBuilder<Artifact> filesToBuild) { + IntermediateArtifacts intermediateArtifacts = + ObjcRuleClasses.intermediateArtifacts(ruleContext); + + Iterable<Xcdatamodel> xcdatamodels = + Xcdatamodels.xcdatamodels(intermediateArtifacts, objcProvider.get(XCDATAMODEL)); + filesToBuild.addAll(Xcdatamodel.outputZips(xcdatamodels)); + + for (Artifact storyboard : objcProvider.get(STORYBOARD)) { + filesToBuild.add(intermediateArtifacts.compiledStoryboardZip(storyboard)); + } + } + protected static boolean isXcTest(RuleContext ruleContext) { return ruleContext.attributes().get(IS_XCTEST, Type.BOOLEAN); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcActionsBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcActionsBuilder.java index ec7fc86f33..4b1868a21d 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcActionsBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcActionsBuilder.java @@ -30,7 +30,6 @@ import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_FRAMEWOR import static com.google.devtools.build.lib.rules.objc.ObjcProvider.WEAK_SDK_FRAMEWORK; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XCASSETS_DIR; -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; import com.google.common.base.Optional; import com.google.common.base.Preconditions; @@ -50,7 +49,6 @@ 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.config.BuildConfiguration; import com.google.devtools.build.lib.util.LazyString; -import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.xcode.xcodegen.proto.XcodeGenProtos; @@ -98,8 +96,8 @@ final class ObjcActionsBuilder { static final PathFragment IBTOOL = new PathFragment(IosSdkCommands.IBTOOL_PATH); static final PathFragment DSYMUTIL = new PathFragment(BIN_DIR + "/dsymutil"); static final PathFragment LIPO = new PathFragment(BIN_DIR + "/lipo"); - static final ImmutableList<String> CLANG_COVERAGE_FLAGS = ImmutableList.<String>of( - "-fprofile-arcs", "-ftest-coverage", "-fprofile-dir=./coverage_output"); + static final ImmutableList<String> CLANG_COVERAGE_FLAGS = + ImmutableList.of("-fprofile-arcs", "-ftest-coverage", "-fprofile-dir=./coverage_output"); // TODO(bazel-team): Reference a rule target rather than a jar file when Darwin runfiles work // better. @@ -270,70 +268,6 @@ final class ObjcActionsBuilder { .build(context)); } - /** - * Creates actions to convert all files specified by the strings attribute into binary format. - */ - private static Iterable<Action> convertStringsActions( - ActionConstructionContext context, - ObjcRuleClasses.Tools baseTools, - StringsFiles stringsFiles) { - ImmutableList.Builder<Action> result = new ImmutableList.Builder<>(); - for (CompiledResourceFile stringsFile : stringsFiles) { - final Artifact original = stringsFile.getOriginal(); - final Artifact bundled = stringsFile.getBundled().getBundled(); - result.add(new SpawnAction.Builder() - .setMnemonic("ConvertStringsPlist") - .setExecutable(baseTools.plmerge()) - .setCommandLine(new CommandLine() { - @Override - public Iterable<String> arguments() { - return ImmutableList.of("--source_file", original.getExecPathString(), - "--out_file", bundled.getExecPathString()); - } - }) - .addInput(original) - .addOutput(bundled) - .build(context)); - } - return result.build(); - } - - /** - * Creates actions to convert all files specified by the xibs attribute into nib format. - */ - private Iterable<Action> convertXibsActions(ObjcRuleClasses.Tools baseTools, XibFiles xibFiles) { - ImmutableList.Builder<Action> result = new ImmutableList.Builder<>(); - for (Artifact original : xibFiles) { - Artifact zipOutput = intermediateArtifacts.compiledXibFileZip(original); - String archiveRoot = BundleableFile.flatBundlePath( - FileSystemUtils.replaceExtension(original.getExecPath(), ".nib")); - result.add(spawnJavaOnDarwinActionBuilder(baseTools.ibtoolzipDeployJar()) - .setMnemonic("XibCompile") - .setCommandLine(new CustomCommandLine.Builder() - // The next three arguments are positional, i.e. they don't have flags before them. - .addPath(zipOutput.getExecPath()) - .add(archiveRoot) - .addPath(IBTOOL) - - .add("--minimum-deployment-target").add(objcConfiguration.getMinimumOs()) - .addPath(original.getExecPath()) - .build()) - .addOutput(zipOutput) - .addInput(original) - .build(context)); - } - return result.build(); - } - - /** - * Outputs of an {@code actool} action besides the zip file. - */ - static final class ExtraActoolOutputs extends IterableWrapper<Artifact> { - ExtraActoolOutputs(Artifact... extraActoolOutputs) { - super(extraActoolOutputs); - } - } - static final class ExtraActoolArgs extends IterableWrapper<String> { ExtraActoolArgs(Iterable<String> args) { super(args); @@ -401,44 +335,6 @@ final class ObjcActionsBuilder { }; } - @VisibleForTesting - static Iterable<String> commonMomczipArguments(ObjcConfiguration configuration) { - return ImmutableList.of( - "-XD_MOMC_SDKROOT=" + IosSdkCommands.sdkDir(configuration), - "-XD_MOMC_IOS_TARGET_VERSION=" + configuration.getMinimumOs(), - "-MOMC_PLATFORMS", configuration.getPlatform().getLowerCaseNameInPlist(), - "-XD_MOMC_TARGET_VERSION=10.6"); - } - - private static Iterable<Action> momczipActions(ActionConstructionContext context, - ObjcRuleClasses.Tools baseTools, final ObjcConfiguration objcConfiguration, - Iterable<Xcdatamodel> datamodels) { - ImmutableList.Builder<Action> result = new ImmutableList.Builder<>(); - for (Xcdatamodel datamodel : datamodels) { - final Artifact outputZip = datamodel.getOutputZip(); - final String archiveRoot = datamodel.archiveRootForMomczip(); - final String container = datamodel.getContainer().getSafePathString(); - result.add(spawnJavaOnDarwinActionBuilder(baseTools.momczipDeployJar()) - .setMnemonic("MomCompile") - .addOutput(outputZip) - .addInputs(datamodel.getInputs()) - .setCommandLine(new CommandLine() { - @Override - public Iterable<String> arguments() { - return new ImmutableList.Builder<String>() - .add(outputZip.getExecPathString()) - .add(archiveRoot) - .add(IosSdkCommands.MOMC_PATH) - .addAll(commonMomczipArguments(objcConfiguration)) - .add(container) - .build(); - } - }) - .build(context)); - } - return result.build(); - } - private static final String FRAMEWORK_SUFFIX = ".framework"; /** @@ -473,15 +369,6 @@ final class ObjcActionsBuilder { } /* - * Returns an ExtraLinkArgs with the parameter prepended to this instance's contents. This - * function does not modify this instance. - */ - @CheckReturnValue - public ExtraLinkArgs prependedWith(Iterable<String> extraLinkArgs) { - return new ExtraLinkArgs(Iterables.concat(extraLinkArgs, this)); - } - - /* * Returns an ExtraLinkArgs with the parameter appended to this instance's contents. This * function does not modify this instance. */ @@ -492,10 +379,6 @@ final class ObjcActionsBuilder { } static final class ExtraLinkInputs extends IterableWrapper<Artifact> { - ExtraLinkInputs(Iterable<Artifact> inputs) { - super(inputs); - } - ExtraLinkInputs(Artifact... inputs) { super(inputs); } @@ -593,22 +476,6 @@ final class ObjcActionsBuilder { .build(context)); } - static final class StringsFiles extends IterableWrapper<CompiledResourceFile> { - StringsFiles(Iterable<CompiledResourceFile> files) { - super(files); - } - } - - /** - * Registers actions for resource conversion. - */ - void registerResourceActions(ObjcRuleClasses.Tools baseTools, StringsFiles stringsFiles, - XibFiles xibFiles, Iterable<Xcdatamodel> datamodels) { - registerAll(convertStringsActions(context, baseTools, stringsFiles)); - registerAll(convertXibsActions(baseTools, xibFiles)); - registerAll(momczipActions(context, baseTools, objcConfiguration, datamodels)); - } - static LazyString joinExecPaths(final Iterable<Artifact> artifacts) { return new LazyString() { @Override 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 1de38f13a5..1c8f7c1faa 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 @@ -47,11 +47,11 @@ public class ObjcBundleLibrary implements RuleConfiguredTargetFactory { // asset catalogs compilation (actool). new BundleSupport(ruleContext, ImmutableSet.of(TargetDeviceFamily.IPHONE), bundling) .registerActions(common.getObjcProvider()) + .validateResources(common.getObjcProvider()) .addXcodeSettings(xcodeProviderBuilder); new ResourceSupport(ruleContext) .validateAttributes() - .registerActions(common.getStoryboards()) .addXcodeSettings(xcodeProviderBuilder); new XcodeSupport(ruleContext) diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java index 65ddb991a6..50a080f26d 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java @@ -31,13 +31,15 @@ import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIB import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INCLUDE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LINKED_BINARY; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.MERGE_ZIP; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_DYLIB; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_FRAMEWORK; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SOURCE; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STORYBOARD; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STRINGS; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.WEAK_SDK_FRAMEWORK; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XCASSETS_DIR; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XCDATAMODEL; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XIB; import static com.google.devtools.build.lib.vfs.PathFragment.TO_PATH_FRAGMENT; import com.google.common.annotations.VisibleForTesting; @@ -336,8 +338,6 @@ public final class ObjcCommon { .addTransitiveAndPropagate(depObjcProviders) .addTransitiveWithoutPropagating(directDepObjcProviders); - Storyboards storyboards; - Iterable<Xcdatamodel> datamodels; if (compilationAttributes.isPresent()) { CompilationAttributes attributes = compilationAttributes.get(); ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(context); @@ -357,31 +357,21 @@ public final class ObjcCommon { if (resourceAttributes.isPresent()) { ResourceAttributes attributes = resourceAttributes.get(); - storyboards = Storyboards.fromInputs(attributes.storyboards(), intermediateArtifacts); - datamodels = Xcdatamodels.xcdatamodels(intermediateArtifacts, attributes.datamodels()); - Iterable<CompiledResourceFile> compiledResources = - CompiledResourceFile.fromStringsFiles(intermediateArtifacts, attributes.strings()); - XibFiles xibFiles = new XibFiles(attributes.xibs()); - objcProvider - .addTransitiveAndPropagate(MERGE_ZIP, storyboards.getOutputZips()) - .addAll(MERGE_ZIP, xibFiles.compiledZips(intermediateArtifacts)) - .addAll(GENERAL_RESOURCE_FILE, storyboards.getInputs()) + .addAll(GENERAL_RESOURCE_FILE, attributes.storyboards()) .addAll(GENERAL_RESOURCE_FILE, attributes.resources()) .addAll(GENERAL_RESOURCE_FILE, attributes.strings()) .addAll(GENERAL_RESOURCE_FILE, attributes.xibs()) .addAll(BUNDLE_FILE, BundleableFile.flattenedRawResourceFiles(attributes.resources())) .addAll(BUNDLE_FILE, BundleableFile.structuredRawResourceFiles(attributes.structuredResources())) - .addAll(BUNDLE_FILE, - Iterables.transform(compiledResources, CompiledResourceFile.TO_BUNDLED)) .addAll(XCASSETS_DIR, uniqueContainers(attributes.assetCatalogs(), ASSET_CATALOG_CONTAINER_TYPE)) .addAll(ASSET_CATALOG, attributes.assetCatalogs()) - .addAll(XCDATAMODEL, datamodels); - } else { - storyboards = Storyboards.empty(); - datamodels = ImmutableList.of(); + .addAll(XCDATAMODEL, attributes.datamodels()) + .addAll(XIB, attributes.xibs()) + .addAll(STRINGS, attributes.strings()) + .addAll(STORYBOARD, attributes.storyboards()); } for (CompilationArtifacts artifacts : compilationArtifacts.asSet()) { @@ -423,8 +413,7 @@ public final class ObjcCommon { objcProvider.addAll(LINKED_BINARY, linkedBinary.asSet()); - return new ObjcCommon( - context, objcProvider.build(), storyboards, datamodels, compilationArtifacts); + return new ObjcCommon(context, objcProvider.build(), compilationArtifacts); } } @@ -436,21 +425,15 @@ public final class ObjcCommon { static final FileType FRAMEWORK_CONTAINER_TYPE = FileType.of(".framework"); private final RuleContext context; private final ObjcProvider objcProvider; - private final Storyboards storyboards; - private final Iterable<Xcdatamodel> datamodels; private final Optional<CompilationArtifacts> compilationArtifacts; private ObjcCommon( RuleContext context, ObjcProvider objcProvider, - Storyboards storyboards, - Iterable<Xcdatamodel> datamodels, Optional<CompilationArtifacts> compilationArtifacts) { this.context = Preconditions.checkNotNull(context); this.objcProvider = Preconditions.checkNotNull(objcProvider); - this.storyboards = Preconditions.checkNotNull(storyboards); - this.datamodels = Preconditions.checkNotNull(datamodels); this.compilationArtifacts = Preconditions.checkNotNull(compilationArtifacts); } @@ -463,22 +446,6 @@ public final class ObjcCommon { } /** - * Returns all storyboards declared in this rule (not including others in the transitive - * dependency tree). - */ - public Storyboards getStoryboards() { - return storyboards; - } - - /** - * Returns all datamodels declared in this rule (not including others in the transitive - * dependency tree). - */ - public Iterable<Xcdatamodel> getDatamodels() { - return datamodels; - } - - /** * Returns an {@link Optional} containing the compiled {@code .a} file, or * {@link Optional#absent()} if this object contains no {@link CompilationArtifacts} or the * compilation information has no sources. @@ -606,8 +573,6 @@ public final class ObjcCommon { Optional<J2ObjcSrcsProvider> maybeJ2ObjcSrcsProvider) { NestedSet<Artifact> allFilesToBuild = NestedSetBuilder.<Artifact>stableOrder() .addTransitive(filesToBuild) - .addTransitive(storyboards.getOutputZips()) - .addAll(Xcdatamodel.outputZips(datamodels)) .build(); RunfilesProvider runfilesProvider = RunfilesProvider.withData( diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcImport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcImport.java index 631def29c4..6c4bf2290a 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcImport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcImport.java @@ -52,7 +52,6 @@ public class ObjcImport implements RuleConfiguredTargetFactory { .validateAttributes(); new ResourceSupport(ruleContext) - .registerActions(common.getStoryboards()) .validateAttributes() .addXcodeSettings(xcodeProviderBuilder); diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java index 2271f4931f..36fed31bc3 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java @@ -94,7 +94,6 @@ public class ObjcLibrary implements RuleConfiguredTargetFactory { .validateAttributes(); new ResourceSupport(ruleContext) - .registerActions(common.getStoryboards()) .validateAttributes() .addXcodeSettings(xcodeProviderBuilder); diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java index c121980bed..e559ab4e35 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java @@ -125,7 +125,7 @@ public final class ObjcProvider implements TransitiveInfoProvider { public static final Key<String> SDK_DYLIB = new Key<>(STABLE_ORDER); public static final Key<SdkFramework> SDK_FRAMEWORK = new Key<>(STABLE_ORDER); public static final Key<SdkFramework> WEAK_SDK_FRAMEWORK = new Key<>(STABLE_ORDER); - public static final Key<Xcdatamodel> XCDATAMODEL = new Key<>(STABLE_ORDER); + public static final Key<Artifact> XCDATAMODEL = new Key<>(STABLE_ORDER); public static final Key<Flag> FLAG = new Key<>(STABLE_ORDER); /** @@ -159,6 +159,21 @@ public final class ObjcProvider implements TransitiveInfoProvider { public static final Key<Artifact> DEBUG_SYMBOLS = new Key<>(STABLE_ORDER); /** + * Artifacts for storyboard sources. + */ + public static final Key<Artifact> STORYBOARD = new Key<>(STABLE_ORDER); + + /** + * Artifacts for .xib file sources. + */ + public static final Key<Artifact> XIB = new Key<>(STABLE_ORDER); + + /** + * Artifacts for strings source files. + */ + public static final Key<Artifact> STRINGS = new Key<>(STABLE_ORDER); + + /** * Flags that apply to a transitive build dependency tree. Each item in the enum corresponds to a * flag. If the item is included in the key {@link #FLAG}, then the flag is considered set. */ 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 5167696e30..20567cbedb 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 @@ -406,8 +406,6 @@ public class ObjcRuleClasses { .direct_compile_time_input() .allowedRuleClasses("objc_bundle", "objc_bundle_library") .allowedFileTypes()) - .add(attr("$momczip_deploy", LABEL).cfg(HOST) - .value(env.getLabel("//tools/objc:momczip_deploy.jar"))) .build(); } @Override @@ -793,6 +791,8 @@ public class ObjcRuleClasses { <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/ .add(attr("infoplist", LABEL) .allowedFileTypes(PLIST_TYPE)) + .add(attr("$momczip_deploy", LABEL).cfg(HOST) + .value(env.getLabel("//tools/objc:momczip_deploy.jar"))) .build(); } @Override @@ -954,21 +954,9 @@ public class ObjcRuleClasses { return ruleContext.getPrerequisiteArtifact("$actoolzip_deploy", Mode.HOST); } - Artifact ibtoolzipDeployJar() { - return ruleContext.getPrerequisiteArtifact("$ibtoolzip_deploy", Mode.HOST); - } - - Artifact momczipDeployJar() { - return ruleContext.getPrerequisiteArtifact("$momczip_deploy", Mode.HOST); - } - FilesToRunProvider xcodegen() { return ruleContext.getExecutablePrerequisite("$xcodegen", Mode.HOST); } - - FilesToRunProvider plmerge() { - return ruleContext.getExecutablePrerequisite("$plmerge", Mode.HOST); - } } } 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 index 636eac4bab..2086298acd 100644 --- 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 @@ -197,6 +197,17 @@ public final class ReleaseBundlingSupport { } /** + * 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.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 @@ -231,8 +242,8 @@ public final class ReleaseBundlingSupport { private Artifact registerBundleSigningActions(Artifact ipaOutput) { PathFragment entitlementsDirectory = ruleContext.getUniqueDirectory("entitlements"); - Artifact teamPrefixFile = ruleContext.getRelatedArtifact( - entitlementsDirectory, ".team_prefix_file"); + Artifact teamPrefixFile = + ruleContext.getRelatedArtifact(entitlementsDirectory, ".team_prefix_file"); registerExtractTeamPrefixAction(teamPrefixFile); Artifact entitlementsNeedingSubstitution = attributes.entitlements(); @@ -241,8 +252,8 @@ public final class ReleaseBundlingSupport { entitlementsDirectory, ".entitlements_with_variables"); registerExtractEntitlementsAction(entitlementsNeedingSubstitution); } - Artifact entitlements = ruleContext.getRelatedArtifact( - entitlementsDirectory, ".entitlements"); + Artifact entitlements = + ruleContext.getRelatedArtifact(entitlementsDirectory, ".entitlements"); registerEntitlementsVariableSubstitutionAction( entitlementsNeedingSubstitution, entitlements, teamPrefixFile); Artifact ipaUnsigned = ObjcRuleClasses.artifactByAppendingToRootRelativePath( @@ -382,7 +393,7 @@ public final class ReleaseBundlingSupport { // Architecture that determines which nested bundles are kept. .setArchitecture(objcConfiguration.getDependencySingleArchitecture()) .setBundleDirFormat(bundleDirFormat) - .setExtraBundleFiles(extraBundleFiles) + .addExtraBundleFiles(extraBundleFiles) .setObjcProvider(objcProvider) .setInfoplistMerging( BundleSupport.infoPlistMerging(ruleContext, objcProvider, optionsProvider)) diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java index 10a1f2e41a..af98af5dce 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java @@ -72,6 +72,7 @@ public abstract class ReleaseBundlingTargetFactory implements RuleConfiguredTarg .registerActions() .addXcodeSettings(xcodeProviderBuilder) .addFilesToBuild(filesToBuild) + .validateResources() .validateAttributes(); XcodeSupport xcodeSupport = new XcodeSupport(ruleContext) diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ResourceSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ResourceSupport.java index 4a279d2a72..d3614a56ad 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ResourceSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ResourceSupport.java @@ -18,7 +18,6 @@ import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.analysis.RuleContext; -import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; /** * Support for resource processing on Objc rules. @@ -28,8 +27,6 @@ import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; final class ResourceSupport { private final RuleContext ruleContext; private final Attributes attributes; - private final IntermediateArtifacts intermediateArtifacts; - private final Iterable<Xcdatamodel> datamodels; /** * Creates a new resource support for the given context. @@ -37,57 +34,6 @@ final class ResourceSupport { ResourceSupport(RuleContext ruleContext) { this.ruleContext = ruleContext; this.attributes = new Attributes(ruleContext); - this.intermediateArtifacts = ObjcRuleClasses.intermediateArtifacts(ruleContext); - this.datamodels = Xcdatamodels.xcdatamodels(intermediateArtifacts, attributes.datamodels()); - } - - /** - * Registers resource generating actions (strings, storyboards, ...). - * - * @param storyboards storyboards defined by this rule - * - * @return this resource support - */ - ResourceSupport registerActions(Storyboards storyboards) { - ObjcActionsBuilder actionsBuilder = ObjcRuleClasses.actionsBuilder(ruleContext); - - ObjcRuleClasses.Tools tools = new ObjcRuleClasses.Tools(ruleContext); - actionsBuilder.registerResourceActions( - tools, - new ObjcActionsBuilder.StringsFiles( - CompiledResourceFile.fromStringsFiles(intermediateArtifacts, attributes.strings())), - new XibFiles(attributes.xibs()), - datamodels); - - registerInterfaceBuilderActions(storyboards, tools); - return this; - } - - private void registerInterfaceBuilderActions( - Storyboards storyboards, ObjcRuleClasses.Tools tools) { - for (Artifact storyboardInput : storyboards.getInputs()) { - String archiveRoot = BundleableFile.flatBundlePath(storyboardInput.getExecPath()) + "c"; - Artifact zipOutput = intermediateArtifacts.compiledStoryboardZip(storyboardInput); - - String minimumOs = - ruleContext.getConfiguration().getFragment(ObjcConfiguration.class).getMinimumOs(); - ruleContext.registerAction( - ObjcActionsBuilder.spawnJavaOnDarwinActionBuilder(tools.ibtoolzipDeployJar()) - .setMnemonic("StoryboardCompile") - .setCommandLine(new CustomCommandLine.Builder() - // The next three arguments are positional, - // i.e. they don't have flags before them. - .addPath(zipOutput.getExecPath()) - .add(archiveRoot) - .addPath(ObjcActionsBuilder.IBTOOL) - - .add("--minimum-deployment-target").add(minimumOs) - .addPath(storyboardInput.getExecPath()) - .build()) - .addOutput(zipOutput) - .addInput(storyboardInput) - .build(ruleContext)); - } } /** @@ -96,7 +42,8 @@ final class ResourceSupport { * @return this resource support */ ResourceSupport addXcodeSettings(XcodeProvider.Builder xcodeProviderBuilder) { - xcodeProviderBuilder.addInputsToXcodegen(Xcdatamodel.inputsToXcodegen(datamodels)); + xcodeProviderBuilder.addInputsToXcodegen(Xcdatamodel.inputsToXcodegen(attributes.datamodels())); + xcodeProviderBuilder.addDatamodelDirs(Xcdatamodels.datamodelDirs(attributes.datamodels())); return this; } @@ -132,16 +79,6 @@ final class ResourceSupport { return ruleContext.getPrerequisiteArtifacts("datamodels", Mode.TARGET).list(); } - ImmutableList<Artifact> xibs() { - return ruleContext.getPrerequisiteArtifacts("xibs", Mode.TARGET) - .errorsForNonMatching(ObjcRuleClasses.XIB_TYPE) - .list(); - } - - ImmutableList<Artifact> strings() { - return ruleContext.getPrerequisiteArtifacts("strings", Mode.TARGET).list(); - } - ImmutableList<Artifact> assetCatalogs() { return ruleContext.getPrerequisiteArtifacts("asset_catalogs", Mode.TARGET).list(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/Xcdatamodel.java b/src/main/java/com/google/devtools/build/lib/rules/objc/Xcdatamodel.java index ef2c1fa5a5..ff8601cb96 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/Xcdatamodel.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/Xcdatamodel.java @@ -64,15 +64,13 @@ class Xcdatamodel extends Value<Xcdatamodel> { /** * Returns the files that should be supplied to Xcodegen when generating a project that includes - * all of the given xcdatamodels. + * all of the given xcdatamodel source files. */ - public static Iterable<Artifact> inputsToXcodegen(Iterable<Xcdatamodel> datamodels) { + public static Iterable<Artifact> inputsToXcodegen(Iterable<Artifact> datamodelFiles) { ImmutableSet.Builder<Artifact> inputs = new ImmutableSet.Builder<>(); - for (Xcdatamodel datamodel : datamodels) { - for (Artifact generalInput : datamodel.inputs) { - if (generalInput.getExecPath().getBaseName().equals(".xccurrentversion")) { - inputs.add(generalInput); - } + for (Artifact generalInput : datamodelFiles) { + if (generalInput.getExecPath().getBaseName().equals(".xccurrentversion")) { + inputs.add(generalInput); } } return inputs.build(); diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/Xcdatamodels.java b/src/main/java/com/google/devtools/build/lib/rules/objc/Xcdatamodels.java index 32d48aa696..340c77533a 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/Xcdatamodels.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/Xcdatamodels.java @@ -34,6 +34,14 @@ class Xcdatamodels { static final ImmutableList<FileType> CONTAINER_TYPES = ImmutableList.of(FileType.of(".xcdatamodeld"), FileType.of(".xcdatamodel")); + static Iterable<PathFragment> datamodelDirs(Iterable<Artifact> xcdatamodels) { + ImmutableSet.Builder<PathFragment> result = new ImmutableSet.Builder<>(); + for (Collection<Artifact> artifacts : byContainer(xcdatamodels).asMap().values()) { + result.addAll(ObjcCommon.uniqueContainers(artifacts, FileType.of(".xcdatamodel"))); + } + return result.build(); + } + static Iterable<Xcdatamodel> xcdatamodels( IntermediateArtifacts intermediateArtifacts, Iterable<Artifact> xcdatamodels) { ImmutableSet.Builder<Xcdatamodel> result = new ImmutableSet.Builder<>(); diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeProvider.java index ac20c8ea8a..07c61f2ed2 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeProvider.java @@ -24,7 +24,6 @@ import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_DYLIB; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_FRAMEWORK; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.WEAK_SDK_FRAMEWORK; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XCASSETS_DIR; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XCDATAMODEL; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; @@ -33,6 +32,7 @@ import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.devtools.build.lib.actions.Artifact; @@ -83,6 +83,7 @@ public final class XcodeProvider implements TransitiveInfoProvider { private final NestedSetBuilder<Artifact> additionalSources = NestedSetBuilder.stableOrder(); private final ImmutableList.Builder<XcodeProvider> extensions = new ImmutableList.Builder<>(); private String architecture; + private ImmutableList.Builder<PathFragment> datamodelDirs = new ImmutableList.Builder<>(); /** * Sets the label of the build target which corresponds to this Xcode target. @@ -246,6 +247,11 @@ public final class XcodeProvider implements TransitiveInfoProvider { return this; } + public Builder addDatamodelDirs(Iterable<PathFragment> datamodelDirs) { + this.datamodelDirs.addAll(datamodelDirs); + return this; + } + public XcodeProvider build() { Preconditions.checkState( !testHost.isPresent() || (productType == XcodeProductType.UNIT_TEST), @@ -324,6 +330,7 @@ public final class XcodeProvider implements TransitiveInfoProvider { private final NestedSet<Artifact> additionalSources; private final ImmutableList<XcodeProvider> extensions; private final String architecture; + private final ImmutableList<PathFragment> datamodelDirs; private XcodeProvider(Builder builder) { this.label = Preconditions.checkNotNull(builder.label); @@ -343,28 +350,7 @@ public final class XcodeProvider implements TransitiveInfoProvider { this.additionalSources = builder.additionalSources.build(); this.extensions = builder.extensions.build(); this.architecture = Preconditions.checkNotNull(builder.architecture); - } - - /** - * Creates a builder whose values are all initialized to this provider. - */ - public Builder toBuilder() { - Builder builder = new Builder(); - builder.label = label; - builder.userHeaderSearchPaths.addAll(userHeaderSearchPaths); - builder.headerSearchPaths.addTransitive(headerSearchPaths); - builder.infoplistMerging = infoplistMerging; - builder.dependencies.addTransitive(dependencies); - builder.xcodeprojBuildSettings.addAll(xcodeprojBuildSettings); - builder.copts.addAll(copts); - builder.productType = productType; - builder.headers.addAll(headers); - builder.compilationArtifacts = compilationArtifacts; - builder.objcProvider = objcProvider; - builder.testHost = testHost; - builder.inputsToXcodegen.addTransitive(inputsToXcodegen); - builder.extensions.addAll(extensions); - return builder; + this.datamodelDirs = builder.datamodelDirs.build(); } private void collectProviders(Set<XcodeProvider> allProviders) { @@ -422,8 +408,7 @@ public final class XcodeProvider implements TransitiveInfoProvider { .addAllSdkFramework(SdkFramework.names(objcProvider.get(SDK_FRAMEWORK))) .addAllFramework(PathFragment.safePathStrings(objcProvider.get(FRAMEWORK_DIR))) .addAllXcassetsDir(PathFragment.safePathStrings(objcProvider.get(XCASSETS_DIR))) - .addAllXcdatamodel(PathFragment.safePathStrings( - Xcdatamodel.xcdatamodelDirs(objcProvider.get(XCDATAMODEL)))) + .addAllXcdatamodel(PathFragment.safePathStrings(datamodelDirs)) .addAllBundleImport(PathFragment.safePathStrings(objcProvider.get(BUNDLE_IMPORT_DIR))) .addAllSdkDylib(objcProvider.get(SDK_DYLIB)) .addAllGeneralResourceFile(Artifact.toExecPaths(objcProvider.get(GENERAL_RESOURCE_FILE))) |