aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com
diff options
context:
space:
mode:
authorGravatar Sergio Campama <kaipi@google.com>2016-05-24 21:10:27 +0000
committerGravatar Yue Gan <yueg@google.com>2016-05-25 08:35:36 +0000
commitf945a0c70f46588ce1203d39824377f5c399358e (patch)
tree13fe9d1626787d8850fc66c5a994e7690f90952a /src/main/java/com
parent1164a4f9db8d2b66d005bfa340ed76fd5f89fb00 (diff)
Support for gathering all the protos seen in the transitive closure of dependencies through the ObjcProtoAspect, compiling and linking the generated protos at the final linking target. This is only enabled for objc_proto_libraries using the portable_proto_filters attribute, and guarded with the "--experimental_auto_top_level_union_objc_protos" flag. This prevents duplicate symbol errors as the generated sources are only linked once.
-- MOS_MIGRATED_REVID=123144532
Diffstat (limited to 'src/main/java/com')
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java76
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java38
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/CompilationArtifacts.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java40
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java76
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/IosTestRule.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java23
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibrary.java35
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryRule.java20
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoProvider.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java33
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ProtoSupport.java301
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();
}