diff options
14 files changed, 670 insertions, 365 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java index bc26cf74ed..ec64b37603 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java @@ -15,6 +15,7 @@ package com.google.devtools.build.lib.rules.objc; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; import com.google.devtools.build.lib.actions.Artifact; @@ -37,10 +38,8 @@ import com.google.devtools.build.lib.rules.apple.AppleConfiguration.Configuratio import com.google.devtools.build.lib.rules.apple.Platform.PlatformType; import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider; import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs; -import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes; import com.google.devtools.build.lib.rules.objc.ProtoSupport.TargetType; -import com.google.devtools.build.lib.vfs.PathFragment; import java.util.List; import java.util.Set; @@ -113,18 +112,21 @@ public class AppleBinary implements RuleConfiguredTargetFactory { archivesToLipo.add(common.getCompilationArtifacts().get().getArchive().get()); binariesToLipo.add(intermediateArtifacts.strippedSingleArchitectureBinary()); - ProtoSupport protoSupport = new ProtoSupport(ruleContext, TargetType.LINKING_TARGET); - Iterable<PathFragment> priorityHeaders; ObjcConfiguration objcConfiguration = childConfig.getFragment(ObjcConfiguration.class); if (objcConfiguration.experimentalAutoTopLevelUnionObjCProtos()) { - protoSupport.registerActions(); - priorityHeaders = protoSupport.getUserHeaderSearchPaths(); - } else { - priorityHeaders = ImmutableList.of(); + ProtoSupport protoSupport = + new ProtoSupport(ruleContext, TargetType.LINKING_TARGET).registerActions(); + + ObjcCommon protoCommon = protoSupport.getCommon(); + new CompilationSupport( + ruleContext, + protoSupport.getIntermediateArtifacts(), + new CompilationAttributes.Builder().build()) + .registerCompileAndArchiveActions(protoCommon, protoSupport.getUserHeaderSearchPaths()); } new CompilationSupport(ruleContext, childConfig) - .registerCompileAndArchiveActions(common, priorityHeaders) + .registerCompileAndArchiveActions(common) .registerLinkActions( common.getObjcProvider(), j2ObjcMappingFileProvider, @@ -162,32 +164,31 @@ public class AppleBinary implements RuleConfiguredTargetFactory { CompilationArtifacts compilationArtifacts = CompilationSupport.compilationArtifacts(ruleContext, intermediateArtifacts); + Optional<Artifact> protoLib; ObjcConfiguration objcConfiguration = buildConfiguration.getFragment(ObjcConfiguration.class); if (objcConfiguration.experimentalAutoTopLevelUnionObjCProtos()) { ProtoSupport protoSupport = new ProtoSupport(ruleContext, TargetType.LINKING_TARGET); - compilationArtifacts = - new CompilationArtifacts.Builder() - .setPchFile(compilationArtifacts.getPchFile()) - .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) - .addAllSources(compilationArtifacts) - .addAllSources(protoSupport.getCompilationArtifacts()) - .build(); + protoLib = protoSupport.getCommon().getCompiledArchive(); + } else { + protoLib = Optional.absent(); } return new ObjcCommon.Builder(ruleContext, buildConfiguration) - .setCompilationAttributes(new CompilationAttributes(ruleContext)) - .setCompilationArtifacts(compilationArtifacts) - .setResourceAttributes(new ResourceAttributes(ruleContext)) - .addDefines(ruleContext.getTokenizedStringListAttr("defines")) - .addDeps(propagatedDeps) - .addDepObjcProviders( - ruleContext.getPrerequisites("bundles", Mode.TARGET, ObjcProvider.class)) - .addNonPropagatedDepObjcProviders(nonPropagatedObjcDeps) - .setIntermediateArtifacts(intermediateArtifacts) - .setAlwayslink(false) - .setHasModuleMap() - .setLinkedBinary(intermediateArtifacts.strippedSingleArchitectureBinary()) - .build(); + .setCompilationAttributes( + CompilationAttributes.Builder.fromRuleContext(ruleContext).build()) + .setCompilationArtifacts(compilationArtifacts) + .setResourceAttributes(new ResourceAttributes(ruleContext)) + .addDefines(ruleContext.getTokenizedStringListAttr("defines")) + .addDeps(propagatedDeps) + .addDepObjcProviders( + ruleContext.getPrerequisites("bundles", Mode.TARGET, ObjcProvider.class)) + .addNonPropagatedDepObjcProviders(nonPropagatedObjcDeps) + .setIntermediateArtifacts(intermediateArtifacts) + .setAlwayslink(false) + .setHasModuleMap() + .setLinkedBinary(intermediateArtifacts.strippedSingleArchitectureBinary()) + .addExtraImportLibraries(protoLib.asSet()) + .build(); } private <T> List<T> nullToEmptyList(List<T> inputList) { 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 9a981d5086..7ee2cc8fb6 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 @@ -33,12 +33,10 @@ import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.rules.apple.AppleConfiguration; import com.google.devtools.build.lib.rules.apple.Platform; import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs; -import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes; import com.google.devtools.build.lib.rules.objc.ProtoSupport.TargetType; import com.google.devtools.build.lib.rules.objc.ReleaseBundlingSupport.LinkedBinary; import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; -import com.google.devtools.build.lib.vfs.PathFragment; /** * Implementation for rules that link binaries. @@ -83,16 +81,6 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder(); - ProtoSupport protoSupport = new ProtoSupport(ruleContext, TargetType.LINKING_TARGET); - Iterable<PathFragment> priorityHeaders; - ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); - if (objcConfiguration.experimentalAutoTopLevelUnionObjCProtos()) { - protoSupport.registerActions().addXcodeProviderOptions(xcodeProviderBuilder); - priorityHeaders = protoSupport.getUserHeaderSearchPaths(); - } else { - priorityHeaders = ImmutableList.of(); - } - IntermediateArtifacts intermediateArtifacts = ObjcRuleClasses.intermediateArtifacts(ruleContext); @@ -113,9 +101,24 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory ruleContext.getPrerequisites("deps", Mode.TARGET, J2ObjcEntryClassProvider.class)) .build(); + ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); + if (objcConfiguration.experimentalAutoTopLevelUnionObjCProtos()) { + ProtoSupport protoSupport = + new ProtoSupport(ruleContext, TargetType.LINKING_TARGET) + .registerActions() + .addXcodeProviderOptions(xcodeProviderBuilder); + + ObjcCommon protoCommon = protoSupport.getCommon(); + new CompilationSupport( + ruleContext, + protoSupport.getIntermediateArtifacts(), + new CompilationAttributes.Builder().build()) + .registerCompileAndArchiveActions(protoCommon, protoSupport.getUserHeaderSearchPaths()); + } + CompilationSupport compilationSupport = new CompilationSupport(ruleContext) - .registerCompileAndArchiveActions(common, priorityHeaders) + .registerCompileAndArchiveActions(common) .registerFullyLinkAction(common.getObjcProvider()) .addXcodeSettings(xcodeProviderBuilder, common) .registerLinkActions( @@ -212,20 +215,10 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory CompilationArtifacts compilationArtifacts = CompilationSupport.compilationArtifacts(ruleContext); - if (ObjcRuleClasses.objcConfiguration(ruleContext).experimentalAutoTopLevelUnionObjCProtos()) { - ProtoSupport protoSupport = new ProtoSupport(ruleContext, TargetType.LINKING_TARGET); - compilationArtifacts = - new CompilationArtifacts.Builder() - .setPchFile(compilationArtifacts.getPchFile()) - .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) - .addAllSources(compilationArtifacts) - .addAllSources(protoSupport.getCompilationArtifacts()) - .build(); - } - ObjcCommon.Builder builder = new ObjcCommon.Builder(ruleContext) - .setCompilationAttributes(new CompilationAttributes(ruleContext)) + .setCompilationAttributes( + CompilationAttributes.Builder.fromRuleContext(ruleContext).build()) .setCompilationArtifacts(compilationArtifacts) .setResourceAttributes(new ResourceAttributes(ruleContext)) .addDefines(ruleContext.getTokenizedStringListAttr("defines")) @@ -248,6 +241,11 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory builder.setLinkmapFile(intermediateArtifacts.linkmap()); } + if (ObjcRuleClasses.objcConfiguration(ruleContext).experimentalAutoTopLevelUnionObjCProtos()) { + ProtoSupport protoSupport = new ProtoSupport(ruleContext, TargetType.LINKING_TARGET); + builder.addExtraImportLibraries(protoSupport.getCommon().getCompiledArchive().asSet()); + } + return builder.build(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationAttributes.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationAttributes.java new file mode 100644 index 0000000000..f41b101c2f --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationAttributes.java @@ -0,0 +1,480 @@ +// Copyright 2016 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.devtools.build.lib.rules.objc; + +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.TOP_LEVEL_MODULE_MAP; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.PrerequisiteArtifacts; +import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; +import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.cmdline.Label; +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.BuildType; +import com.google.devtools.build.lib.rules.cpp.CcCommon; +import com.google.devtools.build.lib.rules.cpp.CppModuleMap; +import com.google.devtools.build.lib.syntax.Type; +import com.google.devtools.build.lib.util.Pair; +import com.google.devtools.build.lib.vfs.PathFragment; + +import java.util.List; + +/** + * Provides a way to access attributes that are common to all compilation rules. + */ +// TODO(bazel-team): Delete and move into support-specific attributes classes once ObjcCommon is +// gone. +final class CompilationAttributes { + static class Builder { + private final NestedSetBuilder<Artifact> hdrs = NestedSetBuilder.stableOrder(); + private final NestedSetBuilder<Artifact> textualHdrs = NestedSetBuilder.stableOrder(); + private final NestedSetBuilder<PathFragment> includes = NestedSetBuilder.stableOrder(); + private final NestedSetBuilder<PathFragment> sdkIncludes = NestedSetBuilder.stableOrder(); + private final NestedSetBuilder<String> copts = NestedSetBuilder.stableOrder(); + private final NestedSetBuilder<String> linkopts = NestedSetBuilder.stableOrder(); + private final NestedSetBuilder<CppModuleMap> moduleMapsForDirectDeps = + NestedSetBuilder.stableOrder(); + private final NestedSetBuilder<SdkFramework> sdkFrameworks = NestedSetBuilder.stableOrder(); + private final NestedSetBuilder<SdkFramework> weakSdkFrameworks = NestedSetBuilder.stableOrder(); + private final NestedSetBuilder<String> sdkDylibs = NestedSetBuilder.stableOrder(); + private Optional<Artifact> bridgingHeader = Optional.absent(); + private Optional<PathFragment> packageFragment = Optional.absent(); + private boolean enableModules; + + /** + * Adds the default values available through the rule's context. + */ + static Builder fromRuleContext(RuleContext ruleContext) { + Builder builder = new Builder(); + + addHeadersFromRuleContext(builder, ruleContext); + addIncludesFromRuleContext(builder, ruleContext); + addSdkAttributesFromRuleContext(builder, ruleContext); + addCompileOptionsFromRuleContext(builder, ruleContext); + addModuleOptionsFromRuleContext(builder, ruleContext); + + return builder; + } + + /** + * Adds headers to be made available for dependents. + */ + public Builder addHdrs(NestedSet<Artifact> hdrs) { + this.hdrs.addTransitive(hdrs); + return this; + } + + /** + * Adds headers that cannot be compiled individually. + */ + public Builder addTextualHdrs(NestedSet<Artifact> textualHdrs) { + this.textualHdrs.addTransitive(textualHdrs); + return this; + } + + /** + * Adds include paths to be made available for compilation. + */ + public Builder addIncludes(NestedSet<PathFragment> includes) { + this.includes.addTransitive(includes); + return this; + } + + /** + * Adds paths for SDK includes. + */ + public Builder addSdkIncludes(NestedSet<PathFragment> sdkIncludes) { + this.sdkIncludes.addTransitive(sdkIncludes); + return this; + } + + /** + * Adds compile-time options. + */ + public Builder addCopts(NestedSet<String> copts) { + this.copts.addTransitive(copts); + return this; + } + + /** + * Adds link-time options. + */ + public Builder addLinkopts(NestedSet<String> linkopts) { + this.linkopts.addTransitive(linkopts); + return this; + } + + /** + * Adds clang module maps for direct dependencies of the rule. These are needed to generate + * module maps. + */ + public Builder addModuleMapsForDirectDeps(NestedSet<CppModuleMap> moduleMapsForDirectDeps) { + this.moduleMapsForDirectDeps.addTransitive(moduleMapsForDirectDeps); + return this; + } + + /** + * Adds SDK frameworks to link against. + */ + public Builder addSdkFrameworks(NestedSet<SdkFramework> sdkFrameworks) { + this.sdkFrameworks.addTransitive(sdkFrameworks); + return this; + } + + /** + * Adds SDK frameworks to be linked weakly. + */ + public Builder addWeakSdkFrameworks(NestedSet<SdkFramework> weakSdkFrameworks) { + this.weakSdkFrameworks.addTransitive(weakSdkFrameworks); + return this; + } + + /** + * Adds SDK Dylibs to link against. + */ + public Builder addSdkDylibs(NestedSet<String> sdkDylibs) { + this.sdkDylibs.addTransitive(sdkDylibs); + return this; + } + + /** + * Sets the bridging header to be used when compiling Swift sources. + */ + public Builder setBridgingHeader(Artifact bridgingHeader) { + Preconditions.checkState( + !this.bridgingHeader.isPresent(), + "bridgingHeader is already set to %s", + this.bridgingHeader); + this.bridgingHeader = Optional.of(bridgingHeader); + return this; + } + + /** + * Sets the package path from which to base the header search paths. + */ + public Builder setPackageFragment(PathFragment packageFragment) { + Preconditions.checkState( + !this.packageFragment.isPresent(), + "packageFragment is already set to %s", + this.packageFragment); + this.packageFragment = Optional.of(packageFragment); + return this; + } + + /** + * Enables the usage of clang modules maps during compilation. + */ + public Builder enableModules() { + this.enableModules = true; + return this; + } + + /** + * Builds a {@code CompilationAttributes} object. + */ + public CompilationAttributes build() { + return new CompilationAttributes( + this.hdrs.build(), + this.textualHdrs.build(), + this.bridgingHeader, + this.includes.build(), + this.sdkIncludes.build(), + this.sdkFrameworks.build(), + this.weakSdkFrameworks.build(), + this.sdkDylibs.build(), + this.packageFragment, + this.copts.build(), + this.linkopts.build(), + this.moduleMapsForDirectDeps.build(), + this.enableModules); + } + + private static void addHeadersFromRuleContext(Builder builder, RuleContext ruleContext) { + if (ruleContext.attributes().has("hdrs", BuildType.LABEL_LIST)) { + NestedSetBuilder<Artifact> headers = NestedSetBuilder.stableOrder(); + for (Pair<Artifact, Label> header : CcCommon.getHeaders(ruleContext)) { + headers.add(header.first); + } + builder.addHdrs(headers.build()); + } + + if (ruleContext.attributes().has("textual_hdrs", BuildType.LABEL_LIST)) { + builder.addTextualHdrs( + PrerequisiteArtifacts.nestedSet(ruleContext, "textual_hdrs", Mode.TARGET)); + } + + if (ruleContext.attributes().has("bridging_header", BuildType.LABEL)) { + Artifact header = ruleContext.getPrerequisiteArtifact("bridging_header", Mode.TARGET); + if (header != null) { + builder.setBridgingHeader(header); + } + } + } + + private static void addIncludesFromRuleContext(Builder builder, RuleContext ruleContext) { + if (ruleContext.attributes().has("includes", Type.STRING_LIST)) { + NestedSetBuilder<PathFragment> includes = NestedSetBuilder.stableOrder(); + includes.addAll( + Iterables.transform( + ruleContext.attributes().get("includes", Type.STRING_LIST), + PathFragment.TO_PATH_FRAGMENT)); + builder.addIncludes(includes.build()); + } + + if (ruleContext.attributes().has("sdk_includes", Type.STRING_LIST)) { + NestedSetBuilder<PathFragment> sdkIncludes = NestedSetBuilder.stableOrder(); + sdkIncludes.addAll( + Iterables.transform( + ruleContext.attributes().get("sdk_includes", Type.STRING_LIST), + PathFragment.TO_PATH_FRAGMENT)); + builder.addSdkIncludes(sdkIncludes.build()); + } + } + + private static void addSdkAttributesFromRuleContext(Builder builder, RuleContext ruleContext) { + if (ruleContext.attributes().has("sdk_frameworks", Type.STRING_LIST)) { + NestedSetBuilder<SdkFramework> frameworks = NestedSetBuilder.stableOrder(); + // TODO(bazel-team): Move the inclusion of the default frameworks to CompilationSupport. + frameworks.addAll(ObjcRuleClasses.AUTOMATIC_SDK_FRAMEWORKS); + for (String explicit : ruleContext.attributes().get("sdk_frameworks", Type.STRING_LIST)) { + frameworks.add(new SdkFramework(explicit)); + } + builder.addSdkFrameworks(frameworks.build()); + } + + if (ruleContext.attributes().has("weak_sdk_frameworks", Type.STRING_LIST)) { + NestedSetBuilder<SdkFramework> weakFrameworks = NestedSetBuilder.stableOrder(); + for (String frameworkName : + ruleContext.attributes().get("weak_sdk_frameworks", Type.STRING_LIST)) { + weakFrameworks.add(new SdkFramework(frameworkName)); + } + builder.addWeakSdkFrameworks(weakFrameworks.build()); + } + + if (ruleContext.attributes().has("sdk_dylibs", Type.STRING_LIST)) { + NestedSetBuilder<String> sdkDylibs = NestedSetBuilder.stableOrder(); + sdkDylibs.addAll(ruleContext.attributes().get("sdk_dylibs", Type.STRING_LIST)); + builder.addSdkDylibs(sdkDylibs.build()); + } + } + + private static void addCompileOptionsFromRuleContext(Builder builder, RuleContext ruleContext) { + if (ruleContext.attributes().has("copts", Type.STRING_LIST)) { + NestedSetBuilder<String> copts = NestedSetBuilder.stableOrder(); + copts.addAll(ruleContext.getTokenizedStringListAttr("copts")); + builder.addCopts(copts.build()); + } + + if (ruleContext.attributes().has("linkopts", Type.STRING_LIST)) { + NestedSetBuilder<String> linkopts = NestedSetBuilder.stableOrder(); + linkopts.addAll(ruleContext.getTokenizedStringListAttr("linkopts")); + builder.addLinkopts(linkopts.build()); + } + } + + private static void addModuleOptionsFromRuleContext(Builder builder, RuleContext ruleContext) { + NestedSetBuilder<CppModuleMap> moduleMaps = NestedSetBuilder.stableOrder(); + ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); + if (objcConfiguration.moduleMapsEnabled()) { + // Make sure all dependencies that have headers are included here. If a module map is + // missing, its private headers will be treated as public! + if (ruleContext.attributes().has("deps", BuildType.LABEL_LIST)) { + Iterable<ObjcProvider> providers = + ruleContext.getPrerequisites("deps", Mode.TARGET, ObjcProvider.class); + for (ObjcProvider provider : providers) { + moduleMaps.addTransitive(provider.get(TOP_LEVEL_MODULE_MAP)); + } + } + if (ruleContext.attributes().has("non_propagated_deps", BuildType.LABEL_LIST)) { + Iterable<ObjcProvider> providers = + ruleContext.getPrerequisites("non_propagated_deps", Mode.TARGET, ObjcProvider.class); + for (ObjcProvider provider : providers) { + moduleMaps.addTransitive(provider.get(TOP_LEVEL_MODULE_MAP)); + } + } + } + + builder.addModuleMapsForDirectDeps(moduleMaps.build()); + + PathFragment packageFragment = + ruleContext.getLabel().getPackageIdentifier().getPathFragment(); + if (packageFragment != null) { + builder.setPackageFragment(packageFragment); + } + + if (ruleContext.attributes().has("enable_modules", Type.BOOLEAN) + && ruleContext.attributes().get("enable_modules", Type.BOOLEAN)) { + builder.enableModules(); + } + } + } + + private final NestedSet<Artifact> hdrs; + private final NestedSet<Artifact> textualHdrs; + private final Optional<Artifact> bridgingHeader; + private final NestedSet<PathFragment> includes; + private final NestedSet<PathFragment> sdkIncludes; + private final NestedSet<SdkFramework> sdkFrameworks; + private final NestedSet<SdkFramework> weakSdkFrameworks; + private final NestedSet<String> sdkDylibs; + private final Optional<PathFragment> packageFragment; + private final NestedSet<String> copts; + private final NestedSet<String> linkopts; + private final NestedSet<CppModuleMap> moduleMapsForDirectDeps; + private final boolean enableModules; + + private CompilationAttributes( + NestedSet<Artifact> hdrs, + NestedSet<Artifact> textualHdrs, + Optional<Artifact> bridgingHeader, + NestedSet<PathFragment> includes, + NestedSet<PathFragment> sdkIncludes, + NestedSet<SdkFramework> sdkFrameworks, + NestedSet<SdkFramework> weakSdkFrameworks, + NestedSet<String> sdkDylibs, + Optional<PathFragment> packageFragment, + NestedSet<String> copts, + NestedSet<String> linkopts, + NestedSet<CppModuleMap> moduleMapsForDirectDeps, + boolean enableModules) { + this.hdrs = hdrs; + this.textualHdrs = textualHdrs; + this.bridgingHeader = bridgingHeader; + this.includes = includes; + this.sdkIncludes = sdkIncludes; + this.sdkFrameworks = sdkFrameworks; + this.weakSdkFrameworks = weakSdkFrameworks; + this.sdkDylibs = sdkDylibs; + this.packageFragment = packageFragment; + this.copts = copts; + this.linkopts = linkopts; + this.moduleMapsForDirectDeps = moduleMapsForDirectDeps; + this.enableModules = enableModules; + } + + /** + * Returns the headers to be made available for dependents. + */ + public NestedSet<Artifact> hdrs() { + return this.hdrs; + } + + /** + * Returns the headers that cannot be compiled individually. + */ + public NestedSet<Artifact> textualHdrs() { + return this.textualHdrs; + } + + /** + * Returns the bridging header to be used when compiling Swift sources. + */ + public Optional<Artifact> bridgingHeader() { + return this.bridgingHeader; + } + + /** + * Returns the include paths to be made available for compilation. + */ + public NestedSet<PathFragment> includes() { + return this.includes; + } + + /** + * Returns the paths for SDK includes. + */ + public NestedSet<PathFragment> sdkIncludes() { + return this.sdkIncludes; + } + + /** + * Returns the SDK frameworks to link against. + */ + public NestedSet<SdkFramework> sdkFrameworks() { + return this.sdkFrameworks; + } + + /** + * Returns the SDK frameworks to be linked weakly. + */ + public NestedSet<SdkFramework> weakSdkFrameworks() { + return this.weakSdkFrameworks; + } + + /** + * Returns the SDK Dylibs to link against. + */ + public NestedSet<String> sdkDylibs() { + return this.sdkDylibs; + } + + /** + * Returns the exec paths of all header search paths that should be added to this target and + * dependers on this target, obtained from the {@code includes} attribute. + */ + public NestedSet<PathFragment> headerSearchPaths(PathFragment genfilesFragment) { + NestedSetBuilder<PathFragment> paths = NestedSetBuilder.stableOrder(); + if (packageFragment.isPresent()) { + List<PathFragment> rootFragments = + ImmutableList.of( + packageFragment.get(), genfilesFragment.getRelative(packageFragment.get())); + + Iterable<PathFragment> relativeIncludes = + Iterables.filter(includes(), Predicates.not(PathFragment.IS_ABSOLUTE)); + for (PathFragment include : relativeIncludes) { + for (PathFragment rootFragment : rootFragments) { + paths.add(rootFragment.getRelative(include).normalize()); + } + } + } + return paths.build(); + } + + /** + * Returns the compile-time options. + */ + public NestedSet<String> copts() { + return this.copts; + } + + /** + * Returns the link-time options. + */ + public NestedSet<String> linkopts() { + return this.linkopts; + } + + /** + * Returns the clang module maps of direct dependencies of this rule. These are needed to generate + * this rule's module map. + */ + public NestedSet<CppModuleMap> moduleMapsForDirectDeps() { + return this.moduleMapsForDirectDeps; + } + + /** + * Returns whether this target uses language features that require clang modules, such as + * {@literal @}import. + */ + public boolean enableModules() { + return this.enableModules; + } +} 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 fb420384c5..632887e02f 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 @@ -85,7 +85,6 @@ import com.google.devtools.build.lib.rules.apple.Platform.PlatformType; import com.google.devtools.build.lib.rules.cpp.CppModuleMap; import com.google.devtools.build.lib.rules.cpp.CppModuleMapAction; import com.google.devtools.build.lib.rules.cpp.LinkerInputs; -import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import com.google.devtools.build.lib.rules.objc.XcodeProvider.Builder; import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector; import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector.InstrumentationSpec; @@ -98,7 +97,6 @@ import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.PathFragment; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Set; @@ -235,7 +233,7 @@ public final class CompilationSupport { static final ImmutableList<String> DEFAULT_COMPILER_FLAGS = ImmutableList.of("-DOS_IOS"); static final ImmutableList<String> DEFAULT_LINKER_FLAGS = ImmutableList.of("-ObjC"); - + /** * Returns information about the given rule's compilation artifacts. */ @@ -243,7 +241,7 @@ public final class CompilationSupport { static CompilationArtifacts compilationArtifacts(RuleContext ruleContext) { return compilationArtifacts(ruleContext, ObjcRuleClasses.intermediateArtifacts(ruleContext)); } - + /** * Returns information about the given rule's compilation artifacts. Dependencies specified * in the current rule's attributes are obtained via {@code ruleContext}. Output locations @@ -277,25 +275,67 @@ public final class CompilationSupport { private final IntermediateArtifacts intermediateArtifacts; /** - * Creates a new compilation support for the given rule. All actions will be created under - * the given build configuration, which may be different than the current rule context - * configuration. + * Creates a new compilation support for the given rule. + */ + public CompilationSupport(RuleContext ruleContext) { + this(ruleContext, ruleContext.getConfiguration()); + } + + /** + * Creates a new compilation support for the given rule. + * + * <p>All actions will be created under the given build configuration, which may be different than + * the current rule context configuration. */ public CompilationSupport(RuleContext ruleContext, BuildConfiguration buildConfiguration) { - this.ruleContext = ruleContext; - this.buildConfiguration = buildConfiguration; - this.objcConfiguration = buildConfiguration.getFragment(ObjcConfiguration.class); - this.appleConfiguration = buildConfiguration.getFragment(AppleConfiguration.class); - this.attributes = new CompilationAttributes(ruleContext); - this.intermediateArtifacts = - ObjcRuleClasses.intermediateArtifacts(ruleContext, buildConfiguration); + this( + ruleContext, + buildConfiguration, + ObjcRuleClasses.intermediateArtifacts(ruleContext, buildConfiguration), + CompilationAttributes.Builder.fromRuleContext(ruleContext).build()); } /** * Creates a new compilation support for the given rule. + * + * <p>The compilation and linking flags will be retrieved from the given compilation attributes. + * The names of the generated artifacts will be retrieved from the given intermediate artifacts. + * + * <p>By instantiating multiple compilation supports for the same rule but with intermediate + * artifacts with different output prefixes, multiple archives can be compiled for the same + * rule context. */ - public CompilationSupport(RuleContext ruleContext) { - this(ruleContext, ruleContext.getConfiguration()); + public CompilationSupport( + RuleContext ruleContext, + IntermediateArtifacts intermediateArtifacts, + CompilationAttributes compilationAttributes) { + this(ruleContext, ruleContext.getConfiguration(), intermediateArtifacts, compilationAttributes); + } + + /** + * Creates a new compilation support for the given rule and build configuration. + * + * <p>All actions will be created under the given build configuration, which may be different than + * the current rule context configuration. + * + * <p>The compilation and linking flags will be retrieved from the given compilation attributes. + * The names of the generated artifacts will be retrieved from the given intermediate artifacts. + * + * <p>By instantiating multiple compilation supports for the same rule but with intermediate + * artifacts with different output prefixes, multiple archives can be compiled for the same + * rule context. + */ + public CompilationSupport( + RuleContext ruleContext, + BuildConfiguration buildConfiguration, + IntermediateArtifacts intermediateArtifacts, + CompilationAttributes compilationAttributes) { + this.ruleContext = ruleContext; + this.buildConfiguration = buildConfiguration; + this.objcConfiguration = buildConfiguration.getFragment(ObjcConfiguration.class); + this.appleConfiguration = buildConfiguration.getFragment(AppleConfiguration.class); + this.attributes = compilationAttributes; + this.intermediateArtifacts = intermediateArtifacts; } /** @@ -1370,9 +1410,9 @@ public final class CompilationSupport { } if (ruleContext.attributes().has("srcs", BuildType.LABEL_LIST)) { - Set<Artifact> hdrsSet = new HashSet<>(attributes.hdrs()); - Set<Artifact> srcsSet = - new HashSet<>(ruleContext.getPrerequisiteArtifacts("srcs", Mode.TARGET).list()); + ImmutableSet<Artifact> hdrsSet = ImmutableSet.copyOf(attributes.hdrs()); + ImmutableSet<Artifact> srcsSet = + ImmutableSet.copyOf(ruleContext.getPrerequisiteArtifacts("srcs", Mode.TARGET).list()); // Check for overlap between srcs and hdrs. for (Artifact header : Sets.intersection(hdrsSet, srcsSet)) { @@ -1382,8 +1422,9 @@ public final class CompilationSupport { } // Check for overlap between srcs and non_arc_srcs. - Set<Artifact> nonArcSrcsSet = - new HashSet<>(ruleContext.getPrerequisiteArtifacts("non_arc_srcs", Mode.TARGET).list()); + ImmutableSet<Artifact> nonArcSrcsSet = + ImmutableSet.copyOf( + ruleContext.getPrerequisiteArtifacts("non_arc_srcs", Mode.TARGET).list()); for (Artifact conflict : Sets.intersection(nonArcSrcsSet, srcsSet)) { String path = conflict.getRootRelativePath().toString(); ruleContext.attributeError( diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalObjcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalObjcLibrary.java index 52dd30ca20..6190ffddd3 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalObjcLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalObjcLibrary.java @@ -31,7 +31,6 @@ import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.Val import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariablesExtension; import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider; import com.google.devtools.build.lib.rules.cpp.PrecompiledFiles; -import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import java.util.Collection; @@ -79,7 +78,7 @@ public class ExperimentalObjcLibrary implements RuleConfiguredTargetFactory { objcProvider, ruleContext.getFragment(AppleConfiguration.class))) { frameworkSequence.addValue(framework); } - builder.addSequence(FRAMEWORKS_VARIABLE_NAME, frameworkSequence.build()); + builder.addSequence(FRAMEWORKS_VARIABLE_NAME, frameworkSequence.build()); } } @@ -89,7 +88,8 @@ public class ExperimentalObjcLibrary implements RuleConfiguredTargetFactory { CompilationArtifacts compilationArtifacts = CompilationSupport.compilationArtifacts(ruleContext); - CompilationAttributes compilationAttributes = new CompilationAttributes(ruleContext); + CompilationAttributes compilationAttributes = + CompilationAttributes.Builder.fromRuleContext(ruleContext).build(); PrecompiledFiles precompiledFiles = new PrecompiledFiles(ruleContext); ObjcCommon common = common(ruleContext, compilationAttributes, compilationArtifacts); 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 7c49f81c0e..150bbe34a1 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 @@ -18,6 +18,7 @@ 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; @@ -35,14 +36,12 @@ import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory. import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.rules.apple.AppleConfiguration; import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs; -import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes; import com.google.devtools.build.lib.rules.objc.ProtoSupport.TargetType; import com.google.devtools.build.lib.rules.objc.ReleaseBundlingSupport.LinkedBinary; import com.google.devtools.build.lib.rules.test.ExecutionInfoProvider; import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; import com.google.devtools.build.lib.syntax.Type; -import com.google.devtools.build.lib.vfs.PathFragment; /** * Implementation for {@code ios_test} rule in Bazel. @@ -100,14 +99,17 @@ public final class IosTest implements RuleConfiguredTargetFactory { NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.stableOrder(); addResourceFilesToBuild(ruleContext, common.getObjcProvider(), filesToBuild); - ProtoSupport protoSupport = new ProtoSupport(ruleContext, TargetType.LINKING_TARGET); - Iterable<PathFragment> priorityHeaders; ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); if (objcConfiguration.experimentalAutoTopLevelUnionObjCProtos()) { - protoSupport.registerActions().addXcodeProviderOptions(xcodeProviderBuilder); - priorityHeaders = protoSupport.getUserHeaderSearchPaths(); - } else { - priorityHeaders = ImmutableList.of(); + ProtoSupport protoSupport = + new ProtoSupport(ruleContext, TargetType.LINKING_TARGET).registerActions(); + + ObjcCommon protoCommon = protoSupport.getCommon(); + new CompilationSupport( + ruleContext, + protoSupport.getIntermediateArtifacts(), + new CompilationAttributes.Builder().build()) + .registerCompileAndArchiveActions(protoCommon, protoSupport.getUserHeaderSearchPaths()); } XcodeProductType productType = getProductType(ruleContext); @@ -161,7 +163,7 @@ public final class IosTest implements RuleConfiguredTargetFactory { extraLinkArgs, extraLinkInputs, DsymOutputType.TEST) - .registerCompileAndArchiveActions(common, priorityHeaders) + .registerCompileAndArchiveActions(common) .registerFullyLinkAction(common.getObjcProvider()) .addXcodeSettings(xcodeProviderBuilder, common) .validateAttributes(); @@ -256,20 +258,19 @@ public final class IosTest implements RuleConfiguredTargetFactory { CompilationArtifacts compilationArtifacts = CompilationSupport.compilationArtifacts(ruleContext); - if (ObjcRuleClasses.objcConfiguration(ruleContext).experimentalAutoTopLevelUnionObjCProtos()) { + Optional<Artifact> protoLib; + ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); + if (objcConfiguration.experimentalAutoTopLevelUnionObjCProtos()) { ProtoSupport protoSupport = new ProtoSupport(ruleContext, TargetType.LINKING_TARGET); - compilationArtifacts = - new CompilationArtifacts.Builder() - .setPchFile(compilationArtifacts.getPchFile()) - .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) - .addAllSources(compilationArtifacts) - .addAllSources(protoSupport.getCompilationArtifacts()) - .build(); + protoLib = protoSupport.getCommon().getCompiledArchive(); + } else { + protoLib = Optional.absent(); } ObjcCommon.Builder builder = new ObjcCommon.Builder(ruleContext) - .setCompilationAttributes(new CompilationAttributes(ruleContext)) + .setCompilationAttributes( + CompilationAttributes.Builder.fromRuleContext(ruleContext).build()) .setCompilationArtifacts(compilationArtifacts) .setResourceAttributes(new ResourceAttributes(ruleContext)) .addDefines(ruleContext.getTokenizedStringListAttr("defines")) @@ -279,6 +280,7 @@ public final class IosTest implements RuleConfiguredTargetFactory { ruleContext.getPrerequisites( "non_propagated_deps", Mode.TARGET, ObjcProvider.class)) .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) + .addExtraImportLibraries(protoLib.asSet()) .setHasModuleMap(); if (isXcTest(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 d15148b1e2..623bde4dd1 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 @@ -58,7 +58,6 @@ import static com.google.devtools.build.lib.vfs.PathFragment.TO_PATH_FRAGMENT; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; -import com.google.common.base.Predicates; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; @@ -69,23 +68,17 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; -import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.packages.BuildType; import com.google.devtools.build.lib.rules.apple.AppleToolchain; -import com.google.devtools.build.lib.rules.cpp.CcCommon; import com.google.devtools.build.lib.rules.cpp.CcLinkParams; import com.google.devtools.build.lib.rules.cpp.CcLinkParamsProvider; import com.google.devtools.build.lib.rules.cpp.CppCompilationContext; import com.google.devtools.build.lib.rules.cpp.CppModuleMap; import com.google.devtools.build.lib.rules.cpp.CppRunfilesProvider; import com.google.devtools.build.lib.rules.cpp.LinkerInputs; -import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.FileType; -import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.PathFragment; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -99,160 +92,6 @@ import java.util.Set; // rule-internal information. Any provider created by a rule should not be read, only published. public final class ObjcCommon { /** - * Provides a way to access attributes that are common to all compilation rules. - */ - // TODO(bazel-team): Delete and move into support-specific attributes classes once ObjcCommon is - // gone. - static final class CompilationAttributes { - private final RuleContext ruleContext; - private final ObjcSdkFrameworks.Attributes sdkFrameworkAttributes; - - CompilationAttributes(RuleContext ruleContext) { - this.ruleContext = Preconditions.checkNotNull(ruleContext); - this.sdkFrameworkAttributes = new ObjcSdkFrameworks.Attributes(ruleContext); - } - - ImmutableList<Artifact> hdrs() { - // Some rules may compile but not have the "hdrs" attribute. - if (!ruleContext.attributes().has("hdrs", BuildType.LABEL_LIST)) { - return ImmutableList.of(); - } - ImmutableList.Builder<Artifact> headers = ImmutableList.builder(); - for (Pair<Artifact, Label> header : CcCommon.getHeaders(ruleContext)) { - headers.add(header.first); - } - return headers.build(); - } - - /** - * Returns headers that cannot be compiled individually. - */ - ImmutableList<Artifact> textualHdrs() { - // Some rules may compile but not have the "textual_hdrs" attribute. - if (!ruleContext.attributes().has("textual_hdrs", BuildType.LABEL_LIST)) { - return ImmutableList.of(); - } - return ruleContext.getPrerequisiteArtifacts("textual_hdrs", Mode.TARGET).list(); - } - - Optional<Artifact> bridgingHeader() { - Artifact header = ruleContext.getPrerequisiteArtifact("bridging_header", Mode.TARGET); - return Optional.fromNullable(header); - } - - Iterable<PathFragment> includes() { - return Iterables.transform( - ruleContext.attributes().get("includes", Type.STRING_LIST), - PathFragment.TO_PATH_FRAGMENT); - } - - Iterable<PathFragment> sdkIncludes() { - return Iterables.transform( - ruleContext.attributes().get("sdk_includes", Type.STRING_LIST), - PathFragment.TO_PATH_FRAGMENT); - } - - /** - * Returns the value of the sdk_frameworks attribute plus frameworks that are included - * automatically. - */ - ImmutableSet<SdkFramework> sdkFrameworks() { - return sdkFrameworkAttributes.sdkFrameworks(); - } - - /** - * Returns the value of the weak_sdk_frameworks attribute. - */ - ImmutableSet<SdkFramework> weakSdkFrameworks() { - return sdkFrameworkAttributes.weakSdkFrameworks(); - } - - /** - * Returns the value of the sdk_dylibs attribute. - */ - ImmutableSet<String> sdkDylibs() { - return sdkFrameworkAttributes.sdkDylibs(); - } - - /** - * Returns the exec paths of all header search paths that should be added to this target and - * dependers on this target, obtained from the {@code includes} attribute. - */ - ImmutableList<PathFragment> headerSearchPaths(PathFragment genfilesFragment) { - ImmutableList.Builder<PathFragment> paths = new ImmutableList.Builder<>(); - PathFragment packageFragment = - ruleContext.getLabel().getPackageIdentifier().getPathFragment(); - List<PathFragment> rootFragments = - ImmutableList.of(packageFragment, genfilesFragment.getRelative(packageFragment)); - - Iterable<PathFragment> relativeIncludes = - Iterables.filter(includes(), Predicates.not(PathFragment.IS_ABSOLUTE)); - for (PathFragment include : relativeIncludes) { - for (PathFragment rootFragment : rootFragments) { - paths.add(rootFragment.getRelative(include).normalize()); - } - } - return paths.build(); - } - - /** - * Returns any values specified in this rule's {@code copts} attribute or an empty list if the - * attribute does not exist or no values are specified. - */ - public Iterable<String> copts() { - return ruleContext.getTokenizedStringListAttr("copts"); - } - - /** - * Returns any values specified in this rule's {@code linkopts} attribute or an empty list if - * the attribute does not exist or no values are specified. - */ - public Iterable<String> linkopts() { - return ruleContext.getTokenizedStringListAttr("linkopts"); - } - - /** - * The clang module maps of direct dependencies of this rule. These are needed to generate - * this rule's module map. - */ - public List<CppModuleMap> moduleMapsForDirectDeps() { - // Make sure all dependencies that have headers are included here. If a module map is missing, - // its private headers will be treated as public! - ArrayList<CppModuleMap> moduleMaps = new ArrayList<>(); - collectModuleMapsFromAttributeIfExists(moduleMaps, "deps"); - collectModuleMapsFromAttributeIfExists(moduleMaps, "non_propagated_deps"); - return moduleMaps; - } - - /** - * Collects all module maps from the targets in a certain attribute and adds them into - * {@code moduleMaps}. - * - * @param moduleMaps an {@link ArrayList} to collect the module maps into - * @param attribute the name of a label list attribute to collect module maps from - */ - private void collectModuleMapsFromAttributeIfExists( - ArrayList<CppModuleMap> moduleMaps, String attribute) { - if (ruleContext.attributes().has(attribute, BuildType.LABEL_LIST)) { - Iterable<ObjcProvider> providers = - ruleContext.getPrerequisites(attribute, Mode.TARGET, ObjcProvider.class); - for (ObjcProvider provider : providers) { - moduleMaps.addAll(provider.get(TOP_LEVEL_MODULE_MAP).toCollection()); - } - } - } - - /** - * Returns whether this target uses language features that require clang modules, such as - * {@literal @}import. - */ - public boolean enableModules() { - return ruleContext.attributes().has("enable_modules", Type.BOOLEAN) - && ruleContext.attributes().get("enable_modules", Type.BOOLEAN); - } - } - - /** * Provides a way to access attributes that are common to all resources rules. */ // TODO(bazel-team): Delete and move into support-specific attributes classes once ObjcCommon is diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFramework.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFramework.java index 67c0fa80dc..e28b5e5636 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFramework.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFramework.java @@ -26,7 +26,6 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.rules.objc.ObjcCommon.Builder; -import com.google.devtools.build.lib.rules.objc.ObjcSdkFrameworks.Attributes; import com.google.devtools.build.lib.syntax.Type; /** @@ -36,13 +35,14 @@ public class ObjcFramework implements RuleConfiguredTargetFactory { @Override public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException, RuleErrorException { - Attributes sdkFrameworkAttributes = new Attributes(ruleContext); + CompilationAttributes compilationAttributes = + CompilationAttributes.Builder.fromRuleContext(ruleContext).build(); ObjcCommon.Builder commonBuilder = new Builder(ruleContext) - .addExtraSdkFrameworks(sdkFrameworkAttributes.sdkFrameworks()) - .addExtraWeakSdkFrameworks(sdkFrameworkAttributes.weakSdkFrameworks()) - .addExtraSdkDylibs(sdkFrameworkAttributes.sdkDylibs()); + .addExtraSdkFrameworks(compilationAttributes.sdkFrameworks()) + .addExtraWeakSdkFrameworks(compilationAttributes.weakSdkFrameworks()) + .addExtraSdkDylibs(compilationAttributes.sdkDylibs()); ImmutableList<Artifact> frameworkImports = ruleContext.getPrerequisiteArtifacts("framework_imports", Mode.TARGET).list(); diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFrameworkRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFrameworkRule.java index 9f264f9d4a..0fba5ca20d 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFrameworkRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFrameworkRule.java @@ -33,6 +33,7 @@ public class ObjcFrameworkRule implements RuleDefinition { @Override public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) { return builder + .requiresConfigurationFragments(ObjcConfiguration.class) /* <!-- #BLAZE_RULE(objc_framework).ATTRIBUTE(framework_imports) --> The list of files under a <code>.framework</code> directory which are provided to Objective-C targets that depend on this target. 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 b1c10f75fc..0ef0aa8159 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 @@ -24,7 +24,6 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; -import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes; import com.google.devtools.build.lib.syntax.Type; @@ -37,7 +36,8 @@ public class ObjcImport implements RuleConfiguredTargetFactory { throws InterruptedException, RuleErrorException { ObjcCommon common = new ObjcCommon.Builder(ruleContext) - .setCompilationAttributes(new CompilationAttributes(ruleContext)) + .setCompilationAttributes( + CompilationAttributes.Builder.fromRuleContext(ruleContext).build()) .setResourceAttributes(new ResourceAttributes(ruleContext)) .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) .setAlwayslink(ruleContext.attributes().get("alwayslink", Type.BOOLEAN)) 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 b7a3faa9ae..54134cac69 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 @@ -29,7 +29,6 @@ import com.google.devtools.build.lib.rules.cpp.CcLinkParamsProvider; import com.google.devtools.build.lib.rules.cpp.CcLinkParamsStore; import com.google.devtools.build.lib.rules.cpp.LinkerInputs; import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink; -import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes; import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; import com.google.devtools.build.lib.syntax.Type; @@ -71,7 +70,8 @@ public class ObjcLibrary implements RuleConfiguredTargetFactory { */ private ObjcCommon common(RuleContext ruleContext) { return new ObjcCommon.Builder(ruleContext) - .setCompilationAttributes(new CompilationAttributes(ruleContext)) + .setCompilationAttributes( + CompilationAttributes.Builder.fromRuleContext(ruleContext).build()) .setResourceAttributes(new ResourceAttributes(ruleContext)) .addDefines(ruleContext.getTokenizedStringListAttr("defines")) .setCompilationArtifacts(CompilationSupport.compilationArtifacts(ruleContext)) 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 79cfb1d20c..89d420b2da 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 @@ -32,14 +32,12 @@ public class ObjcProtoLibrary implements RuleConfiguredTargetFactory { @Override public ConfiguredTarget create(final RuleContext ruleContext) throws InterruptedException, RuleErrorException { - ObjcCommon.Builder commonBuilder = new ObjcCommon.Builder(ruleContext); XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder(); NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.stableOrder(); ProtoSupport protoSupport = new ProtoSupport(ruleContext, TargetType.PROTO_TARGET) .validate() - .addCommonOptions(commonBuilder) .addXcodeProviderOptions(xcodeProviderBuilder) .addFilesToBuild(filesToBuild) .registerActions(); @@ -48,7 +46,7 @@ public class ObjcProtoLibrary implements RuleConfiguredTargetFactory { return null; } - ObjcCommon common = commonBuilder.build(); + ObjcCommon common = protoSupport.getCommon(); filesToBuild.addAll(common.getCompiledArchive().asSet()); @@ -67,9 +65,7 @@ public class ObjcProtoLibrary implements RuleConfiguredTargetFactory { // If the experimental flag is not set, or if it's set and doesn't use the protobuf library, // register the compilation actions, as the output needs to be linked in the final binary. if (!experimentalAutoUnion || !usesProtobufLibrary) { - new CompilationSupport(ruleContext) - .registerCompileAndArchiveActions(common) - .registerFullyLinkAction(common.getObjcProvider()); + new CompilationSupport(ruleContext).registerCompileAndArchiveActions(common); } return ObjcRuleClasses.ruleConfiguredTarget(ruleContext, filesToBuild.build()) diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcSdkFrameworks.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcSdkFrameworks.java deleted file mode 100644 index 8ca09cfae9..0000000000 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcSdkFrameworks.java +++ /dev/null @@ -1,71 +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.common.collect.ImmutableSet; -import com.google.devtools.build.lib.analysis.RuleContext; -import com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.SdkFrameworksDependerRule; -import com.google.devtools.build.lib.syntax.Type; - -/** - * Common logic for rules that inherit from {@link SdkFrameworksDependerRule}. - */ -public class ObjcSdkFrameworks { - - /** - * Class that handles extraction and processing of attributes common to inheritors of {@link - * SdkFrameworksDependerRule}. - */ - public static class Attributes { - - private final RuleContext ruleContext; - - public Attributes(RuleContext ruleContext) { - this.ruleContext = ruleContext; - } - - /** - * Returns the SDK frameworks defined on the rule's {@code sdk_frameworks} attribute as well as - * base frameworks defined in {@link ObjcRuleClasses#AUTOMATIC_SDK_FRAMEWORKS}. - */ - ImmutableSet<SdkFramework> sdkFrameworks() { - ImmutableSet.Builder<SdkFramework> result = new ImmutableSet.Builder<>(); - result.addAll(ObjcRuleClasses.AUTOMATIC_SDK_FRAMEWORKS); - for (String explicit : ruleContext.attributes().get("sdk_frameworks", Type.STRING_LIST)) { - result.add(new SdkFramework(explicit)); - } - return result.build(); - } - - /** - * Returns all SDK frameworks defined on the rule's {@code weak_sdk_frameworks} attribute. - */ - ImmutableSet<SdkFramework> weakSdkFrameworks() { - ImmutableSet.Builder<SdkFramework> result = new ImmutableSet.Builder<>(); - for (String frameworkName : - ruleContext.attributes().get("weak_sdk_frameworks", Type.STRING_LIST)) { - result.add(new SdkFramework(frameworkName)); - } - return result.build(); - } - - /** - * Returns all SDK dylibs defined on the rule's {@code sdk_dylibs} attribute. - */ - ImmutableSet<String> sdkDylibs() { - return ImmutableSet.copyOf(ruleContext.attributes().get("sdk_dylibs", Type.STRING_LIST)); - } - } -} diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ProtoSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ProtoSupport.java index 7d441ecd78..5ee93099ab 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ProtoSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ProtoSupport.java @@ -118,6 +118,7 @@ final class ProtoSupport { private final RuleContext ruleContext; private final Attributes attributes; private final TargetType targetType; + private final IntermediateArtifacts intermediateArtifacts; /** * Creates a new proto support. @@ -129,6 +130,15 @@ final class ProtoSupport { this.ruleContext = ruleContext; this.attributes = new Attributes(ruleContext); this.targetType = targetType; + if (targetType != TargetType.PROTO_TARGET) { + // Use a a prefixed version of the intermediate artifacts to avoid naming collisions, as + // the proto compilation step happens in the same context as the linking target. + this.intermediateArtifacts = + new IntermediateArtifacts( + ruleContext, "_protos", "protos", ruleContext.getConfiguration()); + } else { + this.intermediateArtifacts = ObjcRuleClasses.intermediateArtifacts(ruleContext); + } } /** @@ -164,6 +174,13 @@ final class ProtoSupport { } /** + * Returns the intermediate artifacts associated with generated proto compilation. + */ + public IntermediateArtifacts getIntermediateArtifacts() { + return intermediateArtifacts; + } + + /** * Registers actions required for compiling the proto files. * * @return this proto support @@ -177,29 +194,30 @@ final class ProtoSupport { } /** - * Adds required configuration to the ObjcCommon support class for proto compilation. - * - * @param commonBuilder The builder for the ObjcCommon support class. - * @return this proto support + * Returns the common object for a proto specific compilation environment. */ - public ProtoSupport addCommonOptions(ObjcCommon.Builder commonBuilder) { - commonBuilder - .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) - .addDepObjcProviders( - ruleContext.getPrerequisites( - ObjcRuleClasses.PROTO_LIB_ATTR, Mode.TARGET, ObjcProvider.class)) - .setHasModuleMap(); - - if (usesProtobufLibrary() && experimentalAutoUnion() && targetType == TargetType.PROTO_TARGET) { - commonBuilder - .addDirectDependencyHeaderSearchPaths(getUserHeaderSearchPaths()) - .setCompilationArtifacts(getCompilationArtifacts()); - } else { - commonBuilder - .addUserHeaderSearchPaths(getUserHeaderSearchPaths()) - .setCompilationArtifacts(getCompilationArtifacts()); + public ObjcCommon getCommon() { + ObjcCommon.Builder commonBuilder = + new ObjcCommon.Builder(ruleContext) + .setIntermediateArtifacts(intermediateArtifacts) + .setHasModuleMap() + .setCompilationArtifacts(getCompilationArtifacts()); + + if (targetType == TargetType.LINKING_TARGET) { + commonBuilder.addDepObjcProviders( + ruleContext.getPrerequisites("deps", Mode.TARGET, ObjcProvider.class)); + } else if (targetType == TargetType.PROTO_TARGET) { + commonBuilder.addDepObjcProviders( + ruleContext.getPrerequisites( + ObjcRuleClasses.PROTO_LIB_ATTR, Mode.TARGET, ObjcProvider.class)); + + if (usesProtobufLibrary() && experimentalAutoUnion()) { + commonBuilder.addDirectDependencyHeaderSearchPaths(getUserHeaderSearchPaths()); + } else { + commonBuilder.addUserHeaderSearchPaths(getUserHeaderSearchPaths()); + } } - return this; + return commonBuilder.build(); } /** @@ -235,7 +253,7 @@ final class ProtoSupport { ImmutableList<Artifact> generatedSources = getGeneratedSources(); CompilationArtifacts.Builder builder = new CompilationArtifacts.Builder() - .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) + .setIntermediateArtifacts(intermediateArtifacts) .setPchFile(Optional.<Artifact>absent()) .addAdditionalHdrs(getGeneratedHeaders()); |