diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/objc')
6 files changed, 157 insertions, 34 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java index 5bce8689eb..8eff14704d 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java @@ -31,6 +31,7 @@ import com.google.devtools.build.lib.packages.AspectDefinition; import com.google.devtools.build.lib.packages.AspectParameters; import com.google.devtools.build.lib.rules.proto.ProtoCommon; import com.google.devtools.build.lib.rules.proto.ProtoSourcesProvider; +import com.google.devtools.build.lib.vfs.PathFragment; /** * J2ObjC aspect for the proto_library rule. @@ -132,13 +133,18 @@ public abstract class AbstractJ2ObjcProtoAspect implements ConfiguredAspectFacto Iterable<Artifact> generatedSourceFiles = checkShouldCreateSources(ruleContext) ? ProtoCommon.getGeneratedOutputs(ruleContext, protoSources, ".j2objc.pb.m") : ImmutableList.<Artifact>of(); + PathFragment objcFileRootExecPath = ruleContext.getConfiguration().getGenfilesDirectory() + .getExecPath(); + Iterable<PathFragment> headerSearchPaths = J2ObjcLibrary.j2objcSourceHeaderSearchPaths( + ruleContext, objcFileRootExecPath, protoSources); return new J2ObjcSource( ruleContext.getTarget().getLabel(), generatedSourceFiles, ProtoCommon.getGeneratedOutputs(ruleContext, protoSources, ".j2objc.pb.h"), - ruleContext.getConfiguration().getGenfilesDirectory().getExecPath(), - SourceType.PROTO); + objcFileRootExecPath, + SourceType.PROTO, + headerSearchPaths); } private static Iterable<Artifact> headerMappingFiles(RuleContext ruleContext, 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 d3ad0e17d7..be937b45b2 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 @@ -937,7 +937,7 @@ public final class CompilationSupport { registerCompileAndArchiveActions( compilationArtifact, intermediateArtifacts, - objcProvider, + objcProvider.toJ2ObjcOnlyProvider(), moduleMap, ruleContext.getConfiguration().isCodeCoverageEnabled(), false); 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 f6a527bde6..84427d46f8 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 @@ -272,7 +272,7 @@ public class J2ObjcAspect implements ConfiguredAspectFactory { private J2ObjcSource buildJ2ObjcSource(RuleContext ruleContext, Iterable<Artifact> javaInputSourceFiles) { PathFragment objcFileRootRelativePath = ruleContext.getUniqueDirectory("_j2objc"); - PathFragment objcFilePath = ruleContext + PathFragment objcFileRootExecPath = ruleContext .getConfiguration() .getBinFragment() .getRelative(objcFileRootRelativePath); @@ -280,8 +280,16 @@ public class J2ObjcAspect implements ConfiguredAspectFactory { objcFileRootRelativePath, ".m"); Iterable<Artifact> objcHdrs = getOutputObjcFiles(ruleContext, javaInputSourceFiles, objcFileRootRelativePath, ".h"); - return new J2ObjcSource(ruleContext.getRule().getLabel(), objcSrcs, objcHdrs, objcFilePath, - SourceType.JAVA); + Iterable<PathFragment> headerSearchPaths = J2ObjcLibrary.j2objcSourceHeaderSearchPaths( + ruleContext, objcFileRootExecPath, javaInputSourceFiles); + + return new J2ObjcSource( + ruleContext.getRule().getLabel(), + objcSrcs, + objcHdrs, + objcFileRootExecPath, + SourceType.JAVA, + headerSearchPaths); } private Iterable<Artifact> getOutputObjcFiles(RuleContext ruleContext, 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 4555959e2b..e072c0d5d6 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 @@ -60,9 +60,9 @@ public class J2ObjcLibrary implements RuleConfiguredTargetFactory { ObjcProvider.Builder objcProviderBuilder = new ObjcProvider.Builder() - .addTransitiveAndPropagate( + .addJ2ObjcTransitiveAndPropagate( ruleContext.getPrerequisite("$jre_emul_lib", Mode.TARGET, ObjcProvider.class)) - .addTransitiveAndPropagate( + .addJ2ObjcTransitiveAndPropagate( ruleContext.getPrerequisites("deps", Mode.TARGET, ObjcProvider.class)); XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder(); @@ -74,23 +74,17 @@ public class J2ObjcLibrary implements RuleConfiguredTargetFactory { if (j2ObjcSrcsProvider.hasProtos()) { // Public J2 in Bazel provides no protobuf_lib, and if OSS users try to sneakily use // undocumented functionality to reach here, the below code will error. - objcProviderBuilder.addTransitiveAndPropagate( + objcProviderBuilder.addJ2ObjcTransitiveAndPropagate( ruleContext.getPrerequisite("$protobuf_lib", Mode.TARGET, ObjcProvider.class)); xcodeSupport.addDependencies( xcodeProviderBuilder, new Attribute("$protobuf_lib", Mode.TARGET)); } for (J2ObjcSource j2objcSource : j2ObjcSrcsProvider.getSrcs()) { - PathFragment genDirHeaderSearchPath = - new PathFragment( - j2objcSource.getObjcFilePath(), ruleContext.getConfiguration().getGenfilesFragment()); - - objcProviderBuilder.addAll(ObjcProvider.HEADER, j2objcSource.getObjcHdrs()); - objcProviderBuilder.add(ObjcProvider.INCLUDE, j2objcSource.getObjcFilePath()); - objcProviderBuilder.add(ObjcProvider.INCLUDE, genDirHeaderSearchPath); + objcProviderBuilder.addJ2ObjcAll(ObjcProvider.HEADER, j2objcSource.getObjcHdrs()); + objcProviderBuilder.addJ2ObjcAll(ObjcProvider.INCLUDE, j2objcSource.getHeaderSearchPaths()); xcodeProviderBuilder.addHeaders(j2objcSource.getObjcHdrs()); - xcodeProviderBuilder.addUserHeaderSearchPaths( - ImmutableList.of(j2objcSource.getObjcFilePath(), genDirHeaderSearchPath)); + xcodeProviderBuilder.addUserHeaderSearchPaths(j2objcSource.getHeaderSearchPaths()); } if (ObjcRuleClasses.objcConfiguration(ruleContext).moduleMapsEnabled()) { @@ -112,6 +106,30 @@ public class J2ObjcLibrary implements RuleConfiguredTargetFactory { } /** + * Returns header search paths necessary to compile the J2ObjC-generated code from a single + * target. + * + * @param ruleContext the rule context + * @param objcFileRootExecPath the exec path under which all J2ObjC-generated file resides + * @param sourcesToTranslate the source files to be translated by J2ObjC in a single target + */ + public static Iterable<PathFragment> j2objcSourceHeaderSearchPaths(RuleContext ruleContext, + PathFragment objcFileRootExecPath, Iterable<Artifact> sourcesToTranslate) { + PathFragment genRoot = ruleContext.getConfiguration().getGenfilesFragment(); + ImmutableList.Builder<PathFragment> headerSearchPaths = ImmutableList.builder(); + headerSearchPaths.add(objcFileRootExecPath); + // We add another header search path with gen root if we have generated sources to translate. + for (Artifact sourceToTranslate : sourcesToTranslate) { + if (!sourceToTranslate.isSourceArtifact()) { + headerSearchPaths.add(new PathFragment(objcFileRootExecPath, genRoot)); + return headerSearchPaths.build(); + } + } + + return headerSearchPaths.build(); + } + + /** * Configures a module map for all the sources in {@code j2ObjcSrcsProvider}, registering * an action to generate the module map and exposing that module map through {@code objcProvider}. */ diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcSource.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcSource.java index bdc785854a..8d33c15b1b 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcSource.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcSource.java @@ -50,6 +50,7 @@ public class J2ObjcSource { private final Iterable<Artifact> objcHdrs; private final PathFragment objcFilePath; private final SourceType sourceType; + private final Iterable<PathFragment> headerSearchPaths; /** * Constructs a J2ObjcSource containing target information for j2objc transpilation. @@ -60,14 +61,18 @@ public class J2ObjcSource { * @param objcFilePath the {@code PathFragment} under which all the generated objc files are. It * can be used as header search path for objc compilations. * @param sourceType the type of files from which the ObjC files are generated. + * @param headerSearchPaths the {@code Iterable} of header search paths necessary for compiling + * the generated J2ObjC sources in {@link objcSrcs} */ public J2ObjcSource(Label targetLabel, Iterable<Artifact> objcSrcs, - Iterable<Artifact> objcHdrs, PathFragment objcFilePath, SourceType sourceType) { + Iterable<Artifact> objcHdrs, PathFragment objcFilePath, SourceType sourceType, + Iterable<PathFragment> headerSearchPaths) { this.targetLabel = targetLabel; this.objcSrcs = objcSrcs; this.objcHdrs = objcHdrs; this.objcFilePath = objcFilePath; this.sourceType = sourceType; + this.headerSearchPaths = headerSearchPaths; } /** @@ -99,7 +104,8 @@ public class J2ObjcSource { prunedSourceArtifacts.build(), getObjcHdrs(), getObjcFilePath(), - getSourceType()); + getSourceType(), + getHeaderSearchPaths()); } /** @@ -125,13 +131,20 @@ public class J2ObjcSource { /** * Returns the {@code PathFragment} which represents a directory where the generated ObjC files - * reside and which can also be used as header search path in ObjC compilation. + * reside. */ public PathFragment getObjcFilePath() { return objcFilePath; } /** + * Returns a list of header search paths necessary for compiling the generated J2ObjC sources. + */ + public Iterable<PathFragment> getHeaderSearchPaths() { + return headerSearchPaths; + } + + /** * Returns the type of files from which the ObjC files inside this object are generated. */ public SourceType getSourceType() { @@ -156,12 +169,15 @@ public class J2ObjcSource { && Iterators.elementsEqual(this.objcSrcs.iterator(), that.objcSrcs.iterator()) && Iterators.elementsEqual(this.objcHdrs.iterator(), that.objcHdrs.iterator()) && Objects.equal(this.objcFilePath, that.objcFilePath) - && this.sourceType == that.sourceType; + && this.sourceType == that.sourceType + && Iterators.elementsEqual( + this.headerSearchPaths.iterator(), that.headerSearchPaths.iterator()); } @Override public int hashCode() { - return Objects.hashCode(targetLabel, objcSrcs, objcHdrs, objcFilePath, sourceType); + return Objects.hashCode(targetLabel, objcSrcs, objcHdrs, objcFilePath, sourceType, + headerSearchPaths); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java index 85e05dc10f..dbca5e0269 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java @@ -241,11 +241,16 @@ public final class ObjcProvider implements TransitiveInfoProvider { // Items which should be passed to direct dependers, but not transitive dependers. private final ImmutableMap<Key<?>, NestedSet<?>> nonPropagatedItems; + // Items which are relevent only for J2ObjC-translated sources. + private final ImmutableMap<Key<?>, NestedSet<?>> j2ObjcOnlyItems; + private ObjcProvider( ImmutableMap<Key<?>, NestedSet<?>> items, - ImmutableMap<Key<?>, NestedSet<?>> nonPropagatedItems) { + ImmutableMap<Key<?>, NestedSet<?>> nonPropagatedItems, + ImmutableMap<Key<?>, NestedSet<?>> j2ObjcOnlyItems) { this.items = Preconditions.checkNotNull(items); this.nonPropagatedItems = Preconditions.checkNotNull(nonPropagatedItems); + this.j2ObjcOnlyItems = Preconditions.checkNotNull(j2ObjcOnlyItems); } /** @@ -280,12 +285,25 @@ public final class ObjcProvider implements TransitiveInfoProvider { } /** + * Returns a corresponding provider that contains only information relevent for J2ObjC-translated + * code. This trimmed provider offers a view that is used for compilation actions of + * J2ObjC-translated sources to avoid pulling in unnecessary dependent information from the rest + * of the transitive closure. + */ + // TODO(rduan): Roll this back once J2ObjC compilation is moved to the edges in the dep graph. + public ObjcProvider toJ2ObjcOnlyProvider() { + return new ObjcProvider(j2ObjcOnlyItems, ImmutableMap.<Key<?>, NestedSet<?>>of(), + j2ObjcOnlyItems); + } + + /** * A builder for this context with an API that is optimized for collecting information from * several transitive dependencies. */ public static final class Builder { private final Map<Key<?>, NestedSetBuilder<?>> items = new HashMap<>(); private final Map<Key<?>, NestedSetBuilder<?>> nonPropagatedItems = new HashMap<>(); + private final Map<Key<?>, NestedSetBuilder<?>> j2ObjcPropagatedItems = new HashMap<>(); private static void maybeAddEmptyBuilder(Map<Key<?>, NestedSetBuilder<?>> set, Key<?> key) { if (!set.containsKey(key)) { @@ -294,15 +312,14 @@ public final class ObjcProvider implements TransitiveInfoProvider { } @SuppressWarnings({"rawtypes", "unchecked"}) - private void uncheckedAddAll(Key key, Iterable toAdd, boolean propagate) { - Map<Key<?>, NestedSetBuilder<?>> set = propagate ? items : nonPropagatedItems; + private void uncheckedAddAll(Key key, Iterable toAdd, Map<Key<?>, NestedSetBuilder<?>> set) { maybeAddEmptyBuilder(set, key); set.get(key).addAll(toAdd); } @SuppressWarnings({"rawtypes", "unchecked"}) - private void uncheckedAddTransitive(Key key, NestedSet toAdd, boolean propagate) { - Map<Key<?>, NestedSetBuilder<?>> set = propagate ? items : nonPropagatedItems; + private void uncheckedAddTransitive(Key key, NestedSet toAdd, + Map<Key<?>, NestedSetBuilder<?>> set) { maybeAddEmptyBuilder(set, key); set.get(key).addTransitive(toAdd); } @@ -312,7 +329,7 @@ public final class ObjcProvider implements TransitiveInfoProvider { * ObjcProvider. */ public <E> Builder addTransitiveAndPropagate(Key<E> key, NestedSet<E> items) { - uncheckedAddTransitive(key, items, true); + uncheckedAddTransitive(key, items, this.items); return this; } @@ -322,7 +339,26 @@ public final class ObjcProvider implements TransitiveInfoProvider { */ public Builder addTransitiveAndPropagate(ObjcProvider provider) { for (Map.Entry<Key<?>, NestedSet<?>> typeEntry : provider.items.entrySet()) { - uncheckedAddTransitive(typeEntry.getKey(), typeEntry.getValue(), true); + uncheckedAddTransitive(typeEntry.getKey(), typeEntry.getValue(), this.items); + } + for (Map.Entry<Key<?>, NestedSet<?>> typeEntry : provider.j2ObjcOnlyItems.entrySet()) { + uncheckedAddTransitive(typeEntry.getKey(), typeEntry.getValue(), + this.j2ObjcPropagatedItems); + } + return this; + } + + /** + * Add all elements from provider relevent to J2ObjC (providers directly exporting + * J2ObjC-translated code, J2ObjC runtime deps, etc.), and propagate them to any (transitive) + * dependers on this ObjcProvider. + */ + // TODO(rduan): Roll this back once J2ObjC compilation is moved to the edges in the dep graph. + public Builder addJ2ObjcTransitiveAndPropagate(ObjcProvider provider) { + addTransitiveAndPropagate(provider); + for (Map.Entry<Key<?>, NestedSet<?>> typeEntry : provider.items.entrySet()) { + uncheckedAddTransitive(typeEntry.getKey(), typeEntry.getValue(), + this.j2ObjcPropagatedItems); } return this; } @@ -348,6 +384,19 @@ public final class ObjcProvider implements TransitiveInfoProvider { } /** + * Add all elements from providers relevent to J2ObjC (providers directly exporting + * J2ObjC-translated code, J2ObjC runtime deps, etc.), and propagate them to any (transitive) + * dependers on this ObjcProvider. + */ + // TODO(rduan): Roll this back once J2ObjC compilation is moved to the edges in the dep graph. + public Builder addJ2ObjcTransitiveAndPropagate(Iterable<ObjcProvider> providers) { + for (ObjcProvider provider : providers) { + addJ2ObjcTransitiveAndPropagate(provider); + } + return this; + } + + /** * Add elements from providers, but don't propagate them to any dependers on this ObjcProvider. * These elements will be exposed to {@link #get(Key)} calls, but not to any ObjcProviders * which add this provider to themselves. @@ -355,7 +404,7 @@ public final class ObjcProvider implements TransitiveInfoProvider { public Builder addTransitiveWithoutPropagating(Iterable<ObjcProvider> providers) { for (ObjcProvider provider : providers) { for (Map.Entry<Key<?>, NestedSet<?>> typeEntry : provider.items.entrySet()) { - uncheckedAddTransitive(typeEntry.getKey(), typeEntry.getValue(), false); + uncheckedAddTransitive(typeEntry.getKey(), typeEntry.getValue(), this.nonPropagatedItems); } } return this; @@ -365,7 +414,18 @@ public final class ObjcProvider implements TransitiveInfoProvider { * Add element, and propagate it to any (transitive) dependers on this ObjcProvider. */ public <E> Builder add(Key<E> key, E toAdd) { - uncheckedAddAll(key, ImmutableList.of(toAdd), true); + uncheckedAddAll(key, ImmutableList.of(toAdd), this.items); + return this; + } + + /** + * Add element relevent to J2ObjC (elements containing information for J2ObjC-translated code), + * and propagate it to any (transitive) dependers on this ObjcProvider. + */ + // TODO(rduan): Roll this back once J2ObjC compilation is moved to the edges in the dep graph. + public <E> Builder addJ2Objc(Key<E> key, E toAdd) { + uncheckedAddAll(key, ImmutableList.of(toAdd), this.items); + uncheckedAddAll(key, ImmutableList.of(toAdd), this.j2ObjcPropagatedItems); return this; } @@ -373,7 +433,18 @@ public final class ObjcProvider implements TransitiveInfoProvider { * Add elements in toAdd, and propagate them to any (transitive) dependers on this ObjcProvider. */ public <E> Builder addAll(Key<E> key, Iterable<? extends E> toAdd) { - uncheckedAddAll(key, toAdd, true); + uncheckedAddAll(key, toAdd, this.items); + return this; + } + + /** + * Add elements relevent to J2ObjC (elements containing information for J2ObjC-translated code), + * and propagate them to any (transitive) dependers on this ObjcProvider. + */ + // TODO(rduan): Roll this back once J2ObjC compilation is moved to the edges in the dep graph. + public <E> Builder addJ2ObjcAll(Key<E> key, Iterable<? extends E> toAdd) { + uncheckedAddAll(key, toAdd, this.items); + uncheckedAddAll(key, toAdd, this.j2ObjcPropagatedItems); return this; } @@ -386,7 +457,11 @@ public final class ObjcProvider implements TransitiveInfoProvider { for (Map.Entry<Key<?>, NestedSetBuilder<?>> typeEntry : nonPropagatedItems.entrySet()) { nonPropagated.put(typeEntry.getKey(), typeEntry.getValue().build()); } - return new ObjcProvider(propagated.build(), nonPropagated.build()); + ImmutableMap.Builder<Key<?>, NestedSet<?>> j2ObjcPropagated = new ImmutableMap.Builder<>(); + for (Map.Entry<Key<?>, NestedSetBuilder<?>> typeEntry : j2ObjcPropagatedItems.entrySet()) { + j2ObjcPropagated.put(typeEntry.getKey(), typeEntry.getValue().build()); + } + return new ObjcProvider(propagated.build(), nonPropagated.build(), j2ObjcPropagated.build()); } } } |