aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/objc
diff options
context:
space:
mode:
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/AbstractJ2ObjcProtoAspect.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java14
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibrary.java42
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcSource.java26
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java97
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());
}
}
}