aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Michael Thvedt <mthvedt@google.com>2015-06-18 17:56:11 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2015-06-19 11:04:17 +0000
commitca4e13ac57d5c4c44cc4e4618522799cfde96ab3 (patch)
tree0d66f3ab4195c8aee1c0ca95bf7b91619cb1ebd0
parentad26d68e108b92e529c9f91c5ac812451660af4d (diff)
Move J2ObjCLibrary and supporting classes to Bazel, and enable J2ObJC in Bazel.
-- MOS_MIGRATED_REVID=96324830
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/J2ObjcCommandLineOptions.java (renamed from src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcCommandLineOptions.java)10
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/J2ObjcConfiguration.java (renamed from src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java)6
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryRule.java55
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java282
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibrary.java110
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibraryBaseRule.java79
10 files changed, 554 insertions, 8 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
index dabf2fe27c..dfbcc4244a 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
@@ -80,6 +80,8 @@ import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppConfigurationLoader;
import com.google.devtools.build.lib.rules.cpp.CppOptions;
import com.google.devtools.build.lib.rules.genquery.GenQueryRule;
+import com.google.devtools.build.lib.rules.java.J2ObjcCommandLineOptions;
+import com.google.devtools.build.lib.rules.java.J2ObjcConfiguration;
import com.google.devtools.build.lib.rules.java.JavaConfiguration;
import com.google.devtools.build.lib.rules.java.JavaConfigurationLoader;
import com.google.devtools.build.lib.rules.java.JavaCpuSupplier;
@@ -88,13 +90,13 @@ import com.google.devtools.build.lib.rules.java.JavaOptions;
import com.google.devtools.build.lib.rules.java.JavaToolchainRule;
import com.google.devtools.build.lib.rules.java.Jvm;
import com.google.devtools.build.lib.rules.java.JvmConfigurationLoader;
+import com.google.devtools.build.lib.rules.objc.BazelJ2ObjcLibraryRule;
import com.google.devtools.build.lib.rules.objc.ExperimentalIosTestRule;
import com.google.devtools.build.lib.rules.objc.IosApplicationRule;
import com.google.devtools.build.lib.rules.objc.IosDeviceRule;
import com.google.devtools.build.lib.rules.objc.IosExtensionBinaryRule;
import com.google.devtools.build.lib.rules.objc.IosExtensionRule;
-import com.google.devtools.build.lib.rules.objc.J2ObjcCommandLineOptions;
-import com.google.devtools.build.lib.rules.objc.J2ObjcConfiguration;
+import com.google.devtools.build.lib.rules.objc.J2ObjcLibraryBaseRule;
import com.google.devtools.build.lib.rules.objc.ObjcBinaryRule;
import com.google.devtools.build.lib.rules.objc.ObjcBuildInfoFactory;
import com.google.devtools.build.lib.rules.objc.ObjcBundleLibraryRule;
@@ -329,6 +331,8 @@ public class BazelRuleClassProvider {
builder.addRuleDefinition(new IosApplicationRule());
builder.addRuleDefinition(new IosExtensionBinaryRule());
builder.addRuleDefinition(new IosExtensionRule());
+ builder.addRuleDefinition(new J2ObjcLibraryBaseRule());
+ builder.addRuleDefinition(new BazelJ2ObjcLibraryRule());
builder.addRuleDefinition(new BazelExtraActionRule());
builder.addRuleDefinition(new BazelActionListenerRule());
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java
index acc91733ac..6e7f85a8a9 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java
@@ -25,6 +25,10 @@ import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.bazel.rules.java.BazelJavaRuleClasses.JavaRule;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder;
+import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
+import com.google.devtools.build.lib.rules.java.J2ObjcConfiguration;
+import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
+import com.google.devtools.build.lib.rules.java.JavaConfiguration;
import com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider;
/**
@@ -35,6 +39,8 @@ public final class BazelJavaLibraryRule implements RuleDefinition {
public RuleClass build(Builder builder, final RuleDefinitionEnvironment env) {
return builder
+ .requiresConfigurationFragments(
+ JavaConfiguration.class, CppConfiguration.class, J2ObjcConfiguration.class)
/* <!-- #BLAZE_RULE(java_library).IMPLICIT_OUTPUTS -->
<ul>
<li><code>lib<var>name</var>.jar</code>: A Java archive containing the class files.</li>
@@ -144,6 +150,7 @@ public final class BazelJavaLibraryRule implements RuleDefinition {
.add(attr("exported_plugins", LABEL_LIST).cfg(HOST).allowedRuleClasses("java_plugin")
.legacyAllowAnyFileType())
.advertiseProvider(JavaSourceInfoProvider.class)
+ .advertiseProvider(JavaCompilationArgsProvider.class)
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcCommandLineOptions.java b/src/main/java/com/google/devtools/build/lib/rules/java/J2ObjcCommandLineOptions.java
index 7d1f88b4d4..6c09c84dd7 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcCommandLineOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/J2ObjcCommandLineOptions.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.devtools.build.lib.rules.objc;
+package com.google.devtools.build.lib.rules.java;
import com.google.common.collect.Multimap;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
@@ -23,15 +23,17 @@ import com.google.devtools.common.options.Option;
import java.util.List;
/**
- * Command-line Options for J2ObjC translation of Java source code to ObjC.
+ * Command-line options for J2ObjC translation of Java source code to ObjC.
+ * These command line options are used by Java rules that can be transpiled
+ * (specifically, J2ObjCAspects thereof).
*/
public class J2ObjcCommandLineOptions extends FragmentOptions {
@Option(name = "j2objc_translation_flags",
converter = Converters.CommaSeparatedOptionListConverter.class,
allowMultiple = true,
defaultValue = "",
- category = "undocumented",
- help = "Specifies the translation flags for the J2ObjC transpiler."
+ category = "flags",
+ help = "Additional options to pass to the J2ObjC tool."
)
public List<String> translationFlags;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/java/J2ObjcConfiguration.java
index afb3038169..9a24e446a0 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/J2ObjcConfiguration.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.devtools.build.lib.rules.objc;
+package com.google.devtools.build.lib.rules.java;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
@@ -28,7 +28,9 @@ import java.util.Collections;
import java.util.Set;
/**
- * A J2ObjC transpiler configuration containing J2ObjC translation flags.
+ * A J2ObjC transpiler configuration fragment containing J2ObjC translation flags.
+ * This configuration fragment is used by Java rules that can be transpiled
+ * (specifically, J2ObjCAspects thereof).
*/
public class J2ObjcConfiguration extends Fragment {
/**
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java
index 8db95eb81e..dc195c78ae 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java
@@ -27,6 +27,7 @@ import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder;
import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
+import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
/**
* A base rule for building the java_import rule.
@@ -36,6 +37,8 @@ public class JavaImportBaseRule implements RuleDefinition {
@Override
public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
return builder
+ .requiresConfigurationFragments(JavaConfiguration.class, CppConfiguration.class,
+ J2ObjcConfiguration.class)
.add(attr(":host_jdk", LABEL)
.cfg(HOST)
.value(JavaSemantics.HOST_JDK))
@@ -71,6 +74,7 @@ public class JavaImportBaseRule implements RuleDefinition {
.add(attr("constraints", STRING_LIST)
.orderIndependent()
.nonconfigurable("used in Attribute.validityPredicate implementations (loading time)"))
+ .advertiseProvider(JavaSourceInfoProvider.class)
.advertiseProvider(JavaCompilationArgsProvider.class)
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryRule.java
new file mode 100644
index 0000000000..a976b688a4
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryRule.java
@@ -0,0 +1,55 @@
+// Copyright 2015 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.attr;
+import static com.google.devtools.build.lib.packages.Type.LABEL_LIST;
+
+import com.google.devtools.build.lib.analysis.RuleDefinition;
+import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.packages.RuleClass;
+import com.google.devtools.build.lib.packages.RuleClass.Builder;
+
+/**
+ * Concrete implementation of J2ObjCLibraryBaseRule.
+ */
+public class BazelJ2ObjcLibraryRule implements RuleDefinition {
+
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
+ return builder
+ /* <!-- #BLAZE_RULE(j2objc_library).ATTRIBUTE(deps) -->
+ A list of <code>j2objc_library</code>, <code>java_library</code>
+ and <code>java_import</code> targets that contain
+ Java files to be transpiled to Objective-C.
+ ${SYNOPSIS}
+ <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
+ .add(attr("deps", LABEL_LIST)
+ .aspect(J2ObjcAspect.class)
+ .direct_compile_time_input()
+ .allowedRuleClasses("j2objc_library", "java_library", "java_import")
+ .allowedFileTypes())
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("j2objc_library")
+ .factoryClass(J2ObjcLibrary.class)
+ .ancestors(J2ObjcLibraryBaseRule.class)
+ .build();
+ }
+}
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 4a7bb7f401..1f346ed7a7 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
@@ -56,6 +56,7 @@ import com.google.devtools.build.lib.analysis.config.CompilationMode;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.rules.cpp.LinkerInputs;
+import com.google.devtools.build.lib.rules.java.J2ObjcConfiguration;
import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes;
import com.google.devtools.build.lib.rules.objc.XcodeProvider.Builder;
import com.google.devtools.build.lib.shell.ShellUtils;
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
new file mode 100644
index 0000000000..99bdfb4e22
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
@@ -0,0 +1,282 @@
+// Copyright 2015 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.Type.LABEL;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+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.analysis.TransitiveInfoCollection;
+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.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.packages.Type;
+import com.google.devtools.build.lib.rules.java.J2ObjcConfiguration;
+import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
+import com.google.devtools.build.lib.rules.java.JavaCompilationHelper;
+import com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider;
+import com.google.devtools.build.lib.rules.java.Jvm;
+import com.google.devtools.build.lib.rules.objc.J2ObjcSource.SourceType;
+import com.google.devtools.build.lib.syntax.Label;
+import com.google.devtools.build.lib.syntax.Label.SyntaxException;
+import com.google.devtools.build.lib.util.FileType;
+import com.google.devtools.build.lib.vfs.PathFragment;
+
+import java.util.List;
+
+/**
+ * J2ObjC transpilation aspect for Java rules.
+ */
+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);
+ }
+
+ @Override
+ public AspectDefinition getDefinition() {
+ return addAttributeAspects(new AspectDefinition.Builder("J2ObjCAspect"))
+ .requireProvider(JavaSourceInfoProvider.class)
+ .requireProvider(JavaCompilationArgsProvider.class)
+ .add(attr("$j2objc", LABEL).cfg(HOST).exec()
+ .value(parseLabel("//tools/j2objc:j2objc_deploy.jar")))
+ .add(attr("$j2objc_wrapper", LABEL)
+ .allowedFileTypes(FileType.of(".py"))
+ .cfg(HOST)
+ .exec()
+ .singleArtifact()
+ .value(parseLabel("//tools/j2objc:j2objc_wrapper")))
+ .build();
+ }
+
+ private static Label parseLabel(String from) {
+ try {
+ return Label.parseAbsolute(from);
+ } catch (SyntaxException e) {
+ throw new IllegalArgumentException(from);
+ }
+ }
+
+ @Override
+ public Aspect create(ConfiguredTarget base, RuleContext ruleContext) {
+ Aspect.Builder builder = new Aspect.Builder();
+
+ JavaCompilationArgsProvider compilationArgsProvider =
+ base.getProvider(JavaCompilationArgsProvider.class);
+ JavaSourceInfoProvider sourceInfoProvider =
+ base.getProvider(JavaSourceInfoProvider.class);
+
+ ImmutableSet<Artifact> javaInputFiles = ImmutableSet.<Artifact>builder()
+ .addAll(sourceInfoProvider.getSourceFiles())
+ .addAll(sourceInfoProvider.getSourceJars())
+ .addAll(sourceInfoProvider.getSourceJarsForJarFiles())
+ .build();
+
+ NestedSetBuilder<Artifact> depsHeaderMappingsBuilder = NestedSetBuilder.stableOrder();
+ NestedSetBuilder<Artifact> depsClassMappingsBuilder = NestedSetBuilder.stableOrder();
+ NestedSetBuilder<Artifact> depsDependencyMappingsBuilder = NestedSetBuilder.stableOrder();
+
+ for (J2ObjcMappingFileProvider provider : getJ2ObjCMappings(ruleContext)) {
+ depsHeaderMappingsBuilder.addTransitive(provider.getHeaderMappingFiles());
+ depsClassMappingsBuilder.addTransitive(provider.getClassMappingFiles());
+ depsDependencyMappingsBuilder.addTransitive(provider.getDependencyMappingFiles());
+ }
+
+ NestedSet<Artifact> depsHeaderMappings = depsHeaderMappingsBuilder.build();
+ NestedSet<Artifact> depsClassMappings = depsClassMappingsBuilder.build();
+ NestedSet<Artifact> depsDependencyMappings = depsDependencyMappingsBuilder.build();
+
+ J2ObjcSrcsProvider.Builder srcsBuilder = new J2ObjcSrcsProvider.Builder();
+ J2ObjcMappingFileProvider j2ObjcMappingFileProvider;
+
+ if (!javaInputFiles.isEmpty()) {
+ J2ObjcSource j2ObjcSource = buildJ2ObjcSource(ruleContext, javaInputFiles);
+
+ createJ2ObjcTranspilationAction(ruleContext, depsHeaderMappings, depsClassMappings,
+ javaInputFiles, compilationArgsProvider, j2ObjcSource);
+
+ // J2ObjC merges all input header mapping files into the output header mapping file, so we
+ // only need to export the output header mapping file here.
+ NestedSet<Artifact> headerMappingFiles = NestedSetBuilder.<Artifact>stableOrder()
+ .add(j2ObjcOutputHeaderMappingFile(ruleContext))
+ .build();
+ NestedSet<Artifact> dependencyMappingFiles = NestedSetBuilder.<Artifact>stableOrder()
+ .add(j2ObjcOutputDependencyMappingFile(ruleContext))
+ .addTransitive(depsDependencyMappings)
+ .build();
+
+ srcsBuilder.addSource(j2ObjcSource);
+ j2ObjcMappingFileProvider = new J2ObjcMappingFileProvider(
+ headerMappingFiles, depsClassMappings, dependencyMappingFiles);
+ } else {
+ j2ObjcMappingFileProvider = new J2ObjcMappingFileProvider(
+ depsHeaderMappings, depsClassMappings, depsDependencyMappings);
+ }
+
+ for (J2ObjcSrcsProvider provider :
+ ruleContext.getPrerequisites("exports", Mode.TARGET, J2ObjcSrcsProvider.class)) {
+ srcsBuilder.addTransitive(provider);
+ }
+
+ srcsBuilder.addTransitiveFromDeps(ruleContext);
+
+ return builder
+ .addProvider(J2ObjcSrcsProvider.class, srcsBuilder.build())
+ .addProvider(J2ObjcMappingFileProvider.class, j2ObjcMappingFileProvider)
+ .build();
+ }
+
+ private static void createJ2ObjcTranspilationAction(
+ RuleContext ruleContext,
+ NestedSet<Artifact> depsHeaderMappingFiles,
+ NestedSet<Artifact> depsClassMappingFiles,
+ Iterable<Artifact> sources,
+ JavaCompilationArgsProvider compArgsProvider,
+ J2ObjcSource j2ObjcSource) {
+ CustomCommandLine.Builder argBuilder = CustomCommandLine.builder();
+ PathFragment javaExecutable = ruleContext.getHostConfiguration().getFragment(Jvm.class)
+ .getJavaExecutable();
+ argBuilder.add("--java").add(javaExecutable.getPathString());
+
+ Artifact j2ObjcDeployJar = ruleContext.getPrerequisiteArtifact("$j2objc", Mode.HOST);
+ argBuilder.addExecPath("--j2objc", j2ObjcDeployJar);
+
+ argBuilder.add("--main_class").add("com.google.devtools.j2objc.J2ObjC");
+ argBuilder.addJoinExecPaths("--translated_source_files", ",", j2ObjcSource.getObjcSrcs());
+ argBuilder.add("--objc_file_path").addPath(j2ObjcSource.getObjcFilePath());
+
+ Artifact outputDependencyMappingFile = j2ObjcOutputDependencyMappingFile(ruleContext);
+ argBuilder.addExecPath("--output_dependency_mapping_file", outputDependencyMappingFile);
+
+ Iterable<String> translationFlags = ruleContext
+ .getFragment(J2ObjcConfiguration.class)
+ .getTranslationFlags();
+ argBuilder.add(translationFlags);
+
+ if (!depsHeaderMappingFiles.isEmpty()) {
+ argBuilder.addJoinExecPaths("--header-mapping", ",", depsHeaderMappingFiles);
+ }
+
+ Artifact outputHeaderMappingFile = j2ObjcOutputHeaderMappingFile(ruleContext);
+ argBuilder.addExecPath("--output-header-mapping", outputHeaderMappingFile);
+
+ if (!depsClassMappingFiles.isEmpty()) {
+ argBuilder.addJoinExecPaths("--mapping", ",", depsClassMappingFiles);
+ }
+
+ argBuilder.add("-d").addPath(j2ObjcSource.getObjcFilePath());
+
+ // In J2ObjC, the jars you pass as dependencies must be precisely the same as the
+ // jars used to transpile those dependencies--we cannot use ijars here.
+ NestedSet<Artifact> compileTimeJars =
+ compArgsProvider.getRecursiveJavaCompilationArgs().getRuntimeJars();
+ if (!compileTimeJars.isEmpty()) {
+ argBuilder.addJoinExecPaths("-classpath", ":", compileTimeJars);
+ }
+
+ argBuilder.addExecPaths(sources);
+
+ SpawnAction.Builder builder = new SpawnAction.Builder()
+ .setMnemonic("TranspilingJ2objc")
+ .setExecutable(ruleContext.getPrerequisiteArtifact("$j2objc_wrapper", Mode.HOST))
+ .addInput(ruleContext.getPrerequisiteArtifact("$j2objc_wrapper", Mode.HOST))
+ .addInput(j2ObjcDeployJar)
+ .addInputs(sources)
+ .addTransitiveInputs(compileTimeJars)
+ .addInputs(JavaCompilationHelper.getHostJavabaseInputs(ruleContext))
+ .addTransitiveInputs(depsHeaderMappingFiles)
+ .addTransitiveInputs(depsClassMappingFiles)
+ .setCommandLine(argBuilder.build())
+ .addOutputs(j2ObjcSource.getObjcSrcs())
+ .addOutputs(j2ObjcSource.getObjcHdrs())
+ .addOutput(outputHeaderMappingFile)
+ .addOutput(outputDependencyMappingFile);
+
+ ruleContext.registerAction(builder.build(ruleContext));
+ }
+
+ private static List<? extends J2ObjcMappingFileProvider> getJ2ObjCMappings(RuleContext context) {
+ ImmutableList.Builder<J2ObjcMappingFileProvider> mappingFileProviderBuilder =
+ new ImmutableList.Builder<>();
+ addJ2ObjCMappingsForAttribute(mappingFileProviderBuilder, context, "deps");
+ addJ2ObjCMappingsForAttribute(mappingFileProviderBuilder, context, "runtime_deps");
+ addJ2ObjCMappingsForAttribute(mappingFileProviderBuilder, context, "exports");
+ return mappingFileProviderBuilder.build();
+ }
+
+ private static void addJ2ObjCMappingsForAttribute(
+ ImmutableList.Builder<J2ObjcMappingFileProvider> builder, RuleContext context,
+ String attributeName) {
+ if (context.attributes().has(attributeName, Type.LABEL_LIST)) {
+ for (TransitiveInfoCollection dependencyInfoDatum :
+ context.getPrerequisites(attributeName, Mode.TARGET)) {
+ J2ObjcMappingFileProvider provider =
+ dependencyInfoDatum.getProvider(J2ObjcMappingFileProvider.class);
+ if (provider != null) {
+ builder.add(provider);
+ }
+ }
+ }
+ }
+
+ private static Artifact j2ObjcOutputHeaderMappingFile(RuleContext ruleContext) {
+ return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".mapping.j2objc");
+ }
+
+ private static Artifact j2ObjcOutputDependencyMappingFile(RuleContext ruleContext) {
+ return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".dependency_mapping.j2objc");
+ }
+
+ private J2ObjcSource buildJ2ObjcSource(RuleContext ruleContext,
+ Iterable<Artifact> javaInputSourceFiles) {
+ PathFragment objcFileRootRelativePath = ruleContext.getUniqueDirectory("_j2objc");
+ PathFragment objcFilePath = ruleContext
+ .getConfiguration()
+ .getBinFragment()
+ .getRelative(objcFileRootRelativePath);
+ Iterable<Artifact> objcSrcs = getOutputObjcFiles(ruleContext, javaInputSourceFiles,
+ objcFileRootRelativePath, ".m");
+ Iterable<Artifact> objcHdrs = getOutputObjcFiles(ruleContext, javaInputSourceFiles,
+ objcFileRootRelativePath, ".h");
+ return new J2ObjcSource(ruleContext.getRule().getLabel(), objcSrcs, objcHdrs, objcFilePath,
+ SourceType.JAVA);
+ }
+
+ private Iterable<Artifact> getOutputObjcFiles(RuleContext ruleContext,
+ Iterable<Artifact> javaSrcs, PathFragment objcFileRootRelativePath, String suffix) {
+ ImmutableList.Builder<Artifact> objcSources = ImmutableList.builder();
+
+ for (Artifact javaSrc : javaSrcs) {
+ objcSources.add(ruleContext.getRelatedArtifact(
+ objcFileRootRelativePath.getRelative(javaSrc.getExecPath()), suffix));
+ }
+
+ return objcSources.build();
+ }
+}
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
new file mode 100644
index 0000000000..e2224a8378
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibrary.java
@@ -0,0 +1,110 @@
+// Copyright 2015 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.collect.nestedset.Order.STABLE_ORDER;
+
+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.RuleConfiguredTargetBuilder;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.packages.Type;
+import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
+import com.google.devtools.build.lib.rules.java.J2ObjcConfiguration;
+import com.google.devtools.build.lib.vfs.PathFragment;
+
+import java.util.List;
+
+/**
+ * Implementation for the "j2objc_library" rule, which exports ObjC source files translated from
+ * Java source files in java_library rules to dependent objc_binary rules for compilation and
+ * linking into the final application bundle. See {@link J2ObjcLibraryBaseRule} for details.
+ */
+public class J2ObjcLibrary implements RuleConfiguredTargetFactory {
+
+ public static final String NO_ENTRY_CLASS_ERROR_MSG =
+ "Entry classes must be specified when flag --compilationMode=opt is on in order to"
+ + " perform J2ObjC dead code stripping.";
+
+ @Override
+ public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException {
+ checkAttributes(ruleContext);
+
+ if (ruleContext.hasErrors()) {
+ return null;
+ }
+
+ J2ObjcSrcsProvider j2ObjcSrcsProvider = new J2ObjcSrcsProvider.Builder()
+ .addTransitiveFromDeps(ruleContext)
+ .addEntryClasses(ruleContext.attributes().get("entry_classes", Type.STRING_LIST))
+ .build();
+
+ ObjcProvider.Builder objcProvider = new ObjcProvider.Builder()
+ .addTransitiveAndPropagate(ruleContext.getPrerequisite(
+ "$jre_emul_lib", Mode.TARGET, ObjcProvider.class))
+ .addTransitiveAndPropagate(ruleContext.getPrerequisites(
+ "deps", Mode.TARGET, ObjcProvider.class));
+
+ if (j2ObjcSrcsProvider.hasProtos()) {
+ if (ruleContext.attributes().has("$protobuf_lib", Type.LABEL)) {
+ objcProvider.addTransitiveAndPropagate(ruleContext.getPrerequisite(
+ "$protobuf_lib", Mode.TARGET, ObjcProvider.class));
+ } 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.");
+ }
+ }
+
+ for (J2ObjcSource j2objcSource : j2ObjcSrcsProvider.getSrcs()) {
+ objcProvider.addAll(ObjcProvider.HEADER, j2objcSource.getObjcHdrs());
+ objcProvider.add(ObjcProvider.INCLUDE, j2objcSource.getObjcFilePath());
+ objcProvider.add(ObjcProvider.INCLUDE, new PathFragment(
+ j2objcSource.getObjcFilePath(),
+ ruleContext.getConfiguration().getGenfilesFragment()));
+ }
+
+ return new RuleConfiguredTargetBuilder(ruleContext)
+ .setFilesToBuild(NestedSetBuilder.<Artifact>emptySet(STABLE_ORDER))
+ .add(RunfilesProvider.class, RunfilesProvider.EMPTY)
+ .addProvider(J2ObjcSrcsProvider.class, j2ObjcSrcsProvider)
+ .addProvider(
+ J2ObjcMappingFileProvider.class, ObjcRuleClasses.j2ObjcMappingFileProvider(ruleContext))
+ .addProvider(ObjcProvider.class, objcProvider.build())
+ .build();
+ }
+
+ private static void checkAttributes(RuleContext ruleContext) {
+ checkAttributes(ruleContext, "deps");
+ checkAttributes(ruleContext, "exports");
+ }
+
+ private static void checkAttributes(RuleContext ruleContext, String attributeName) {
+ if (!ruleContext.attributes().has(attributeName, Type.LABEL_LIST)) {
+ return;
+ }
+
+ List<String> entryClasses = ruleContext.attributes().get("entry_classes", Type.STRING_LIST);
+ J2ObjcConfiguration j2objcConfiguration = ruleContext.getFragment(J2ObjcConfiguration.class);
+ if (j2objcConfiguration.removeDeadCode() && (entryClasses == null || entryClasses.isEmpty())) {
+ ruleContext.attributeError("entry_classes", NO_ENTRY_CLASS_ERROR_MSG);
+ }
+ }
+}
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
new file mode 100644
index 0000000000..5842402ad0
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibraryBaseRule.java
@@ -0,0 +1,79 @@
+// Copyright 2015 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.attr;
+import static com.google.devtools.build.lib.packages.Type.LABEL;
+import static com.google.devtools.build.lib.packages.Type.STRING_LIST;
+
+import com.google.devtools.build.lib.analysis.BaseRuleClasses;
+import com.google.devtools.build.lib.analysis.RuleDefinition;
+import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.packages.RuleClass;
+import com.google.devtools.build.lib.packages.RuleClass.Builder;
+import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
+
+/**
+ * Abstract rule definition for j2objc_library.
+ */
+public class J2ObjcLibraryBaseRule implements RuleDefinition {
+ @Override
+ public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
+ // TODO(rduan): Add support for package prefixes.
+ return builder
+ /* <!-- #BLAZE_RULE(j2objc_library).ATTRIBUTE(entry_classes) -->
+ The list of Java classes whose translated ObjC counterparts will be referenced directly
+ by user ObjC code. This attibute is required if flag <code>--j2objc_dead_code_removal
+ </code> is on. The Java classes should be specified in their canonical names as defined by
+ <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.7">the Java
+ Language Specification.</a>
+ ${SYNOPSIS}
+ When flag <code>--j2objc_dead_code_removal</code> is specified, the list of entry classes
+ will be collected transitively and used as entry points to perform dead code analysis.
+ Unused classes will then be removed from the final ObjC app bundle.
+ <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
+ .add(attr("entry_classes", STRING_LIST))
+ .add(attr("$jre_emul_jar", LABEL)
+ .value(env.getLabel("//third_party/java_src/j2objc/jre_emul:libjre_emul.jar")))
+ .add(attr("$jre_emul_lib", LABEL)
+ .value(env.getLabel("//third_party/java_src/j2objc/jre_emul:jre_emul_lib")))
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("$j2objc_library_base")
+ .type(RuleClassType.ABSTRACT)
+ .ancestors(BaseRuleClasses.BaseRule.class, ObjcRuleClasses.CoptsRule.class)
+ .build();
+ }
+}
+
+// TODO(mthvedt): Add support and examples for open-source users.
+/*<!-- #BLAZE_RULE (NAME = j2objc_library, TYPE = LIBRARY, FAMILY = Objective-C) -->
+
+${ATTRIBUTE_SIGNATURE}
+
+<p>This rule uses <a href="https://github.com/google/j2objc">J2ObjC</a>
+to translate Java source files to Objective-C, which then can be used used as dependencies of
+<code>objc_library</code> and <code>objc_binary</code> rules. More information about J2ObjC
+can be found <a href="http://j2objc.org">here</a>.
+</p>
+
+
+${ATTRIBUTE_DEFINITION}
+
+<!-- #END_BLAZE_RULE -->*/