aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/objc
diff options
context:
space:
mode:
authorGravatar allevato <allevato@google.com>2018-04-05 09:46:55 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-04-05 09:48:42 -0700
commite1ed9e9e567334fdf7c26cd0db6f20c64840f119 (patch)
tree5ef5b93f36dc499b64bb5d3f3aed9bcec8e822cb /src/main/java/com/google/devtools/build/lib/rules/objc
parentd7829b1cb0cfbafe10a70c0a4868158dba46b27a (diff)
Fix strict module map propagation for j2objc.
J2Objc needs special consideration to implement strict Swift-ObjC deps. The module maps for the generated Objective-C code are associated with their originating java_library targets (via the J2Objc aspect), which a swift_library cannot directly depend on. So those deeper down module maps need to be propagated transitively *until* a j2objc_library is reached; at that point, the j2objc_library should propagate all of its Java deps module maps, but *not* any of its j2objc_library deps (because that would be non-strict). PiperOrigin-RevId: 191754811
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/objc')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java11
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibrary.java63
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java34
3 files changed, 84 insertions, 24 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
index c12faf2e1c..73a3557164 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
@@ -809,10 +809,13 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF
for (Attribute dependentAttribute : dependentAttributes) {
if (ruleContext.attributes().has(dependentAttribute.getName(), BuildType.LABEL_LIST)
|| ruleContext.attributes().has(dependentAttribute.getName(), BuildType.LABEL)) {
- builder.addDepObjcProviders(ruleContext.getPrerequisites(
- dependentAttribute.getName(),
- dependentAttribute.getAccessMode(),
- ObjcProvider.SKYLARK_CONSTRUCTOR));
+ Iterable<ObjcProvider> depObjcProviders =
+ ruleContext.getPrerequisites(
+ dependentAttribute.getName(),
+ dependentAttribute.getAccessMode(),
+ ObjcProvider.SKYLARK_CONSTRUCTOR);
+ builder.addDepObjcProviders(depObjcProviders);
+ builder.addRepropagatedModuleMapObjcProviders(depObjcProviders);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibrary.java
index b761f53fdc..317fbbb221 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibrary.java
@@ -15,8 +15,6 @@
package com.google.devtools.build.lib.rules.objc;
import static com.google.devtools.build.lib.collect.nestedset.Order.STABLE_ORDER;
-import static com.google.devtools.build.lib.rules.objc.ObjcProvider.JRE_LIBRARY;
-import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
@@ -29,6 +27,7 @@ import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.BuildType;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.List;
@@ -48,13 +47,51 @@ public class J2ObjcLibrary implements RuleConfiguredTargetFactory {
ImmutableList.of("java_import", "java_library", "proto_library");
private ObjcCommon common(RuleContext ruleContext) throws InterruptedException {
+ List<ConfiguredTargetAndData> deps =
+ ruleContext.getPrerequisiteConfiguredTargetAndTargets("deps", Mode.TARGET);
+ List<ConfiguredTargetAndData> jreDeps =
+ ruleContext.getPrerequisiteConfiguredTargetAndTargets("jre_deps", Mode.TARGET);
+
+ ImmutableList.Builder<ObjcProvider> repropagatedModuleMapsProviders =
+ new ImmutableList.Builder<>();
+
+ // In order to support strict Obj-C deps from Swift, we need to repropagate the module maps of
+ // targets that swift_libraries cannot directly depend on, like java_library. So we repropagate
+ // for any dependency *except* j2objc_library (which are detected by looking for
+ // J2ObjcEntryClassProvider). This keeps dependencies between j2objc_libraries strict (Swift
+ // can't indirectly depend on a j2objc_library through another one), but ensures that the
+ // underlying java_library/proto_library dependencies can be imported.
+ for (ConfiguredTargetAndData dep : deps) {
+ ConfiguredTarget target = dep.getConfiguredTarget();
+ if (target.getProvider(J2ObjcEntryClassProvider.class) == null) {
+ ObjcProvider objcProvider = target.get(ObjcProvider.SKYLARK_CONSTRUCTOR);
+ if (objcProvider != null) {
+ repropagatedModuleMapsProviders.add(objcProvider);
+ }
+ }
+ }
+
+ // JRE deps are objc_libraries, so always repropagate them.
+ for (ConfiguredTargetAndData dep : jreDeps) {
+ ConfiguredTarget target = dep.getConfiguredTarget();
+ ObjcProvider objcProvider = target.get(ObjcProvider.SKYLARK_CONSTRUCTOR);
+ if (objcProvider != null) {
+ repropagatedModuleMapsProviders.add(objcProvider);
+ }
+ }
+
+ // Adding the deps and jreDeps here is still required to propagate the rest of the dependencies'
+ // providers' information up the tree (whether transitively or only to direct dependencies,
+ // depending on the key in question). The repropagated module map providers merely decide which
+ // providers should *also* have their module maps re-propagated to the next direct dependency.
return new ObjcCommon.Builder(ruleContext)
.setCompilationAttributes(
CompilationAttributes.Builder.fromRuleContext(ruleContext).build())
- .addDeps(ruleContext.getPrerequisiteConfiguredTargetAndTargets("deps", Mode.TARGET))
- .addDeps(ruleContext.getPrerequisiteConfiguredTargetAndTargets("jre_deps", Mode.TARGET))
+ .addDeps(deps)
+ .addDeps(jreDeps)
.setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext))
.setHasModuleMap()
+ .addRepropagatedModuleMapObjcProviders(repropagatedModuleMapsProviders.build())
.build();
}
@@ -72,24 +109,12 @@ public class J2ObjcLibrary implements RuleConfiguredTargetFactory {
.addEntryClasses(ruleContext.attributes().get("entry_classes", Type.STRING_LIST))
.build();
- Iterable<ObjcProvider> jreDeps =
- ruleContext.getPrerequisites("jre_deps", Mode.TARGET, ObjcProvider.SKYLARK_CONSTRUCTOR);
- ObjcProvider.Builder objcProviderBuilder =
- new ObjcProvider.Builder(ruleContext.getAnalysisEnvironment().getSkylarkSemantics())
- .addTransitiveAndPropagate(jreDeps)
- .addTransitiveAndPropagate(
- ruleContext.getPrerequisites(
- "deps", Mode.TARGET, ObjcProvider.SKYLARK_CONSTRUCTOR));
- for (ObjcProvider prereq : jreDeps) {
- objcProviderBuilder.addTransitiveAndPropagate(JRE_LIBRARY, prereq.get(LIBRARY));
- }
-
- ObjcProvider objcProvider = objcProviderBuilder.build();
+ ObjcCommon common = common(ruleContext);
+ ObjcProvider objcProvider = common.getObjcProvider();
J2ObjcMappingFileProvider j2ObjcMappingFileProvider = J2ObjcMappingFileProvider.union(
ruleContext.getPrerequisites("deps", Mode.TARGET, J2ObjcMappingFileProvider.class));
- ObjcCommon common = common(ruleContext);
CompilationArtifacts moduleMapCompilationArtifacts =
new CompilationArtifacts.Builder()
.setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext))
@@ -101,7 +126,7 @@ public class J2ObjcLibrary implements RuleConfiguredTargetFactory {
.doNotUsePch()
.build()
.registerFullyLinkAction(
- common.getObjcProvider(),
+ objcProvider,
ruleContext.getImplicitOutputArtifact(CompilationSupport.FULLY_LINKED_LIB))
.registerGenerateModuleMapAction(moduleMapCompilationArtifacts)
.validateAttributes();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java
index d4a26a234d..13a915f22a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java
@@ -157,6 +157,7 @@ public final class ObjcCommon {
private Iterable<ObjcProvider> depObjcProviders = ImmutableList.of();
private Iterable<ObjcProvider> directDepObjcProviders = ImmutableList.of();
private Iterable<ObjcProvider> runtimeDepObjcProviders = ImmutableList.of();
+ private Iterable<ObjcProvider> repropagatedModuleMapObjcProviders = ImmutableList.of();
private Iterable<String> defines = ImmutableList.of();
private Iterable<PathFragment> includes = ImmutableList.of();
private Iterable<PathFragment> directDependencyIncludes = ImmutableList.of();
@@ -363,6 +364,22 @@ public final class ObjcCommon {
}
/**
+ * Adds Objc providers whose module maps should be repropagated as if they are directly
+ * associated with the target propagating the provider being built.
+ *
+ * <p>This supports a small number of specialized use cases, like J2Objc, where the module maps
+ * associated with the {@code java_library} (via an aspect) need to be repropagated by the
+ * {@code j2objc_library} that depends on them so that Swift code can access those module maps
+ * for the purposes of strict module map propagation (without propagating the module maps
+ * _fully_ transitively).
+ */
+ Builder addRepropagatedModuleMapObjcProviders(Iterable<ObjcProvider> objcProviders) {
+ this.repropagatedModuleMapObjcProviders =
+ Iterables.concat(this.repropagatedModuleMapObjcProviders, objcProviders);
+ return this;
+ }
+
+ /**
* Adds additional static libraries to be linked into the final ObjC application bundle.
*/
Builder addExtraImportLibraries(Iterable<Artifact> extraImportLibraries) {
@@ -544,13 +561,21 @@ public final class ObjcCommon {
}
}
+ if (useStrictObjcModuleMaps(context)) {
+ for (ObjcProvider provider : repropagatedModuleMapObjcProviders) {
+ objcProvider.addAllForDirectDependents(MODULE_MAP, provider.get(ObjcProvider.MODULE_MAP));
+ objcProvider.addAllForDirectDependents(
+ TOP_LEVEL_MODULE_MAP, provider.get(ObjcProvider.TOP_LEVEL_MODULE_MAP));
+ }
+ }
+
if (hasModuleMap) {
CppModuleMap moduleMap = intermediateArtifacts.moduleMap();
Optional<Artifact> umbrellaHeader = moduleMap.getUmbrellaHeader();
if (umbrellaHeader.isPresent()) {
objcProvider.add(UMBRELLA_HEADER, umbrellaHeader.get());
}
- if (context.getFragment(ObjcConfiguration.class).useStrictObjcModuleMaps()) {
+ if (useStrictObjcModuleMaps(context)) {
objcProvider.addForDirectDependents(MODULE_MAP, moduleMap.getArtifact());
objcProvider.addForDirectDependents(TOP_LEVEL_MODULE_MAP, moduleMap);
} else {
@@ -572,6 +597,13 @@ public final class ObjcCommon {
return new ObjcCommon(objcProvider.build(), compilationArtifacts);
}
+ private static boolean useStrictObjcModuleMaps(RuleContext context) {
+ // We need to check isLegalFragment first because some non-compilation rules, like
+ // objc_bundle_library, don't declare this fragment.
+ return context.isLegalFragment(ObjcConfiguration.class)
+ && context.getFragment(ObjcConfiguration.class).useStrictObjcModuleMaps();
+ }
+
private static boolean isCcLibrary(ConfiguredTargetAndData info) {
try {
String targetName = info.getTarget().getTargetKind();