diff options
author | allevato <allevato@google.com> | 2018-04-05 09:46:55 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-04-05 09:48:42 -0700 |
commit | e1ed9e9e567334fdf7c26cd0db6f20c64840f119 (patch) | |
tree | 5ef5b93f36dc499b64bb5d3f3aed9bcec8e822cb /src/main/java/com/google/devtools/build/lib | |
parent | d7829b1cb0cfbafe10a70c0a4868158dba46b27a (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')
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(); |