aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java
diff options
context:
space:
mode:
authorGravatar Michael Thvedt <mthvedt@google.com>2015-09-18 17:09:02 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2015-09-21 08:59:14 +0000
commitf081184097239243b436f96774b63b010d5e021f (patch)
tree3c145b4d0bae5768a0ea4935e838dced3f78d7f9 /src/main/java
parentee26ee1c5b4a10ca6bb401e0dafaea0026de4ab9 (diff)
Enable j2objc_library proto aspect for Bazel. Note that the remote j2objc workspace hasn't been set up yet.
RELNOTES: j2objc_library on Bazel now transpiles transitive proto_library dependencies. (Note that java_* rules in Bazel do not yet support protos; currently they ignore proto dependencies.) -- MOS_MIGRATED_REVID=103392720
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java179
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcProtoAspect.java103
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibrary.java18
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibraryBaseRule.java2
6 files changed, 295 insertions, 15 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java
index 58d79c60fd..f23d62dcbe 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java
@@ -128,6 +128,8 @@ public class BazelJavaRuleClasses {
"genproto", // TODO(bazel-team): we should filter using providers instead (skylark rule).
"java_import",
"java_library",
+ // There is no Java protoc for Bazel--yet. This is here for the benefit of J2 protos.
+ "proto_library",
"sh_binary",
"sh_library");
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
new file mode 100644
index 0000000000..fa976a159c
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AbstractJ2ObjcProtoAspect.java
@@ -0,0 +1,179 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.devtools.build.lib.rules.objc.J2ObjcSource.SourceType;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.Aspect;
+import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+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.syntax.Label;
+
+/**
+ * J2ObjC aspect for the proto_library rule.
+ *
+ * <p>J2ObjC proto is different from other proto languages in that it needs to implement both the
+ * Java API and the Objective-C API. The Java API implementation is needed for compatibility with
+ * ObjC code translated by J2ObjC from Java. The Objective-C API is also required for compatibility
+ * with hand-written ObjC code. As an example, for an accessor of a int field called int_value in
+ * message Foo, both the Java API version (getIntValue) and the ObjC version (intValue) are needed.
+ *
+ * <p>On the whole, the dependency chain looks like: objc_binary -> objc_library -> j2objc_library
+ * -> java_library -> proto_library. The jars containing compiled Java protos provided by
+ * proto_library are needed in the classpath for J2ObjC transpilation in java_library, but they
+ * themselves are not transpiled or exported to objc_* rules. Instead, the J2ObjC protos generated
+ * by this class and provided by proto_library will be exported all the way to objc_binary for ObjC
+ * compilation and linking into the final application bundle.
+ */
+public abstract class AbstractJ2ObjcProtoAspect implements ConfiguredAspectFactory {
+ public static final String NAME = "J2ObjcProtoAspect";
+
+ public AspectDefinition getDefinition() {
+ AspectDefinition.Builder builder = new AspectDefinition.Builder("J2ObjcProtoAspect")
+ .requireProvider(ProtoSourcesProvider.class)
+ .attributeAspect("deps", getClass())
+ .attributeAspect("exports", getClass())
+ .attributeAspect("runtime_deps", getClass());
+ return addAdditionalAttributes(builder).build();
+ }
+
+ protected abstract AspectDefinition.Builder addAdditionalAttributes(
+ AspectDefinition.Builder builder);
+
+ protected static Label parseLabel(String from) {
+ try {
+ return Label.parseAbsolute(from);
+ } catch (LabelSyntaxException e) {
+ throw new IllegalArgumentException(from);
+ }
+ }
+
+ protected abstract boolean checkShouldCreateAspect(RuleContext ruleContext);
+
+ @Override
+ public Aspect create(ConfiguredTarget base, RuleContext ruleContext,
+ AspectParameters parameters) {
+ if (!checkShouldCreateAspect(ruleContext)) {
+ return new Aspect.Builder(NAME).build();
+ }
+
+ ProtoSourcesProvider protoSourcesProvider = base.getProvider(ProtoSourcesProvider.class);
+ ImmutableList<Artifact> protoSources = protoSourcesProvider.getProtoSources();
+ NestedSet<Artifact> transitiveImports = protoSourcesProvider.getTransitiveImports();
+
+ J2ObjcSrcsProvider.Builder srcsBuilder = new J2ObjcSrcsProvider.Builder();
+ Iterable<Artifact> headerMappingFiles;
+ Iterable<Artifact> classMappingFiles;
+
+ if (protoSources.isEmpty()) {
+ headerMappingFiles = ImmutableList.of();
+ classMappingFiles = ImmutableList.of();
+ } else {
+ J2ObjcSource j2ObjcSource = j2ObjcSource(ruleContext, protoSources);
+ headerMappingFiles = headerMappingFiles(ruleContext, protoSources);
+ classMappingFiles = classMappingFiles(ruleContext, protoSources);
+ srcsBuilder.addSource(j2ObjcSource);
+
+ createActions(base, ruleContext, protoSources, transitiveImports,
+ headerMappingFiles, classMappingFiles, j2ObjcSource);
+ }
+
+ J2ObjcSrcsProvider j2objcSrcsProvider = srcsBuilder
+ .addTransitiveJ2ObjcSrcs(ruleContext, "deps")
+ .build();
+ NestedSet<Artifact> j2ObjcTransitiveHeaderMappingFiles = j2ObjcTransitiveHeaderMappingFiles(
+ ruleContext, headerMappingFiles);
+ NestedSet<Artifact> j2ObjcTransitiveClassMappingFiles = j2ObjcTransitiveClassMappingFiles(
+ ruleContext, classMappingFiles);
+
+ return new Aspect.Builder(NAME)
+ .addProvider(J2ObjcSrcsProvider.class, j2objcSrcsProvider)
+ .addProvider(
+ J2ObjcMappingFileProvider.class,
+ new J2ObjcMappingFileProvider(
+ j2ObjcTransitiveHeaderMappingFiles,
+ j2ObjcTransitiveClassMappingFiles,
+ NestedSetBuilder.<Artifact>stableOrder().build()))
+ .build();
+ }
+
+ protected abstract void createActions(ConfiguredTarget base, RuleContext ruleContext,
+ Iterable<Artifact> protoSources, NestedSet<Artifact> transitiveProtoSources,
+ Iterable<Artifact> headerMappingFiles, Iterable<Artifact> classMappingFiles,
+ J2ObjcSource j2ObjcSource);
+
+ protected abstract boolean checkShouldCreateSources(RuleContext ruleContext);
+
+ private J2ObjcSource j2ObjcSource(RuleContext ruleContext,
+ ImmutableList<Artifact> protoSources) {
+ Iterable<Artifact> generatedSourceFiles = checkShouldCreateSources(ruleContext)
+ ? ProtoCommon.getGeneratedOutputs(ruleContext, protoSources, ".j2objc.pb.m")
+ : ImmutableList.<Artifact>of();
+
+ return new J2ObjcSource(
+ ruleContext.getTarget().getLabel(),
+ generatedSourceFiles,
+ ProtoCommon.getGeneratedOutputs(ruleContext, protoSources, ".j2objc.pb.h"),
+ ruleContext.getConfiguration().getGenfilesDirectory().getExecPath(),
+ SourceType.PROTO);
+ }
+
+ private static Iterable<Artifact> headerMappingFiles(RuleContext ruleContext,
+ ImmutableList<Artifact> protoSources) {
+ return ProtoCommon.getGeneratedOutputs(ruleContext, protoSources, ".j2objc.mapping");
+ }
+
+ private static Iterable<Artifact> classMappingFiles(RuleContext ruleContext,
+ ImmutableList<Artifact> protoSources) {
+ return ProtoCommon.getGeneratedOutputs(ruleContext, protoSources, ".clsmap.properties");
+ }
+
+ private static NestedSet<Artifact> j2ObjcTransitiveHeaderMappingFiles(RuleContext ruleContext,
+ Iterable<Artifact> headerMappingFiles) {
+ NestedSetBuilder<Artifact> mappingFileBuilder = NestedSetBuilder.stableOrder();
+ mappingFileBuilder.addAll(headerMappingFiles);
+
+ for (J2ObjcMappingFileProvider provider :
+ ruleContext.getPrerequisites("deps", Mode.TARGET, J2ObjcMappingFileProvider.class)) {
+ mappingFileBuilder.addTransitive(provider.getHeaderMappingFiles());
+ }
+
+ return mappingFileBuilder.build();
+ }
+
+ private static NestedSet<Artifact> j2ObjcTransitiveClassMappingFiles(RuleContext ruleContext,
+ Iterable<Artifact> classMappingFiles) {
+ NestedSetBuilder<Artifact> mappingFileBuilder = NestedSetBuilder.stableOrder();
+ mappingFileBuilder.addAll(classMappingFiles);
+
+ for (J2ObjcMappingFileProvider provider :
+ ruleContext.getPrerequisites("deps", Mode.TARGET, J2ObjcMappingFileProvider.class)) {
+ mappingFileBuilder.addTransitive(provider.getClassMappingFiles());
+ }
+
+ return mappingFileBuilder.build();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcProtoAspect.java
new file mode 100644
index 0000000000..1103aee7ff
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcProtoAspect.java
@@ -0,0 +1,103 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.rules.objc;
+
+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 com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.vfs.PathFragment;
+
+/**
+ * An aspect that transpiles .proto dependencies using the J2ObjC proto plugin,
+ * //tools/objc:compile_protos and //tools/objc:proto_support. N.B.: These two tools
+ * have not yet been released into open-source.
+ */
+public class BazelJ2ObjcProtoAspect extends AbstractJ2ObjcProtoAspect {
+
+ @Override
+ protected AspectDefinition.Builder addAdditionalAttributes(AspectDefinition.Builder builder) {
+ return builder
+ .add(attr("$protoc_darwin", LABEL)
+ .cfg(HOST)
+ .exec()
+ .value(parseLabel("//tools/objc:compile_protos")))
+ .add(attr("$protoc_support_darwin", LABEL)
+ .cfg(HOST)
+ .exec()
+ .value(parseLabel("//tools/objc:proto_support")))
+ .add(attr("$j2objc_plugin", LABEL)
+ .cfg(HOST)
+ .exec()
+ .value(parseLabel(
+ "//third_party/java/j2objc:proto_plugin")));
+ }
+
+ @Override
+ protected boolean checkShouldCreateAspect(RuleContext ruleContext) {
+ return true;
+ }
+
+ protected void createActions(ConfiguredTarget base, RuleContext ruleContext,
+ Iterable<Artifact> protoSources, NestedSet<Artifact> transitiveProtoSources,
+ Iterable<Artifact> headerMappingFiles, Iterable<Artifact> classMappingFiles,
+ J2ObjcSource j2ObjcSource) {
+ String genDir = ruleContext.getConfiguration().getGenfilesDirectory().getExecPathString();
+ Artifact compiler = ruleContext.getPrerequisiteArtifact(
+ "$protoc_darwin", Mode.HOST);
+ Artifact j2objcPlugin = ruleContext.getPrerequisiteArtifact("$j2objc_plugin", Mode.HOST);
+
+ ruleContext.registerAction(new SpawnAction.Builder()
+ .setMnemonic("TranslatingJ2ObjcProtos")
+ .addInput(compiler)
+ .addInput(j2objcPlugin)
+ .addInputs(ruleContext.getPrerequisiteArtifacts(
+ "$protoc_support_darwin", Mode.HOST).list())
+ .addInputs(protoSources)
+ .addTransitiveInputs(transitiveProtoSources)
+ .addOutputs(j2ObjcSource.getObjcSrcs())
+ .addOutputs(j2ObjcSource.getObjcHdrs())
+ .addOutputs(headerMappingFiles)
+ .addOutputs(classMappingFiles)
+ .setExecutable(new PathFragment("/usr/bin/python"))
+ .setCommandLine(new CustomCommandLine.Builder()
+ .add(compiler.getPath().toString())
+ .add("-w")
+ .add(compiler.getRoot().getPath().toString())
+ .add("--generate-j2objc")
+ .add("--generator-param=file_dir_mapping")
+ .add("--generator-param=generate_class_mappings")
+ .add("--j2objc-plugin=" + j2objcPlugin.getExecPathString())
+ .add("--output-dir=" + genDir)
+ .addExecPaths(protoSources)
+ .build())
+ .setExecutionInfo(ImmutableMap.of(ExecutionRequirements.REQUIRES_DARWIN, ""))
+ .build(ruleContext));
+ }
+
+ @Override
+ protected boolean checkShouldCreateSources(RuleContext ruleContext) {
+ return true;
+ }
+}
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 0b15f5dbf3..48ed58fb0e 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
@@ -59,9 +59,9 @@ public class J2ObjcAspect implements ConfiguredAspectFactory {
* Adds the attribute aspect args to the given AspectDefinition.Builder.
*/
protected AspectDefinition.Builder addAttributeAspects(AspectDefinition.Builder builder) {
- return builder.attributeAspect("deps", J2ObjcAspect.class)
- .attributeAspect("exports", J2ObjcAspect.class)
- .attributeAspect("runtime_deps", J2ObjcAspect.class);
+ return builder.attributeAspect("deps", J2ObjcAspect.class, BazelJ2ObjcProtoAspect.class)
+ .attributeAspect("exports", J2ObjcAspect.class, BazelJ2ObjcProtoAspect.class)
+ .attributeAspect("runtime_deps", J2ObjcAspect.class, BazelJ2ObjcProtoAspect.class);
}
@Override
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 bb88b2f539..88a66c4138 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
@@ -72,18 +72,12 @@ public class J2ObjcLibrary implements RuleConfiguredTargetFactory {
.addDependencies(xcodeProviderBuilder, new Attribute("deps", Mode.TARGET));
if (j2ObjcSrcsProvider.hasProtos()) {
- if (ruleContext.attributes().has("$protobuf_lib", BuildType.LABEL)) {
- objcProviderBuilder.addTransitiveAndPropagate(
- ruleContext.getPrerequisite("$protobuf_lib", Mode.TARGET, ObjcProvider.class));
- xcodeSupport.addDependencies(
- xcodeProviderBuilder, new Attribute("$protobuf_lib", Mode.TARGET));
- } else {
- // In theory no Bazel rule should ever provide protos, because they're not supported yet.
- // If we reach here, it's a programming error, not a rule error.
- throw new IllegalStateException(
- "Found protos in the dependencies of rule " + ruleContext.getLabel() + ", "
- + "but protos are not supported in Bazel.");
- }
+ // 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(
+ ruleContext.getPrerequisite("$protobuf_lib", Mode.TARGET, ObjcProvider.class));
+ xcodeSupport.addDependencies(
+ xcodeProviderBuilder, new Attribute("$protobuf_lib", Mode.TARGET));
}
for (J2ObjcSource j2objcSource : j2ObjcSrcsProvider.getSrcs()) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibraryBaseRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibraryBaseRule.java
index a0825f6d5f..9bcfcea3d0 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibraryBaseRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibraryBaseRule.java
@@ -47,6 +47,8 @@ public class J2ObjcLibraryBaseRule implements RuleDefinition {
.add(attr("entry_classes", STRING_LIST))
.add(attr("$jre_emul_lib", LABEL)
.value(env.getLabel("//third_party/java/j2objc:jre_emul_lib")))
+ .add(attr("$protobuf_lib", LABEL)
+ .value(env.getLabel("//third_party/java/j2objc:proto_runtime")))
.build();
}