diff options
Diffstat (limited to 'src/main/java/com/google/devtools')
14 files changed, 475 insertions, 194 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java index 48d31f5c7a..df63b8a78b 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java @@ -132,6 +132,7 @@ import com.google.devtools.build.lib.rules.objc.ObjcConfigurationLoader; import com.google.devtools.build.lib.rules.objc.ObjcFrameworkRule; import com.google.devtools.build.lib.rules.objc.ObjcImportRule; import com.google.devtools.build.lib.rules.objc.ObjcLibraryRule; +import com.google.devtools.build.lib.rules.objc.ObjcProtoAspect; import com.google.devtools.build.lib.rules.objc.ObjcProtoLibraryRule; import com.google.devtools.build.lib.rules.objc.ObjcProvider; import com.google.devtools.build.lib.rules.objc.ObjcRuleClasses; @@ -288,6 +289,7 @@ public class BazelRuleClassProvider { J2ObjcAspect j2ObjcAspect = new J2ObjcAspect(TOOLS_REPOSITORY, bazelJ2ObjcProtoAspect); AndroidStudioInfoAspect androidStudioInfoAspect = new AndroidStudioInfoAspect(TOOLS_REPOSITORY, new BazelAndroidStudioInfoSemantics()); + ObjcProtoAspect objcProtoAspect = new ObjcProtoAspect(); builder.addNativeAspectClass(androidNeverlinkAspect); builder.addNativeAspectClass(dexArchiveAspect); @@ -295,6 +297,7 @@ public class BazelRuleClassProvider { builder.addNativeAspectClass(bazelJ2ObjcProtoAspect); builder.addNativeAspectClass(j2ObjcAspect); builder.addNativeAspectClass(androidStudioInfoAspect); + builder.addNativeAspectClass(objcProtoAspect); builder.addRuleDefinition(new WorkspaceBaseRule()); @@ -397,7 +400,7 @@ public class BazelRuleClassProvider { builder.addRuleDefinition(new ObjcRuleClasses.ReleaseBundlingRule()); builder.addRuleDefinition(new ObjcRuleClasses.SimulatorRule()); builder.addRuleDefinition(new ObjcRuleClasses.CompilingRule()); - builder.addRuleDefinition(new ObjcRuleClasses.LinkingRule()); + builder.addRuleDefinition(new ObjcRuleClasses.LinkingRule(objcProtoAspect)); builder.addRuleDefinition(new ObjcRuleClasses.ResourcesRule()); builder.addRuleDefinition(new ObjcRuleClasses.XcodegenRule()); builder.addRuleDefinition(new ObjcRuleClasses.AlwaysLinkRule()); 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 0e4cb61c1a..690207b3ab 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 @@ -39,6 +39,8 @@ 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; @@ -47,7 +49,7 @@ import java.util.Set; * Implementation for the "apple_binary" rule. */ public class AppleBinary implements RuleConfiguredTargetFactory { - + /** * {@link SplitTransitionProvider} instance for the apple binary rule. (This is exposed for * convenience as a single static instance as it possesses no internal state.) @@ -67,9 +69,9 @@ public class AppleBinary implements RuleConfiguredTargetFactory { ObjcProvider.class); ImmutableListMultimap<BuildConfiguration, TransitiveInfoCollection> configToDepsCollectionMap = ruleContext.getPrerequisitesByConfiguration("deps", Mode.SPLIT); - + Set<BuildConfiguration> childConfigurations = getChildConfigurations(ruleContext); - + IntermediateArtifacts ruleIntermediateArtifacts = ObjcRuleClasses.intermediateArtifacts(ruleContext); @@ -80,7 +82,7 @@ public class AppleBinary implements RuleConfiguredTargetFactory { NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.<Artifact>stableOrder() .add(ruleIntermediateArtifacts.combinedArchitectureBinary()); - + for (BuildConfiguration childConfig : childConfigurations) { IntermediateArtifacts intermediateArtifacts = ObjcRuleClasses.intermediateArtifacts(ruleContext, childConfig); @@ -90,7 +92,7 @@ public class AppleBinary implements RuleConfiguredTargetFactory { ImmutableList.Builder<J2ObjcMappingFileProvider> j2ObjcMappingFileProviders = ImmutableList.builder(); J2ObjcEntryClassProvider.Builder j2ObjcEntryClassProviderBuilder = - new J2ObjcEntryClassProvider.Builder(); + new J2ObjcEntryClassProvider.Builder(); for (TransitiveInfoCollection dep : configToDepsCollectionMap.get(childConfig)) { if (dep.getProvider(J2ObjcMappingFileProvider.class) != null) { j2ObjcMappingFileProviders.add(dep.getProvider(J2ObjcMappingFileProvider.class)); @@ -103,18 +105,32 @@ public class AppleBinary implements RuleConfiguredTargetFactory { J2ObjcMappingFileProvider j2ObjcMappingFileProvider = J2ObjcMappingFileProvider.union(j2ObjcMappingFileProviders.build()); J2ObjcEntryClassProvider j2ObjcEntryClassProvider = j2ObjcEntryClassProviderBuilder.build(); - + if (!common.getCompilationArtifacts().get().getArchive().isPresent()) { ruleContext.throwWithRuleError(REQUIRES_AT_LEAST_ONE_SOURCE_FILE); } 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(); + } + new CompilationSupport(ruleContext, childConfig) - .registerCompileAndArchiveActions(common) + .registerCompileAndArchiveActions(common, priorityHeaders) .registerLinkActions( - common.getObjcProvider(), j2ObjcMappingFileProvider, j2ObjcEntryClassProvider, - new ExtraLinkArgs(), ImmutableList.<Artifact>of(), + common.getObjcProvider(), + j2ObjcMappingFileProvider, + j2ObjcEntryClassProvider, + new ExtraLinkArgs(), + ImmutableList.<Artifact>of(), DsymOutputType.APP) .validateAttributes(); ruleContext.assertNoErrors(); @@ -146,26 +162,38 @@ public class AppleBinary implements RuleConfiguredTargetFactory { CompilationArtifacts compilationArtifacts = CompilationSupport.compilationArtifacts(ruleContext, intermediateArtifacts); + 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(); + } + return new ObjcCommon.Builder(ruleContext, buildConfiguration) - .setCompilationAttributes(new CompilationAttributes(ruleContext)) - .setResourceAttributes(new ResourceAttributes(ruleContext)) - .setCompilationArtifacts(compilationArtifacts) - .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(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(); } private <T> List<T> nullToEmptyList(List<T> inputList) { return inputList != null ? inputList : ImmutableList.<T>of(); } - + private Set<BuildConfiguration> getChildConfigurations(RuleContext ruleContext) { // This is currently a hack to obtain all child configurations regardless of the attribute // values of this rule -- this rule does not currently use the actual info provided by @@ -173,7 +201,7 @@ public class AppleBinary implements RuleConfiguredTargetFactory { ImmutableListMultimap<BuildConfiguration, CcToolchainProvider> configToProvider = ruleContext.getPrerequisitesByConfiguration(":cc_toolchain", Mode.SPLIT, CcToolchainProvider.class); - + return configToProvider.keySet(); } 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 66af77d6b9..9a981d5086 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 @@ -35,8 +35,10 @@ 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. @@ -79,10 +81,21 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory ObjcProvider objcProvider = common.getObjcProvider(); assertLibraryOrSources(objcProvider, ruleContext); + 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); - XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder(); NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.<Artifact>stableOrder() .add(intermediateArtifacts.strippedSingleArchitectureBinary()); @@ -102,11 +115,13 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory CompilationSupport compilationSupport = new CompilationSupport(ruleContext) - .registerCompileAndArchiveActions(common) + .registerCompileAndArchiveActions(common, priorityHeaders) .registerFullyLinkAction(common.getObjcProvider()) .addXcodeSettings(xcodeProviderBuilder, common) .registerLinkActions( - objcProvider, j2ObjcMappingFileProvider, j2ObjcEntryClassProvider, + objcProvider, + j2ObjcMappingFileProvider, + j2ObjcEntryClassProvider, getExtraLinkArgs(ruleContext), ImmutableList.<Artifact>of(), DsymOutputType.APP) @@ -116,7 +131,6 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory Optional<RunfilesSupport> maybeRunfilesSupport = Optional.absent(); switch (hasReleaseBundlingSupport) { case YES: - ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class); // TODO(bazel-team): Remove once all bundle users are migrated to ios_application. ReleaseBundlingSupport releaseBundlingSupport = @@ -198,15 +212,25 @@ 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)) - .setResourceAttributes(new ResourceAttributes(ruleContext)) .setCompilationArtifacts(compilationArtifacts) + .setResourceAttributes(new ResourceAttributes(ruleContext)) .addDefines(ruleContext.getTokenizedStringListAttr("defines")) .addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET)) - .addDepObjcProviders( - ruleContext.getPrerequisites("bundles", Mode.TARGET, ObjcProvider.class)) + .addDeps(ruleContext.getPrerequisites("bundles", Mode.TARGET)) .addNonPropagatedDepObjcProviders( ruleContext.getPrerequisites( "non_propagated_deps", Mode.TARGET, ObjcProvider.class)) diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationArtifacts.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationArtifacts.java index 326a208301..099541ab07 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationArtifacts.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationArtifacts.java @@ -72,7 +72,7 @@ final class CompilationArtifacts { this.precompiledSrcs = Iterables.concat(this.precompiledSrcs, precompiledSrcs); return this; } - + Builder setPchFile(Optional<Artifact> pchFile) { Preconditions.checkState(this.pchFile == null, "pchFile is already set to: %s", this.pchFile); @@ -87,6 +87,14 @@ final class CompilationArtifacts { return this; } + Builder addAllSources(CompilationArtifacts otherArtifacts) { + return this.addNonArcSrcs(otherArtifacts.getNonArcSrcs()) + .addSrcs(otherArtifacts.getSrcs()) + .addPrecompiledSrcs(otherArtifacts.getPrecompiledSrcs()) + .addPrivateHdrs(otherArtifacts.getPrivateHdrs()) + .addAdditionalHdrs(otherArtifacts.getAdditionalHdrs()); + } + CompilationArtifacts build() { Optional<Artifact> archive = Optional.absent(); if (!Iterables.isEmpty(srcs) 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 3fff5d53bd..919bdc8713 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 @@ -305,7 +305,33 @@ public final class CompilationSupport { * @return this compilation support */ CompilationSupport registerCompileAndArchiveActions(ObjcCommon common) { - return registerCompileAndArchiveActions(common, ExtraCompileArgs.NONE); + return registerCompileAndArchiveActions( + common, ExtraCompileArgs.NONE, ImmutableList.<PathFragment>of()); + } + + /** + * Registers all actions necessary to compile this rule's sources and archive them. + * + * @param common common information about this rule and its dependencies + * @param priorityHeaders priority headers to be included before the dependency headers + * @return this compilation support + */ + CompilationSupport registerCompileAndArchiveActions( + ObjcCommon common, Iterable<PathFragment> priorityHeaders) { + return registerCompileAndArchiveActions(common, ExtraCompileArgs.NONE, priorityHeaders); + } + + /** + * Registers all actions necessary to compile this rule's sources and archive them. + * + * @param common common information about this rule and its dependencies + * @param extraCompileArgs args to be added to compile actions + * @return this compilation support + */ + CompilationSupport registerCompileAndArchiveActions( + ObjcCommon common, ExtraCompileArgs extraCompileArgs) { + return registerCompileAndArchiveActions( + common, extraCompileArgs, ImmutableList.<PathFragment>of()); } /** @@ -313,11 +339,13 @@ public final class CompilationSupport { * * @param common common information about this rule and its dependencies * @param extraCompileArgs args to be added to compile actions + * @param priorityHeaders priority headers to be included before the dependency headers * @return this compilation support */ CompilationSupport registerCompileAndArchiveActions( ObjcCommon common, - ExtraCompileArgs extraCompileArgs) { + ExtraCompileArgs extraCompileArgs, + Iterable<PathFragment> priorityHeaders) { if (common.getCompilationArtifacts().isPresent()) { registerGenerateModuleMapAction(common.getCompilationArtifacts()); Optional<CppModuleMap> moduleMap; @@ -330,6 +358,7 @@ public final class CompilationSupport { common.getCompilationArtifacts().get(), common.getObjcProvider(), extraCompileArgs, + priorityHeaders, moduleMap, buildConfiguration.isCodeCoverageEnabled()); } @@ -344,6 +373,7 @@ public final class CompilationSupport { CompilationArtifacts compilationArtifacts, ObjcProvider objcProvider, ExtraCompileArgs extraCompileArgs, + Iterable<PathFragment> priorityHeaders, Optional<CppModuleMap> moduleMap, boolean isCodeCoverageEnabled) { ImmutableList.Builder<Artifact> objFiles = new ImmutableList.Builder<>(); @@ -357,6 +387,7 @@ public final class CompilationSupport { sourceFile, objFile, objcProvider, + priorityHeaders, moduleMap, compilationArtifacts, Iterables.concat(extraCompileArgs, ImmutableList.of("-fobjc-arc")), @@ -370,6 +401,7 @@ public final class CompilationSupport { nonArcSourceFile, objFile, objcProvider, + priorityHeaders, moduleMap, compilationArtifacts, Iterables.concat(extraCompileArgs, ImmutableList.of("-fno-objc-arc")), @@ -377,7 +409,7 @@ public final class CompilationSupport { } objFiles.addAll(compilationArtifacts.getPrecompiledSrcs()); - + if (compilationArtifacts.hasSwiftSources()) { registerSwiftModuleMergeAction(compilationArtifacts, objcProvider); } @@ -411,6 +443,7 @@ public final class CompilationSupport { Artifact sourceFile, Artifact objFile, ObjcProvider objcProvider, + Iterable<PathFragment> priorityHeaders, Optional<CppModuleMap> moduleMap, CompilationArtifacts compilationArtifacts, Iterable<String> otherFlags, @@ -448,6 +481,7 @@ public final class CompilationSupport { .add(objcConfiguration.getCoptsForCompilationMode()) .addBeforeEachPath("-iquote", ObjcCommon.userHeaderSearchPaths(buildConfiguration)) .addBeforeEachExecPath("-include", compilationArtifacts.getPchFile().asSet()) + .addBeforeEachPath("-I", priorityHeaders) .addBeforeEachPath("-I", objcProvider.get(INCLUDE)) .addBeforeEachPath("-isystem", objcProvider.get(INCLUDE_SYSTEM)) .add(otherFlags) 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 062eaed308..b4e7c855bb 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 @@ -35,13 +35,14 @@ 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 java.util.ArrayList; -import java.util.List; +import com.google.devtools.build.lib.vfs.PathFragment; /** * Implementation for {@code ios_test} rule in Bazel. @@ -99,6 +100,16 @@ 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(); + } + XcodeProductType productType = getProductType(ruleContext); ExtraLinkArgs extraLinkArgs; Iterable<Artifact> extraLinkInputs; @@ -131,7 +142,7 @@ public final class IosTest implements RuleConfiguredTargetFactory { filesToBuild.add(testApp.getIpa()); } - + J2ObjcMappingFileProvider j2ObjcMappingFileProvider = J2ObjcMappingFileProvider.union( ruleContext.getPrerequisites("deps", Mode.TARGET, J2ObjcMappingFileProvider.class)); J2ObjcEntryClassProvider j2ObjcEntryClassProvider = new J2ObjcEntryClassProvider.Builder() @@ -141,14 +152,17 @@ public final class IosTest implements RuleConfiguredTargetFactory { new CompilationSupport(ruleContext) .registerLinkActions( - common.getObjcProvider(), j2ObjcMappingFileProvider, j2ObjcEntryClassProvider, - extraLinkArgs, extraLinkInputs, DsymOutputType.TEST) - .registerCompileAndArchiveActions(common) + common.getObjcProvider(), + j2ObjcMappingFileProvider, + j2ObjcEntryClassProvider, + extraLinkArgs, + extraLinkInputs, + DsymOutputType.TEST) + .registerCompileAndArchiveActions(common, priorityHeaders) .registerFullyLinkAction(common.getObjcProvider()) .addXcodeSettings(xcodeProviderBuilder, common) .validateAttributes(); - ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); new ReleaseBundlingSupport( ruleContext, common.getObjcProvider(), @@ -232,23 +246,53 @@ public final class IosTest implements RuleConfiguredTargetFactory { } } + /** + * Constructs an {@link ObjcCommon} instance based on the attributes. + */ private ObjcCommon common(RuleContext ruleContext) { - ImmutableList<SdkFramework> extraSdkFrameworks = isXcTest(ruleContext) - ? AUTOMATIC_SDK_FRAMEWORKS_FOR_XCTEST : ImmutableList.<SdkFramework>of(); - List<ObjcProvider> extraDepObjcProviders = new ArrayList<>(); + 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)) + .setCompilationArtifacts(compilationArtifacts) + .setResourceAttributes(new ResourceAttributes(ruleContext)) + .addDefines(ruleContext.getTokenizedStringListAttr("defines")) + .addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET)) + .addDeps(ruleContext.getPrerequisites("bundles", Mode.TARGET)) + .addNonPropagatedDepObjcProviders( + ruleContext.getPrerequisites( + "non_propagated_deps", Mode.TARGET, ObjcProvider.class)) + .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) + .setHasModuleMap(); + if (isXcTest(ruleContext)) { - extraDepObjcProviders.add(xcTestAppProvider(ruleContext).getObjcProvider()); + builder + .addExtraSdkFrameworks(AUTOMATIC_SDK_FRAMEWORKS_FOR_XCTEST) + .addDepObjcProviders(ImmutableList.of(xcTestAppProvider(ruleContext).getObjcProvider())); } // Add the memleaks library if the --ios_memleaks flag is true. The library pauses the test // after all tests have been executed so that leaks can be run. ObjcConfiguration config = ruleContext.getFragment(ObjcConfiguration.class); if (config.runMemleaks()) { - extraDepObjcProviders - .add(ruleContext.getPrerequisite(MEMLEAKS_DEP_ATTR, Mode.TARGET, ObjcProvider.class)); + builder.addDepObjcProviders( + ruleContext.getPrerequisites(MEMLEAKS_DEP_ATTR, Mode.TARGET, ObjcProvider.class)); } - return ObjcLibrary.common(ruleContext, extraSdkFrameworks, /*alwayslink=*/false, - extraDepObjcProviders); + + return builder.build(); } protected static boolean isXcTest(RuleContext ruleContext) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTestRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosTestRule.java index 12f69defd7..4292f4a9b0 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTestRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IosTestRule.java @@ -18,7 +18,6 @@ import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTran import static com.google.devtools.build.lib.packages.Attribute.attr; import static com.google.devtools.build.lib.packages.BuildType.LABEL; import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST; -import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.BundlingRule; import static com.google.devtools.build.lib.syntax.Type.BOOLEAN; import static com.google.devtools.build.lib.syntax.Type.STRING_LIST; @@ -37,6 +36,7 @@ import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; import com.google.devtools.build.lib.rules.apple.AppleConfiguration; +import com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.BundlingRule; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.FileType; @@ -182,7 +182,6 @@ public class IosTestRule implements RuleDefinition { .ancestors( BaseRuleClasses.BaseRule.class, BaseRuleClasses.TestBaseRule.class, - ObjcRuleClasses.CompilingRule.class, ObjcRuleClasses.ReleaseBundlingRule.class, ObjcRuleClasses.LinkingRule.class, ObjcRuleClasses.XcodegenRule.class, diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java index 6d4f47552f..7cf1fcf323 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java @@ -193,6 +193,7 @@ public class ObjcCommandLineOptions extends FragmentOptions { ) public Label extraEntitlements; + // TODO(b/28451644): Make this option the default behavior. @Option( name = "experimental_auto_top_level_union_objc_protos", defaultValue = "false", @@ -212,7 +213,7 @@ public class ObjcCommandLineOptions extends FragmentOptions { + "when signing." ) public boolean deviceDebugEntitlements; - + @VisibleForTesting static final String DEFAULT_MINIMUM_IOS = "7.0"; @SuppressWarnings("unchecked") 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 41a0201586..b7a3faa9ae 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 @@ -16,7 +16,6 @@ package com.google.devtools.build.lib.rules.objc; import static com.google.devtools.build.lib.rules.objc.XcodeProductType.LIBRARY_STATIC; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.ConfiguredTarget; @@ -68,41 +67,29 @@ public class ObjcLibrary implements RuleConfiguredTargetFactory { } /** - * Constructs an {@link ObjcCommon} instance based on the attributes of the given rule. The rule - * should inherit from {@link ObjcLibraryRule}.. + * Constructs an {@link ObjcCommon} instance based on the attributes of the given rule context. */ - static ObjcCommon common(RuleContext ruleContext, Iterable<SdkFramework> extraSdkFrameworks, - boolean alwayslink, Iterable<ObjcProvider> extraDepObjcProviders) { - CompilationArtifacts compilationArtifacts = - CompilationSupport.compilationArtifacts(ruleContext); - + private ObjcCommon common(RuleContext ruleContext) { return new ObjcCommon.Builder(ruleContext) .setCompilationAttributes(new CompilationAttributes(ruleContext)) .setResourceAttributes(new ResourceAttributes(ruleContext)) - .addExtraSdkFrameworks(extraSdkFrameworks) .addDefines(ruleContext.getTokenizedStringListAttr("defines")) - .setCompilationArtifacts(compilationArtifacts) + .setCompilationArtifacts(CompilationSupport.compilationArtifacts(ruleContext)) .addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET)) .addDepObjcProviders( ruleContext.getPrerequisites("bundles", Mode.TARGET, ObjcProvider.class)) .addNonPropagatedDepObjcProviders( ruleContext.getPrerequisites("non_propagated_deps", Mode.TARGET, ObjcProvider.class)) .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) - .setAlwayslink(alwayslink) + .setAlwayslink(ruleContext.attributes().get("alwayslink", Type.BOOLEAN)) .setHasModuleMap() - .addDepObjcProviders(extraDepObjcProviders) .build(); } @Override public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException, RuleErrorException { - final ObjcCommon common = - common( - ruleContext, - ImmutableList.<SdkFramework>of(), - ruleContext.attributes().get("alwayslink", Type.BOOLEAN), - ImmutableList.<ObjcProvider>of()); + ObjcCommon common = common(ruleContext); XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder(); NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.<Artifact>stableOrder() 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 a6ec22d9f1..79cfb1d20c 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 @@ -23,6 +23,7 @@ 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.ProtoSupport.TargetType; /** * Implementation for the "objc_proto_library" rule. @@ -31,18 +32,17 @@ public class ObjcProtoLibrary implements RuleConfiguredTargetFactory { @Override public ConfiguredTarget create(final RuleContext ruleContext) throws InterruptedException, RuleErrorException { - ProtoSupport protoSupport = new ProtoSupport(ruleContext); - ObjcCommon.Builder commonBuilder = new ObjcCommon.Builder(ruleContext); XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder(); NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.stableOrder(); - protoSupport - .validate() - .addCommonOptions(commonBuilder) - .addXcodeProviderOptions(xcodeProviderBuilder) - .addFilesToBuild(filesToBuild) - .registerActions(); + ProtoSupport protoSupport = + new ProtoSupport(ruleContext, TargetType.PROTO_TARGET) + .validate() + .addCommonOptions(commonBuilder) + .addXcodeProviderOptions(xcodeProviderBuilder) + .addFilesToBuild(filesToBuild) + .registerActions(); if (ruleContext.hasErrors()) { return null; @@ -52,17 +52,26 @@ public class ObjcProtoLibrary implements RuleConfiguredTargetFactory { filesToBuild.addAll(common.getCompiledArchive().asSet()); - new CompilationSupport(ruleContext) - .registerCompileAndArchiveActions(commonBuilder.build()) - .registerFullyLinkAction(common.getObjcProvider()); - new XcodeSupport(ruleContext) .addFilesToBuild(filesToBuild) .addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), LIBRARY_STATIC) .addDependencies( - xcodeProviderBuilder, new Attribute(ObjcProtoLibraryRule.PROTO_LIB_ATTR, Mode.TARGET)) + xcodeProviderBuilder, new Attribute(ObjcRuleClasses.PROTO_LIB_ATTR, Mode.TARGET)) .registerActions(xcodeProviderBuilder.build()); + boolean usesProtobufLibrary = protoSupport.usesProtobufLibrary(); + + boolean experimentalAutoUnion = + ObjcRuleClasses.objcConfiguration(ruleContext).experimentalAutoTopLevelUnionObjCProtos(); + + // 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()); + } + return ObjcRuleClasses.ruleConfiguredTarget(ruleContext, filesToBuild.build()) .addProvider(XcodeProvider.class, xcodeProviderBuilder.build()) .addProvider(ObjcProvider.class, common.getObjcProvider()) diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryRule.java index 2cb9f9cafc..c8b62fe7ad 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryRule.java @@ -14,16 +14,20 @@ package com.google.devtools.build.lib.rules.objc; -import static com.google.devtools.build.lib.packages.Attribute.ComputedDefault; import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST; import static com.google.devtools.build.lib.packages.Attribute.attr; import static com.google.devtools.build.lib.packages.BuildType.LABEL; import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST; +import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.PROTOBUF_WELL_KNOWN_TYPES; +import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.PROTO_COMPILER_ATTR; +import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.PROTO_COMPILER_SUPPORT_ATTR; +import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.PROTO_LIB_ATTR; import static com.google.devtools.build.lib.syntax.Type.BOOLEAN; import com.google.devtools.build.lib.analysis.BaseRuleClasses; import com.google.devtools.build.lib.analysis.RuleDefinition; import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; +import com.google.devtools.build.lib.packages.Attribute.ComputedDefault; import com.google.devtools.build.lib.packages.AttributeMap; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder; @@ -43,10 +47,6 @@ public class ObjcProtoLibraryRule implements RuleDefinition { static final String PER_PROTO_INCLUDES_ATTR = "per_proto_includes"; static final String PORTABLE_PROTO_FILTERS_ATTR = "portable_proto_filters"; - static final String PROTO_COMPILER_ATTR = "$googlemac_proto_compiler"; - static final String PROTO_COMPILER_SUPPORT_ATTR = "$googlemac_proto_compiler_support"; - static final String PROTO_LIB_ATTR = "$lib_protobuf"; - static final String PROTOBUF_WELL_KNOWN_TYPES = "$protobuf_well_known_types"; static final String XCODE_GEN_ATTR = "$xcodegen"; @Override @@ -123,7 +123,7 @@ public class ObjcProtoLibraryRule implements RuleDefinition { @Override public Object getDefault(AttributeMap rule) { if (rule.isAttributeValueExplicitlySpecified(PORTABLE_PROTO_FILTERS_ATTR)) { - return env.getLabel("//external:objc_protobuf_lib"); + return env.getToolsLabel("//tools/objc:objc_protobuf_lib"); } else { return rule.get(OUTPUT_CPP_ATTR, Type.BOOLEAN) ? env.getLabel("//external:objc_proto_cpp_lib") @@ -132,15 +132,9 @@ public class ObjcProtoLibraryRule implements RuleDefinition { } })) .add( - // The well known type proto label should resolve to the shared location of proto - // dependencies of targets in the workspace. Unless all dependencies refer to the same - // label for these proto dependencies, an artifact comparison between them is not - // possible. Ultimately, we will need to resolve this cross-repository dependency, but, - // for now, these well-known protos do not exist in a common repository, and must thus - // be present in the root workspace. attr(PROTOBUF_WELL_KNOWN_TYPES, LABEL) .cfg(HOST) - .value(env.getLabel("//tools/objc:protobuf_well_known_types"))) + .value(env.getToolsLabel("//tools/objc:protobuf_well_known_types"))) .add( attr(XCODE_GEN_ATTR, LABEL) .cfg(HOST) diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoProvider.java index d1ed2b9aea..6692988a82 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoProvider.java @@ -55,7 +55,7 @@ public class ObjcProtoProvider implements TransitiveInfoProvider { * several transitive dependencies. */ public static final class Builder { - private final NestedSetBuilder<Artifact> protoSources = NestedSetBuilder.linkOrder(); + private final NestedSetBuilder<Artifact> protoSources = NestedSetBuilder.naiveLinkOrder(); private final NestedSetBuilder<Artifact> portableProtoFilters = NestedSetBuilder.linkOrder(); /** @@ -69,8 +69,8 @@ public class ObjcProtoProvider implements TransitiveInfoProvider { /** * Adds all the proto filters to the set of dependencies. */ - public Builder addPortableProtoFilters(Iterable<Artifact> protoFilters) { - this.portableProtoFilters.addAll(protoFilters); + public Builder addPortableProtoFilters(NestedSet<Artifact> protoFilters) { + this.portableProtoFilters.addTransitive(protoFilters); return this; } 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 48981fbbe0..4c089de70c 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 @@ -808,9 +808,24 @@ public class ObjcRuleClasses { } /** + * Protocol buffer related implicit attributes. + */ + static final String PROTO_COMPILER_ATTR = "$googlemac_proto_compiler"; + static final String PROTO_COMPILER_SUPPORT_ATTR = "$googlemac_proto_compiler_support"; + static final String PROTO_LIB_ATTR = "$lib_protobuf"; + static final String PROTOBUF_WELL_KNOWN_TYPES = "$protobuf_well_known_types"; + + /** * Common attributes for {@code objc_*} rules that link sources and dependencies. */ public static class LinkingRule implements RuleDefinition { + + private final ObjcProtoAspect objcProtoAspect; + + public LinkingRule(ObjcProtoAspect objcProtoAspect) { + this.objcProtoAspect = objcProtoAspect; + } + @Override public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { return builder @@ -827,8 +842,24 @@ public class ObjcRuleClasses { .singleArtifact() .value(env.getToolsLabel("//tools/objc:j2objc_dead_code_pruner"))) .add(attr("$dummy_lib", LABEL).value(env.getToolsLabel("//tools/objc:dummy_lib"))) + .add( + attr(PROTO_COMPILER_ATTR, LABEL) + .allowedFileTypes(FileType.of(".py")) + .cfg(HOST) + .singleArtifact() + .value(env.getToolsLabel("//tools/objc:protobuf_compiler"))) + .add( + attr(PROTO_COMPILER_SUPPORT_ATTR, LABEL) + .legacyAllowAnyFileType() + .cfg(HOST) + .value(env.getToolsLabel("//tools/objc:protobuf_compiler_support"))) + .add( + attr(PROTOBUF_WELL_KNOWN_TYPES, LABEL) + .cfg(HOST) + .value(env.getToolsLabel("//tools/objc:protobuf_well_known_types"))) + .override(builder.copy("deps").aspect(objcProtoAspect)) /* <!-- #BLAZE_RULE($objc_linking_rule).ATTRIBUTE(linkopts) --> - Extra flags to pass to the linker. + Extra flags to pass to the linker. <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/ .add(attr("linkopts", STRING_LIST)) .build(); 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 4c2d8d60ad..c6844f9d4d 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 @@ -16,12 +16,13 @@ package com.google.devtools.build.lib.rules.objc; import static com.google.common.base.CaseFormat.LOWER_UNDERSCORE; import static com.google.common.base.CaseFormat.UPPER_CAMEL; +import static com.google.devtools.build.lib.packages.BuildType.LABEL; +import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.CharMatcher; import com.google.common.base.Function; 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; @@ -59,6 +60,8 @@ import javax.annotation.Nullable; * <p>Methods on this class can be called in any order without impacting the result. */ final class ProtoSupport { + private static final PathFragment BAZEL_TOOLS_PREFIX = new PathFragment("external/bazel_tools/"); + private static final Function<Artifact, PathFragment> PARENT_PATHFRAGMENT = new Function<Artifact, PathFragment>() { @Override @@ -67,6 +70,25 @@ final class ProtoSupport { } }; + /** + * Type of target that is generating the protos. There is a distinction because when generating + * the protos from an objc_proto_library, the attributes of the rule need to be considered, but + * when generating from a linking target (e.g. objc_binary), the attributes don't exist, but the + * ObjcProtoProviders need to be checked. + */ + enum TargetType { + /** + * The generating rule is an objc_proto_library rule. + */ + PROTO_TARGET, + + /** + * The generating target is a linking rule, which generates, compiles and links all the protos + * in the transitive closure of dependencies. + */ + LINKING_TARGET, + } + @VisibleForTesting static final String NO_PROTOS_ERROR = "no protos to compile - a non-empty deps attribute is required"; @@ -95,15 +117,18 @@ final class ProtoSupport { private final RuleContext ruleContext; private final Attributes attributes; + private final TargetType targetType; /** * Creates a new proto support. * * @param ruleContext context this proto library is constructed in + * @param targetType the type of target generating the protos */ - public ProtoSupport(RuleContext ruleContext) { + public ProtoSupport(RuleContext ruleContext, TargetType targetType) { this.ruleContext = ruleContext; this.attributes = new Attributes(ruleContext); + this.targetType = targetType; } /** @@ -123,7 +148,7 @@ final class ProtoSupport { ruleContext.ruleError(NO_PROTOS_ERROR); } - if (attributes.usesProtobufLibrary()) { + if (usesProtobufLibrary()) { if (attributes.getPortableProtoFilters().isEmpty()) { ruleContext.ruleError(PORTABLE_PROTO_FILTERS_EMPTY_ERROR); } @@ -144,8 +169,8 @@ final class ProtoSupport { * @return this proto support */ public ProtoSupport registerActions() { - registerProtoInputListFileAction(); - if (!attributes.getProtoFiles().isEmpty()) { + if (!Iterables.isEmpty(getProtoSources())) { + registerProtoInputListFileAction(); registerGenerateProtoFilesAction(); } return this; @@ -155,17 +180,25 @@ 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 bundle support + * @return this proto support */ public ProtoSupport addCommonOptions(ObjcCommon.Builder commonBuilder) { commonBuilder - .setCompilationArtifacts(getCompilationArtifacts()) - .addUserHeaderSearchPaths(getSearchPathEntries()) .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) .addDepObjcProviders( ruleContext.getPrerequisites( - ObjcProtoLibraryRule.PROTO_LIB_ATTR, Mode.TARGET, ObjcProvider.class)) + 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()); + } return this; } @@ -173,11 +206,11 @@ final class ProtoSupport { * Adds required configuration to the XcodeProvider support class for proto compilation. * * @param xcodeProviderBuilder The builder for the XcodeProvider support class. - * @return this bundle support + * @return this proto support */ public ProtoSupport addXcodeProviderOptions(XcodeProvider.Builder xcodeProviderBuilder) { xcodeProviderBuilder - .addUserHeaderSearchPaths(getSearchPathEntries()) + .addUserHeaderSearchPaths(getUserHeaderSearchPaths()) .addCopts(ObjcRuleClasses.objcConfiguration(ruleContext).getCopts()) .addHeaders(getGeneratedHeaders()) .setCompilationArtifacts(getCompilationArtifacts()); @@ -188,13 +221,126 @@ final class ProtoSupport { * Adds the files needed to be built by the rule. * * @param filesToBuild An aggregated set of the files to be built by the rule. - * @return this bundle support + * @return this proto support */ public ProtoSupport addFilesToBuild(NestedSetBuilder<Artifact> filesToBuild) { filesToBuild.addAll(getGeneratedSources()).addAll(getGeneratedHeaders()); return this; } + /** + * Returns the proto compilation artifacts for the current rule. + */ + public CompilationArtifacts getCompilationArtifacts() { + ImmutableList<Artifact> generatedSources = getGeneratedSources(); + CompilationArtifacts.Builder builder = + new CompilationArtifacts.Builder() + .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) + .setPchFile(Optional.<Artifact>absent()) + .addAdditionalHdrs(getGeneratedHeaders()) + .addAdditionalHdrs(generatedSources); + + if (experimentalAutoUnion()) { + if (targetType == TargetType.PROTO_TARGET && !usesProtobufLibrary() + || targetType == TargetType.LINKING_TARGET) { + builder.addNonArcSrcs(generatedSources); + } + } else { + if (targetType == TargetType.PROTO_TARGET) { + builder.addNonArcSrcs(generatedSources); + } + } + + return builder.build(); + } + + /** + * Returns the include paths for the generated protos. + */ + public ImmutableSet<PathFragment> getUserHeaderSearchPaths() { + PathFragment workspaceRelativeOutputDir = getWorkspaceRelativeOutputDir(); + + ImmutableSet.Builder<PathFragment> searchPathEntriesBuilder = + new ImmutableSet.Builder<PathFragment>().add(workspaceRelativeOutputDir); + + if (attributes.needsPerProtoIncludes()) { + PathFragment generatedProtoDir = + new PathFragment(workspaceRelativeOutputDir, ruleContext.getLabel().getPackageFragment()); + + searchPathEntriesBuilder + .add(generatedProtoDir) + .addAll(Iterables.transform(getGeneratedHeaders(), PARENT_PATHFRAGMENT)); + } + + return searchPathEntriesBuilder.build(); + } + + /** + * Returns whether the rule is configured to use the protobuf library. + */ + public boolean usesProtobufLibrary() { + return attributes.hasPortableProtoFilters() || targetType == TargetType.LINKING_TARGET; + } + + private Iterable<Artifact> getProtoSources() { + NestedSetBuilder<Artifact> protos = NestedSetBuilder.stableOrder(); + + if (experimentalAutoUnion() && targetType == TargetType.LINKING_TARGET) { + Iterable<ObjcProtoProvider> objcProtoProviders = + ruleContext.getPrerequisites("deps", Mode.TARGET, ObjcProtoProvider.class); + for (ObjcProtoProvider objcProtoProvider : objcProtoProviders) { + protos.addTransitive(objcProtoProvider.getProtoSources()); + } + } + + protos.addTransitive(attributes.getProtoFiles()); + + // Transform the well known proto artifacts by removing the external/bazel_tools prefix if + // present. Otherwise the comparison for filtering out the well known types is not possible. + ImmutableSet.Builder<PathFragment> wellKnownProtoPathsBuilder = new ImmutableSet.Builder<>(); + for (Artifact wellKnownProto : attributes.getWellKnownTypeProtos()) { + PathFragment execPath = wellKnownProto.getExecPath(); + if (execPath.startsWith(BAZEL_TOOLS_PREFIX)) { + wellKnownProtoPathsBuilder.add(execPath.relativeTo(BAZEL_TOOLS_PREFIX)); + } else { + wellKnownProtoPathsBuilder.add(execPath); + } + } + + ImmutableSet<PathFragment> wellKnownProtoPaths = wellKnownProtoPathsBuilder.build(); + + // Filter out the well known types from being sent to be generated, as these protos have already + // been generated and linked in libprotobuf.a. + ImmutableSet.Builder<Artifact> filteredProtos = new ImmutableSet.Builder<>(); + for (Artifact proto : protos.build()) { + if (!wellKnownProtoPaths.contains(proto.getExecPath())) { + filteredProtos.add(proto); + } + } + + return filteredProtos.build(); + } + + private NestedSet<Artifact> getPortableProtoFilters() { + NestedSetBuilder<Artifact> portableProtoFilters = NestedSetBuilder.stableOrder(); + + if (experimentalAutoUnion() && targetType == TargetType.LINKING_TARGET) { + Iterable<ObjcProtoProvider> objcProtoProviders = + ruleContext.getPrerequisites("deps", Mode.TARGET, ObjcProtoProvider.class); + for (ObjcProtoProvider objcProtoProvider : objcProtoProviders) { + portableProtoFilters.addTransitive(objcProtoProvider.getPortableProtoFilters()); + } + } + + portableProtoFilters.addAll(attributes.getPortableProtoFilters()); + return portableProtoFilters.build(); + } + + private boolean experimentalAutoUnion() { + ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); + return objcConfiguration.experimentalAutoTopLevelUnionObjCProtos(); + } + private void registerProtoInputListFileAction() { ruleContext.registerAction( new FileWriteAction( @@ -215,6 +361,15 @@ final class ProtoSupport { .build(ruleContext)); } + private Artifact getProtoInputListFile() { + return ruleContext.getUniqueDirectoryArtifact( + "_protos", "_proto_input_files", ruleContext.getConfiguration().getGenfilesDirectory()); + } + + private String getProtoInputListFileContents() { + return Artifact.joinExecPaths("\n", getProtoSources()); + } + private PathFragment getWorkspaceRelativeOutputDir() { // Generate sources in a package-and-rule-scoped directory; adds both the // package-and-rule-scoped directory and the header-containing-directory to the include path @@ -225,19 +380,8 @@ final class ProtoSupport { ruleContext.getBinOrGenfilesDirectory().getExecPath(), rootRelativeOutputDir); } - private CompilationArtifacts getCompilationArtifacts() { - ImmutableList<Artifact> generatedSources = getGeneratedSources(); - return new CompilationArtifacts.Builder() - .addNonArcSrcs(generatedSources) - .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) - .setPchFile(Optional.<Artifact>absent()) - .addAdditionalHdrs(getGeneratedHeaders()) - .addAdditionalHdrs(generatedSources) - .build(); - } - private ImmutableList<Artifact> getGeneratedHeaders() { - boolean useObjcName = attributes.usesObjcHeaderNames() || attributes.usesProtobufLibrary(); + boolean useObjcName = attributes.usesObjcHeaderNames() || usesProtobufLibrary(); return generatedOutputArtifacts(FileType.of(".pb" + (useObjcName ? "objc.h" : ".h"))); } @@ -245,46 +389,18 @@ final class ProtoSupport { return generatedOutputArtifacts( FileType.of( ".pb" - + (attributes.usesProtobufLibrary() ? "objc" : "") + + (usesProtobufLibrary() ? "objc" : "") + (attributes.outputsCpp() ? ".cc" : ".m"))); } - private ImmutableSet<PathFragment> getSearchPathEntries() { - PathFragment workspaceRelativeOutputDir = getWorkspaceRelativeOutputDir(); - - ImmutableSet.Builder<PathFragment> searchPathEntriesBuilder = - new ImmutableSet.Builder<PathFragment>().add(workspaceRelativeOutputDir); - - if (attributes.needsPerProtoIncludes()) { - PathFragment generatedProtoDir = - new PathFragment(workspaceRelativeOutputDir, ruleContext.getLabel().getPackageFragment()); - - searchPathEntriesBuilder - .add(generatedProtoDir) - .addAll(Iterables.transform(getGeneratedHeaders(), PARENT_PATHFRAGMENT)); - } - - return searchPathEntriesBuilder.build(); - } - - private Artifact getProtoInputListFile() { - return ruleContext.getUniqueDirectoryArtifact( - "_protos", "_proto_input_files", ruleContext.getConfiguration().getGenfilesDirectory()); - } - - private String getProtoInputListFileContents() { - return Artifact.joinExecPaths("\n", getFilteredProtos()); - } - private NestedSet<Artifact> getGenerateActionInputs() { NestedSetBuilder<Artifact> inputsBuilder = NestedSetBuilder.<Artifact>stableOrder() .add(attributes.getProtoCompiler()) - .addAll(attributes.getProtoFiles()) + .addAll(getProtoSources()) .add(getProtoInputListFile()) - .addAll(attributes.getProtoLibrary()) .addAll(attributes.getProtoCompilerSupport()) - .addAll(attributes.getPortableProtoFilters()); + .addAll(getPortableProtoFilters()); Artifact optionsFile = attributes.getOptionsFile(); if (optionsFile != null) { @@ -299,7 +415,7 @@ final class ProtoSupport { } private CustomCommandLine getGenerateCommandLine() { - if (attributes.usesProtobufLibrary()) { + if (usesProtobufLibrary()) { return getProtobufCommandLine(); } else { return getPb2CommandLine(); @@ -346,7 +462,7 @@ final class ProtoSupport { .add("."); boolean configAdded = false; - for (Artifact portableProtoFilter : attributes.getPortableProtoFilters()) { + for (Artifact portableProtoFilter : getPortableProtoFilters()) { String configFlag; if (!configAdded) { configFlag = "--config"; @@ -362,12 +478,12 @@ final class ProtoSupport { private ImmutableList<Artifact> generatedOutputArtifacts(FileType newFileType) { ImmutableList.Builder<Artifact> builder = new ImmutableList.Builder<>(); - for (Artifact protoFile : getFilteredProtos()) { + for (Artifact protoFile : getProtoSources()) { String protoFileName = FileSystemUtils.removeExtension(protoFile.getFilename()); String generatedOutputName; if (attributes.outputsCpp()) { generatedOutputName = protoFileName; - } else if (attributes.usesProtobufLibrary()){ + } else if (usesProtobufLibrary()) { // The protobuf library generates filenames with some slight modifications. generatedOutputName = generateProtobufFilename(protoFileName); } else { @@ -457,14 +573,6 @@ final class ProtoSupport { return casedSegments.toString(); } - private Iterable<Artifact> getFilteredProtos() { - // Filter the well known types from being sent to be generated, as these protos have already - // been generated and linked in libprotobuf.a. - return Iterables.filter( - attributes.getProtoFiles(), - Predicates.not(Predicates.in(attributes.getWellKnownTypeProtos()))); - } - /** * Common rule attributes used by an Objective C proto library. */ @@ -479,31 +587,44 @@ final class ProtoSupport { * Returns whether the generated files should be C++ or Objective C. */ boolean outputsCpp() { - return ruleContext.attributes().get(ObjcProtoLibraryRule.OUTPUT_CPP_ATTR, Type.BOOLEAN); + if (ruleContext.attributes().has(ObjcProtoLibraryRule.OUTPUT_CPP_ATTR, Type.BOOLEAN)) { + return ruleContext.attributes().get(ObjcProtoLibraryRule.OUTPUT_CPP_ATTR, Type.BOOLEAN); + } + return false; } /** * Returns whether the generated header files should have be of type pb.h or pbobjc.h. */ boolean usesObjcHeaderNames() { - return ruleContext + if (ruleContext .attributes() - .get(ObjcProtoLibraryRule.USE_OBJC_HEADER_NAMES_ATTR, Type.BOOLEAN); + .has(ObjcProtoLibraryRule.USE_OBJC_HEADER_NAMES_ATTR, Type.BOOLEAN)) { + return ruleContext + .attributes() + .get(ObjcProtoLibraryRule.USE_OBJC_HEADER_NAMES_ATTR, Type.BOOLEAN); + } + return false; } /** * Returns whether the includes should include each of the proto generated headers. */ boolean needsPerProtoIncludes() { - return ruleContext + if (ruleContext .attributes() - .get(ObjcProtoLibraryRule.PER_PROTO_INCLUDES_ATTR, Type.BOOLEAN); + .has(ObjcProtoLibraryRule.PER_PROTO_INCLUDES_ATTR, Type.BOOLEAN)) { + return ruleContext + .attributes() + .get(ObjcProtoLibraryRule.PER_PROTO_INCLUDES_ATTR, Type.BOOLEAN); + } + return false; } /** * Returns whether to use the protobuf library instead of the PB2 library. */ - boolean usesProtobufLibrary() { + boolean hasPortableProtoFilters() { return ruleContext .attributes() .isAttributeValueExplicitlySpecified(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR); @@ -513,9 +634,14 @@ final class ProtoSupport { * Returns the list of portable proto filters. */ ImmutableList<Artifact> getPortableProtoFilters() { - return ruleContext - .getPrerequisiteArtifacts(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR, Mode.HOST) - .list(); + if (ruleContext + .attributes() + .has(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR, LABEL_LIST)) { + return ruleContext + .getPrerequisiteArtifacts(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR, Mode.HOST) + .list(); + } + return ImmutableList.of(); } /** @@ -523,7 +649,7 @@ final class ProtoSupport { */ ImmutableList<Artifact> getWellKnownTypeProtos() { return ruleContext - .getPrerequisiteArtifacts(ObjcProtoLibraryRule.PROTOBUF_WELL_KNOWN_TYPES, Mode.HOST) + .getPrerequisiteArtifacts(ObjcRuleClasses.PROTOBUF_WELL_KNOWN_TYPES, Mode.HOST) .list(); } @@ -532,15 +658,18 @@ final class ProtoSupport { */ @Nullable Artifact getOptionsFile() { - return ruleContext.getPrerequisiteArtifact(ObjcProtoLibraryRule.OPTIONS_FILE_ATTR, Mode.HOST); + if (ruleContext.attributes().has(ObjcProtoLibraryRule.OPTIONS_FILE_ATTR, LABEL)) { + return ruleContext.getPrerequisiteArtifact( + ObjcProtoLibraryRule.OPTIONS_FILE_ATTR, Mode.HOST); + } + return null; } /** * Returns the proto compiler to be used. */ Artifact getProtoCompiler() { - return ruleContext.getPrerequisiteArtifact( - ObjcProtoLibraryRule.PROTO_COMPILER_ATTR, Mode.HOST); + return ruleContext.getPrerequisiteArtifact(ObjcRuleClasses.PROTO_COMPILER_ATTR, Mode.HOST); } /** @@ -548,17 +677,7 @@ final class ProtoSupport { */ ImmutableList<Artifact> getProtoCompilerSupport() { return ruleContext - .getPrerequisiteArtifacts(ObjcProtoLibraryRule.PROTO_COMPILER_SUPPORT_ATTR, Mode.HOST) - .list(); - } - - /** - * Returns the list of files that compose the proto library. This is the implicit dependency - * added to the objc_proto_library target. - */ - ImmutableList<Artifact> getProtoLibrary() { - return ruleContext - .getPrerequisiteArtifacts(ObjcProtoLibraryRule.PROTO_LIB_ATTR, Mode.TARGET) + .getPrerequisiteArtifacts(ObjcRuleClasses.PROTO_COMPILER_SUPPORT_ATTR, Mode.HOST) .list(); } |