diff options
author | 2015-03-18 22:13:59 +0000 | |
---|---|---|
committer | 2015-03-20 14:33:19 +0000 | |
commit | 35200df5ba6ad7558fbf7a9b33bfd63c934e9ce4 (patch) | |
tree | 45af4ad6bd8bec8ba5c445fbdfa7892543c218bf /src/main/java/com/google | |
parent | e7bfc7eba33fe9670559aef1f955bc8610dafc98 (diff) |
Prevent clashing xcode targets for multiple architectures.
Without this change we create a xcode target for each combination (target, architecture)
which causes the xcode project generation to blow up: Xcode transparently handles
architectures. Eventually we want to match Xcode's behaviour but for now we export just
a single architecture's xcode targets which should allow developers to work in xcode as
before while preserving multi-architecture compilation for IPAs in blaze.
--
MOS_MIGRATED_REVID=88973190
Diffstat (limited to 'src/main/java/com/google')
3 files changed, 46 insertions, 13 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibrary.java index fee926e243..221baa7dee 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibrary.java @@ -168,12 +168,15 @@ public class ObjcProtoLibrary implements RuleConfiguredTargetFactory { .addHeaders(protoGeneratedSources) .build(); + ObjcConfiguration configuration = ObjcRuleClasses.objcConfiguration(ruleContext); + Iterable<XcodeProvider> protoDeps = ruleContext.getPrerequisites( + ObjcProtoLibraryRule.LIBPROTOBUF_ATTR, Mode.TARGET, XcodeProvider.class); XcodeProvider xcodeProvider = new XcodeProvider.Builder() .setLabel(ruleContext.getLabel()) + .setArchitecture(configuration.getIosCpu()) .addUserHeaderSearchPaths(searchPathEntries) - .addDependencies(ruleContext.getPrerequisites( - ObjcProtoLibraryRule.LIBPROTOBUF_ATTR, Mode.TARGET, XcodeProvider.class)) - .addCopts(ObjcRuleClasses.objcConfiguration(ruleContext).getCopts()) + .addDependencies(protoDeps, configuration) + .addCopts(configuration.getCopts()) .setProductType(LIBRARY_STATIC) .addHeaders(protoGeneratedHeaders) .setCompilationArtifacts(common.getCompilationArtifacts().get()) 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 b064b2c836..1ef52104cb 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 @@ -48,6 +48,7 @@ import com.google.devtools.build.xcode.xcodegen.proto.XcodeGenProtos.XcodeprojBu import java.util.Arrays; import java.util.EnumSet; import java.util.LinkedHashSet; +import java.util.List; import java.util.Set; /** @@ -79,6 +80,7 @@ public final class XcodeProvider implements TransitiveInfoProvider { private final NestedSetBuilder<Artifact> inputsToXcodegen = NestedSetBuilder.stableOrder(); private final NestedSetBuilder<Artifact> additionalSources = NestedSetBuilder.stableOrder(); private final ImmutableList.Builder<XcodeProvider> extensions = new ImmutableList.Builder<>(); + private String architecture; /** * Sets the label of the build target which corresponds to this Xcode target. @@ -129,7 +131,9 @@ public final class XcodeProvider implements TransitiveInfoProvider { * Adds {@link XcodeProvider}s corresponding to direct dependencies of this target which should * be added in the {@code .xcodeproj} file. */ - public Builder addDependencies(Iterable<XcodeProvider> dependencies) { + public Builder addDependencies( + Iterable<XcodeProvider> dependencies, ObjcConfiguration configuration) { + String architecture = getDependencyArchitecture(configuration); for (XcodeProvider dependency : dependencies) { // TODO(bazel-team): This is messy. Maybe we should make XcodeProvider be able to specify // how to depend on it rather than require this method to choose based on the dependency's @@ -137,7 +141,7 @@ public final class XcodeProvider implements TransitiveInfoProvider { if (dependency.productType == XcodeProductType.EXTENSION) { this.extensions.add(dependency); this.inputsToXcodegen.addTransitive(dependency.inputsToXcodegen); - } else { + } else if (dependency.architecture.equals(architecture)) { this.dependencies.add(dependency); this.dependencies.addTransitive(dependency.dependencies); this.addTransitiveSets(dependency); @@ -147,6 +151,22 @@ public final class XcodeProvider implements TransitiveInfoProvider { } /** + * Returns the architecture for which we keep dependencies. + * + * <p>When building with multiple architectures we want to avoid duplicating the same target for + * each architecture. Instead we pick one architecture for which to keep all dependencies and + * discard any others. + */ + private String getDependencyArchitecture(ObjcConfiguration configuration) { + List<String> iosMultiCpus = configuration.getIosMultiCpus(); + String architecture = configuration.getIosCpu(); + if (!iosMultiCpus.isEmpty()) { + architecture = iosMultiCpus.get(0); + } + return architecture; + } + + /** * Adds additional build settings of this target. */ public Builder addXcodeprojBuildSettings( @@ -231,8 +251,17 @@ public final class XcodeProvider implements TransitiveInfoProvider { return this; } + /** + * Sets the CPU architecture this xcode target was constructed for, derived from + * {@link ObjcConfiguration#getIosCpu()}. + */ + public Builder setArchitecture(String architecture) { + this.architecture = architecture; + return this; + } + public XcodeProvider build() { - Preconditions.checkArgument( + Preconditions.checkState( !testHost.isPresent() || (productType == XcodeProductType.UNIT_TEST), "%s product types cannot have a test host (test host: %s).", productType, testHost); return new XcodeProvider(this); @@ -272,10 +301,6 @@ public final class XcodeProvider implements TransitiveInfoProvider { return inputsToXcodegen; } - public ImmutableList<XcodeProvider> getTopLevelTargets() { - return topLevelTargets; - } - /** * Returns all the target controls that must be added to the xcodegen control. No other target * controls are needed to generate a functional project file. This method creates a new list @@ -312,6 +337,7 @@ public final class XcodeProvider implements TransitiveInfoProvider { private final NestedSet<Artifact> inputsToXcodegen; private final NestedSet<Artifact> additionalSources; private final ImmutableList<XcodeProvider> extensions; + private final String architecture; private XcodeProvider(Builder builder) { this.label = Preconditions.checkNotNull(builder.label); @@ -330,6 +356,7 @@ public final class XcodeProvider implements TransitiveInfoProvider { this.inputsToXcodegen = builder.inputsToXcodegen.build(); this.additionalSources = builder.additionalSources.build(); this.extensions = builder.extensions.build(); + this.architecture = Preconditions.checkNotNull(builder.architecture); } /** diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeSupport.java index 16cc88bb1e..e176346570 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeSupport.java @@ -95,6 +95,7 @@ public final class XcodeSupport { ObjcProvider objcProvider, XcodeProductType productType) { xcodeProviderBuilder .setLabel(ruleContext.getLabel()) + .setArchitecture(ObjcRuleClasses.objcConfiguration(ruleContext).getIosCpu()) .setObjcProvider(objcProvider) .setProductType(productType); return this; @@ -106,9 +107,11 @@ public final class XcodeSupport { * @return this xcode support */ XcodeSupport addDependencies(Builder xcodeProviderBuilder, Attribute attribute) { - xcodeProviderBuilder.addDependencies( - ruleContext.getPrerequisites( - attribute.getName(), attribute.getAccessMode(), XcodeProvider.class)); + Iterable<XcodeProvider> dependencies = ruleContext.getPrerequisites( + attribute.getName(), attribute.getAccessMode(), XcodeProvider.class); + + xcodeProviderBuilder + .addDependencies(dependencies, ObjcRuleClasses.objcConfiguration(ruleContext)); return this; } } |