aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib')
-rw-r--r--src/main/java/com/google/devtools/build/lib/BUILD1
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/BaseJavaCompilationHelper.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java94
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaHeaderCompileActionBuilder.java330
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchain.java28
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainData.java22
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainProvider.java114
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainRule.java7
11 files changed, 549 insertions, 70 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index 1800b43ea2..08e7789772 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -409,6 +409,7 @@ java_library(
],
deps = [
":concurrent",
+ ":preconditions",
"//src/main/protobuf:build_proto_v2",
"//third_party:guava",
"//third_party:protobuf",
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/BaseJavaCompilationHelper.java b/src/main/java/com/google/devtools/build/lib/rules/java/BaseJavaCompilationHelper.java
index c586c6a42f..109b606fea 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/BaseJavaCompilationHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/BaseJavaCompilationHelper.java
@@ -132,7 +132,7 @@ public class BaseJavaCompilationHelper {
/**
* Returns the javac bootclasspath artifacts.
*/
- protected final Iterable<Artifact> getBootClasspath() {
+ protected final ImmutableList<Artifact> getBootClasspath() {
return ruleContext.getPrerequisiteArtifacts("$javac_bootclasspath", Mode.HOST).list();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java
index 5500cd7226..63dee12638 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java
@@ -109,12 +109,7 @@ public final class JavaCompilationHelper extends BaseJavaCompilationHelper {
builder.setClasspathEntries(attributes.getCompileTimeClassPath());
builder.addResources(attributes.getResources());
builder.addClasspathResources(attributes.getClassPathResources());
- // Only add default bootclasspath entries if not explicitly set in attributes.
- if (!attributes.getBootClassPath().isEmpty()) {
- builder.setBootclasspathEntries(attributes.getBootClassPath());
- } else {
- builder.setBootclasspathEntries(getBootClasspath());
- }
+ builder.setBootclasspathEntries(getBootclasspathOrDefault());
builder.setExtdirInputs(getExtdirInputs());
builder.setLangtoolsJar(getLangtoolsJar());
builder.setJavaBuilderJar(getJavaBuilderJar());
@@ -143,6 +138,16 @@ public final class JavaCompilationHelper extends BaseJavaCompilationHelper {
getAnalysisEnvironment().registerAction(builder.build());
}
+ /** Returns the bootclasspath explicit set in attributes if present, or else the default. */
+ private ImmutableList<Artifact> getBootclasspathOrDefault() {
+ JavaTargetAttributes attributes = getAttributes();
+ if (!attributes.getBootClassPath().isEmpty()) {
+ return attributes.getBootClassPath();
+ } else {
+ return getBootClasspath();
+ }
+ }
+
/**
* Creates the Action that compiles Java source files and optionally instruments them for
* coverage.
@@ -196,6 +201,67 @@ public final class JavaCompilationHelper extends BaseJavaCompilationHelper {
getRuleContext().getLabel().toString());
}
+ private boolean shouldUseHeaderCompilation() {
+ if (!getJavaConfiguration().useHeaderCompilation()) {
+ return false;
+ }
+ if (!attributes.hasSourceFiles() && !attributes.hasSourceJars()) {
+ return false;
+ }
+ if (JavaToolchainProvider.getHeaderCompilerJar(getRuleContext()) == null) {
+ getRuleContext().ruleError(
+ "header compilation was requested but it is not support by the current Java toolchain;"
+ + " see the java_toolchain.header_compiler attribute");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Creates the Action that compiles ijars from source.
+ *
+ * @param runtimeJar the jar output of this java compilation, used to create output-relative
+ * paths for new artifacts.
+ */
+ private Artifact createHeaderCompilationAction(
+ Artifact runtimeJar, JavaCompilationArtifacts.Builder artifactBuilder) {
+
+ Artifact headerJar =
+ getAnalysisEnvironment()
+ .getDerivedArtifact(
+ FileSystemUtils.replaceExtension(runtimeJar.getRootRelativePath(), "-hjar.jar"),
+ runtimeJar.getRoot());
+ Artifact headerDeps =
+ getAnalysisEnvironment()
+ .getDerivedArtifact(
+ FileSystemUtils.replaceExtension(runtimeJar.getRootRelativePath(), "-hjar.jdeps"),
+ runtimeJar.getRoot());
+
+ JavaTargetAttributes attributes = getAttributes();
+ JavaHeaderCompileActionBuilder builder = new JavaHeaderCompileActionBuilder(getRuleContext());
+ builder.addSourceFiles(attributes.getSourceFiles());
+ builder.addSourceJars(attributes.getSourceJars());
+ builder.setClasspathEntries(attributes.getCompileTimeClassPath());
+ builder.addAllBootclasspathEntries(getBootclasspathOrDefault());
+ builder.addAllExtClasspathEntries(getExtdirInputs());
+ // TODO(cushon): restrict to only API-generating annotation processors
+ builder.addProcessorPaths(attributes.getProcessorPath());
+ builder.addProcessorNames(attributes.getProcessorNames());
+ builder.setJavacOpts(getJavacOpts());
+ builder.setTempDirectory(tempDir(headerJar));
+ builder.setOutputJar(headerJar);
+ builder.setOutputDepsProto(headerDeps);
+ builder.setStrictJavaDeps(attributes.getStrictJavaDeps());
+ builder.addCompileTimeDependencyArtifacts(attributes.getCompileTimeDependencyArtifacts());
+ builder.addDirectJars(attributes.getDirectJars());
+ builder.setRuleKind(attributes.getRuleKind());
+ builder.setTargetLabel(attributes.getTargetLabel());
+ builder.build();
+
+ artifactBuilder.setCompileTimeDependencies(headerDeps);
+ return headerJar;
+ }
+
/**
* Returns the artifact for a jar file containing class files that were generated by
* annotation processors.
@@ -228,8 +294,8 @@ public final class JavaCompilationHelper extends BaseJavaCompilationHelper {
* Returns the artifact for the manifest proto emitted from JavaBuilder. For example, for a
* class jar foo.jar, returns "foo.jar_manifest_proto".
*
- * @param outputJar The artifact for the class jar emitted form JavaBuilder
- * @return The output artifact for the manifest proto emitted from JavaBuilder
+ * @param outputJar The artifact for the class jar emitted form JavaBuilder
+ * @return The output artifact for the manifest proto emitted from JavaBuilder
*/
public Artifact createManifestProtoOutput(Artifact outputJar) {
return getRuleContext().getDerivedArtifact(
@@ -396,12 +462,18 @@ public final class JavaCompilationHelper extends BaseJavaCompilationHelper {
* Creates the actions that produce the interface jar. Adds the jar artifacts to the given
* JavaCompilationArtifacts builder.
*
- * @return The ijar (if requested), or class jar (if not)
+ * @return the header jar (if requested), or ijar (if requested), or else the class jar
*/
public Artifact createCompileTimeJarAction(
Artifact runtimeJar, JavaCompilationArtifacts.Builder builder) {
- Artifact jar =
- getJavaConfiguration().getUseIjars() ? createIjarAction(runtimeJar, false) : runtimeJar;
+ Artifact jar;
+ if (shouldUseHeaderCompilation()) {
+ jar = createHeaderCompilationAction(runtimeJar, builder);
+ } else if (getJavaConfiguration().getUseIjars()) {
+ jar = createIjarAction(runtimeJar, false);
+ } else {
+ jar = runtimeJar;
+ }
builder.addCompileTimeJar(jar);
return jar;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java
index d5f346ab15..0d5c6cd35d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java
@@ -560,7 +560,7 @@ public class JavaCompileAction extends AbstractAction {
for (Artifact extjar : extdirInputs) {
extdirs.add(extjar.getExecPath().getParentDirectory());
}
- result.add(Joiner.on(configuration.getHostPathSeparator()).join(extdirs));
+ result.add(Joiner.on(configuration.getHostPathSeparator()).join(extdirs));
}
if (!processorPath.isEmpty()) {
@@ -666,7 +666,7 @@ public class JavaCompileAction extends AbstractAction {
* Builds the list of mappings between jars on the classpath and their
* originating targets names.
*/
- private static ImmutableList<String> addJarsToTargets(
+ static ImmutableList<String> addJarsToTargets(
NestedSet<Artifact> classpath, Collection<Artifact> directJars) {
ImmutableList.Builder<String> builder = ImmutableList.builder();
for (Artifact jar : classpath) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
index 8a3c6232bc..8ba74343ef 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
@@ -130,6 +130,7 @@ public final class JavaConfiguration extends Fragment {
private final ImmutableList<String> defaultJavaBuilderJvmOpts;
private final Label javaLangtoolsJar;
private final boolean useIjars;
+ private final boolean useHeaderCompilation;
private final boolean generateJavaDeps;
private final JavaClasspathMode experimentalJavaClasspath;
private final ImmutableList<String> javaWarns;
@@ -161,6 +162,7 @@ public final class JavaConfiguration extends Fragment {
this.defaultJavaBuilderJvmOpts = defaultJavaBuilderJvmOpts;
this.javaLangtoolsJar = javaOptions.javaLangtoolsJar;
this.useIjars = javaOptions.useIjars;
+ this.useHeaderCompilation = javaOptions.headerCompilation;
this.generateJavaDeps = generateJavaDeps;
this.experimentalJavaClasspath = javaOptions.experimentalJavaClasspath;
this.javaWarns = ImmutableList.copyOf(javaOptions.javaWarns);
@@ -241,6 +243,11 @@ public final class JavaConfiguration extends Fragment {
return useIjars;
}
+ /** Returns true iff Java header compilation is enabled. */
+ public boolean useHeaderCompilation() {
+ return useHeaderCompilation;
+ }
+
/**
* Returns true iff dependency information is generated after compilation.
*/
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaHeaderCompileActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaHeaderCompileActionBuilder.java
new file mode 100644
index 0000000000..671224ae46
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaHeaderCompileActionBuilder.java
@@ -0,0 +1,330 @@
+// Copyright 2016 The Bazel Authors. 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.java;
+
+import static com.google.devtools.build.lib.util.Preconditions.checkNotNull;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType;
+import com.google.devtools.build.lib.actions.ResourceSet;
+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.CommandLine;
+import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
+import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.CustomMultiArgv;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration.StrictDepsMode;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.vfs.PathFragment;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+/**
+ * Builder for Java header compilation actions, to be used if --experimental_java_header_compilation
+ * is enabled.
+ *
+ * <p>The header compiler consumes the inputs of a java compilation, and produces an interface
+ * jar that can be used as a compile-time jar by upstream targets. The header interface jar is
+ * equivalent to the output of ijar, but unlike ijar the header compiler operates directly on
+ * Java source files instead post-processing the class outputs of the compilation. Compiling the
+ * interface jar from source moves javac off the build's critical path.
+ *
+ * <p>The implementation of the header compiler tool can be found under
+ * {@code //src/java_tools/buildjar/java/com/google/devtools/build/java/turbine}.
+ */
+public class JavaHeaderCompileActionBuilder {
+
+ static final ResourceSet RESOURCE_SET =
+ ResourceSet.createWithRamCpuIo(/*memoryMb=*/ 750.0, /*cpuUsage=*/ 0.5, /*ioUsage=*/ 0.0);
+
+ private final RuleContext ruleContext;
+
+ private Artifact outputJar;
+ @Nullable private Artifact outputDepsProto;
+ private final Collection<Artifact> sourceFiles = new ArrayList<>();
+ private final Collection<Artifact> sourceJars = new ArrayList<>();
+ private NestedSet<Artifact> classpathEntries = NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
+ private List<Artifact> bootclasspathEntries = new ArrayList<>();
+ @Nullable private String ruleKind;
+ @Nullable private Label targetLabel;
+ private PathFragment tempDirectory;
+ private BuildConfiguration.StrictDepsMode strictJavaDeps = BuildConfiguration.StrictDepsMode.OFF;
+ private List<Artifact> directJars = new ArrayList<>();
+ private List<Artifact> compileTimeDependencyArtifacts = new ArrayList<>();
+ private ImmutableList<String> javacOpts;
+ private List<Artifact> processorPath = new ArrayList<>();
+ private List<String> processorNames = new ArrayList<>();
+
+ /** Creates a builder using the configuration of the rule as the action configuration. */
+ public JavaHeaderCompileActionBuilder(RuleContext ruleContext) {
+ this.ruleContext = ruleContext;
+ }
+
+ /** Sets the output jdeps file. */
+ public JavaHeaderCompileActionBuilder setOutputDepsProto(@Nullable Artifact outputDepsProto) {
+ this.outputDepsProto = outputDepsProto;
+ return this;
+ }
+
+ /** Sets the direct dependency artifacts. */
+ public JavaHeaderCompileActionBuilder addDirectJars(Collection<Artifact> directJars) {
+ checkNotNull(directJars, "directJars must not be null");
+ this.directJars.addAll(directJars);
+ return this;
+ }
+
+ /** Sets the .jdeps artifacts for direct dependencies. */
+ public JavaHeaderCompileActionBuilder addCompileTimeDependencyArtifacts(
+ Collection<Artifact> dependencyArtifacts) {
+ checkNotNull(dependencyArtifacts, "dependencyArtifacts must not be null");
+ this.compileTimeDependencyArtifacts.addAll(dependencyArtifacts);
+ return this;
+ }
+
+ /** Sets Java compiler flags. */
+ public JavaHeaderCompileActionBuilder setJavacOpts(ImmutableList<String> javacOpts) {
+ checkNotNull(javacOpts, "javacOpts must not be null");
+ this.javacOpts = javacOpts;
+ return this;
+ }
+
+ /** Sets the output jar. */
+ public JavaHeaderCompileActionBuilder setOutputJar(Artifact outputJar) {
+ checkNotNull(outputJar, "outputJar must not be null");
+ this.outputJar = outputJar;
+ return this;
+ }
+
+ /** Adds a Java source file to compile. */
+ public JavaHeaderCompileActionBuilder addSourceFile(Artifact sourceFile) {
+ checkNotNull(sourceFile, "sourceFile must not be null");
+ sourceFiles.add(sourceFile);
+ return this;
+ }
+
+ /** Adds Java source files to compile. */
+ public JavaHeaderCompileActionBuilder addSourceFiles(Collection<Artifact> sourceFiles) {
+ checkNotNull(sourceFiles, "sourceFiles must not be null");
+ this.sourceFiles.addAll(sourceFiles);
+ return this;
+ }
+
+ /** Adds a jar archive of Java sources to compile. */
+ public JavaHeaderCompileActionBuilder addSourceJars(Collection<Artifact> sourceJars) {
+ checkNotNull(sourceJars, "sourceJars must not be null");
+ this.sourceJars.addAll(sourceJars);
+ return this;
+ }
+
+ /** Sets the compilation classpath entries. */
+ public JavaHeaderCompileActionBuilder setClasspathEntries(NestedSet<Artifact> classpathEntries) {
+ checkNotNull(classpathEntries, "classpathEntries must not be null");
+ this.classpathEntries = classpathEntries;
+ return this;
+ }
+
+ /** Sets the compilation bootclasspath entries. */
+ public JavaHeaderCompileActionBuilder addAllBootclasspathEntries(
+ Collection<Artifact> bootclasspathEntries) {
+ checkNotNull(bootclasspathEntries, "bootclasspathEntries must not be null");
+ this.bootclasspathEntries.addAll(bootclasspathEntries);
+ return this;
+ }
+
+ /** Sets the compilation extclasspath entries. */
+ public JavaHeaderCompileActionBuilder addAllExtClasspathEntries(
+ Collection<Artifact> extclasspathEntries) {
+ checkNotNull(extclasspathEntries, "extclasspathEntries must not be null");
+ // fold extclasspath entries into the bootclasspath; that's what javac ends up doing
+ this.bootclasspathEntries.addAll(extclasspathEntries);
+ return this;
+ }
+
+ /** Sets the annotation processors classpath entries. */
+ public JavaHeaderCompileActionBuilder addProcessorPaths(Collection<Artifact> processorPaths) {
+ checkNotNull(processorPaths, "processorPaths must not be null");
+ this.processorPath.addAll(processorPaths);
+ return this;
+ }
+
+ /** Sets the fully-qualified class names of annotation processors to run. */
+ public JavaHeaderCompileActionBuilder addProcessorNames(Collection<String> processorNames) {
+ checkNotNull(processorNames, "processorNames must not be null");
+ this.processorNames.addAll(processorNames);
+ return this;
+ }
+
+ /** Sets the kind of the build rule being compiled (e.g. {@code java_library}). */
+ public JavaHeaderCompileActionBuilder setRuleKind(@Nullable String ruleKind) {
+ this.ruleKind = ruleKind;
+ return this;
+ }
+
+ /** Sets the label of the target being compiled. */
+ public JavaHeaderCompileActionBuilder setTargetLabel(@Nullable Label targetLabel) {
+ this.targetLabel = targetLabel;
+ return this;
+ }
+
+ /**
+ * Sets the path to a temporary directory, e.g. for extracting sourcejar entries to before
+ * compilation.
+ */
+ public JavaHeaderCompileActionBuilder setTempDirectory(PathFragment tempDirectory) {
+ checkNotNull(tempDirectory, "tempDirectory must not be null");
+ this.tempDirectory = tempDirectory;
+ return this;
+ }
+
+ /** Sets the Strict Java Deps mode. */
+ public JavaHeaderCompileActionBuilder setStrictJavaDeps(StrictDepsMode strictJavaDeps) {
+ checkNotNull(strictJavaDeps, "strictJavaDeps must not be null");
+ this.strictJavaDeps = strictJavaDeps;
+ return this;
+ }
+
+ /** Builds and registers the {@link SpawnAction} for a header compilation. */
+ public void build() {
+ checkNotNull(outputDepsProto, "outputDepsProto must not be null");
+ checkNotNull(sourceFiles, "sourceFiles must not be null");
+ checkNotNull(sourceJars, "sourceJars must not be null");
+ checkNotNull(classpathEntries, "classpathEntries must not be null");
+ checkNotNull(bootclasspathEntries, "bootclasspathEntries must not be null");
+ checkNotNull(tempDirectory, "tempDirectory must not be null");
+ checkNotNull(strictJavaDeps, "strictJavaDeps must not be null");
+ checkNotNull(directJars, "directJars must not be null");
+ checkNotNull(compileTimeDependencyArtifacts, "compileTimeDependencyArtifacts must not be null");
+ checkNotNull(javacOpts, "javacOpts must not be null");
+ checkNotNull(processorPath, "processorPath must not be null");
+ checkNotNull(processorNames, "processorNames must not be null");
+
+ SpawnAction.Builder builder = new SpawnAction.Builder();
+
+ builder.addOutput(outputJar);
+ if (outputDepsProto != null) {
+ builder.addOutput(outputDepsProto);
+ }
+
+ builder.useParameterFile(ParameterFileType.SHELL_QUOTED);
+ builder.setCommandLine(buildCommandLine(ruleContext.getConfiguration().getHostPathSeparator()));
+
+ builder.addTransitiveInputs(JavaCompilationHelper.getHostJavabaseInputs(ruleContext));
+ builder.addInputs(classpathEntries);
+ builder.addInputs(bootclasspathEntries);
+ builder.addInputs(processorPath);
+ builder.addInputs(sourceJars);
+ builder.addInputs(sourceFiles);
+ builder.addInputs(directJars);
+ builder.addInputs(compileTimeDependencyArtifacts);
+
+ Artifact langtools = ruleContext.getPrerequisiteArtifact("$java_langtools", Mode.HOST);
+ builder.addTool(langtools);
+
+ List<String> jvmArgs =
+ ImmutableList.<String>builder()
+ .addAll(JavaToolchainProvider.getDefaultJavacJvmOptions(ruleContext))
+ .add("-Xbootclasspath/p:" + langtools.getExecPath().getPathString())
+ .build();
+ builder.setJarExecutable(
+ ruleContext.getHostConfiguration().getFragment(Jvm.class).getJavaExecutable(),
+ JavaToolchainProvider.getHeaderCompilerJar(ruleContext),
+ jvmArgs);
+
+ builder.setResources(RESOURCE_SET);
+
+ builder.setMnemonic("Turbine");
+
+ int count = sourceFiles.size() + sourceJars.size();
+ builder.setProgressMessage(
+ "Compiling Java headers " + outputJar.prettyPrint() + " (" + count + " files)");
+
+ ruleContext.registerAction(builder.build(ruleContext));
+ }
+
+ /** Builds the header compiler command line. */
+ private CommandLine buildCommandLine(String hostPathSeparator) {
+ CustomCommandLine.Builder result = CustomCommandLine.builder();
+
+ result.addExecPath("--output", outputJar);
+
+ if (outputDepsProto != null) {
+ result.addExecPath("--output_deps", outputDepsProto);
+ }
+
+ result.add("--temp_dir").addPath(tempDirectory);
+
+ result.addJoinExecPaths("--classpath", hostPathSeparator, classpathEntries);
+ result.addJoinExecPaths(
+ "--bootclasspath", hostPathSeparator, bootclasspathEntries);
+
+ if (!processorNames.isEmpty()) {
+ result.add("--processors", processorNames);
+ }
+ if (!processorPath.isEmpty()) {
+ result.addJoinExecPaths(
+ "--processorpath", hostPathSeparator, processorPath);
+ }
+
+ result.addExecPaths("--sources", sourceFiles);
+
+ if (!sourceJars.isEmpty()) {
+ result.addExecPaths("--source_jars", sourceJars);
+ }
+
+ result.add("--javacopts", javacOpts);
+
+ if (ruleKind != null) {
+ result.add("--rule_kind");
+ result.add(ruleKind);
+ }
+ if (targetLabel != null) {
+ result.add("--target_label");
+ if (targetLabel.getPackageIdentifier().getRepository().isDefault()) {
+ result.add(targetLabel.toString());
+ } else {
+ // @-prefixed strings will be assumed to be params filenames and expanded,
+ // so add an extra @ to escape it.
+ result.add("@" + targetLabel);
+ }
+ }
+
+ if (strictJavaDeps != BuildConfiguration.StrictDepsMode.OFF) {
+ result.add("--strict_java_deps");
+ result.add(strictJavaDeps.toString());
+ result.add(
+ new CustomMultiArgv() {
+ @Override
+ public Iterable<String> argv() {
+ return JavaCompileAction.addJarsToTargets(classpathEntries, directJars);
+ }
+ });
+
+ if (!compileTimeDependencyArtifacts.isEmpty()) {
+ result.addExecPaths("--deps_artifacts", compileTimeDependencyArtifacts);
+ }
+ }
+
+ return result.build();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java
index 0a5fcc0455..1785ab9e7b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java
@@ -88,7 +88,6 @@ public class JavaOptions extends FragmentOptions {
}
}
-
/** Converter for --singlejar_top. */
public static class SingleJarConverter extends DefaultLabelConverter {
public SingleJarConverter() {
@@ -234,6 +233,14 @@ public class JavaOptions extends FragmentOptions {
help = "No-op. Kept here for backwards compatibility.")
public boolean useSourceIjars;
+ @Option(
+ name = "experimental_java_header_compilation",
+ defaultValue = "false",
+ category = "undocumented",
+ help = "Experimental: compile ijars directly from source."
+ )
+ public boolean headerCompilation;
+
@Deprecated
@Option(name = "experimental_incremental_ijars",
defaultValue = "false",
@@ -413,6 +420,7 @@ public class JavaOptions extends FragmentOptions {
host.javacOpts = javacOpts;
host.javaLangtoolsJar = javaLangtoolsJar;
host.javacExtdir = javacExtdir;
+ host.headerCompilation = headerCompilation;
host.javaBuilderTop = javaBuilderTop;
host.javaToolchain = javaToolchain;
host.singleJarTop = singleJarTop;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchain.java
index 97aa87f8e0..27ef1754d7 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchain.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchain.java
@@ -13,12 +13,16 @@
// limitations under the License.
package com.google.devtools.build.lib.rules.java;
+import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.FileProvider;
+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.Runfiles;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
@@ -42,8 +46,13 @@ public final class JavaToolchain implements RuleConfiguredTargetFactory {
final JavaToolchainData toolchainData =
new JavaToolchainData(source, target, encoding, xlint, misc, jvmOpts);
final JavaConfiguration configuration = ruleContext.getFragment(JavaConfiguration.class);
- JavaToolchainProvider provider = new JavaToolchainProvider(toolchainData,
- configuration.getDefaultJavacFlags(), configuration.getDefaultJavaBuilderJvmFlags());
+ Artifact headerCompiler = getTurbine(ruleContext);
+ JavaToolchainProvider provider =
+ new JavaToolchainProvider(
+ toolchainData,
+ configuration.getDefaultJavacFlags(),
+ configuration.getDefaultJavaBuilderJvmFlags(),
+ headerCompiler);
RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext)
.add(JavaToolchainProvider.class, provider)
.setFilesToBuild(new NestedSetBuilder<Artifact>(Order.STABLE_ORDER).build())
@@ -51,4 +60,19 @@ public final class JavaToolchain implements RuleConfiguredTargetFactory {
return builder.build();
}
+
+ private Artifact getTurbine(RuleContext ruleContext) {
+ TransitiveInfoCollection prerequisite =
+ ruleContext.getPrerequisite("header_compiler", Mode.HOST);
+ if (prerequisite == null) {
+ return null;
+ }
+ Iterable<Artifact> artifacts = prerequisite.getProvider(FileProvider.class).getFilesToBuild();
+ if (Iterables.size(artifacts) != 1) {
+ ruleContext.attributeError(
+ "header_compiler", prerequisite.getLabel() + " expected a single artifact");
+ return null;
+ }
+ return Iterables.getOnlyElement(artifacts);
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainData.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainData.java
index e022538824..dca7ca15c4 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainData.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainData.java
@@ -13,6 +13,8 @@
// limitations under the License.
package com.google.devtools.build.lib.rules.java;
+import static com.google.devtools.build.lib.util.Preconditions.checkNotNull;
+
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
@@ -28,20 +30,24 @@ import java.util.List;
*/
@Immutable
public class JavaToolchainData {
-
+
private final String sourceVersion;
private final String targetVersion;
private final String encoding;
private final ImmutableList<String> options;
private final ImmutableList<String> jvmOpts;
- public JavaToolchainData(String sourceVersion, String targetVersion, String encoding,
- List<String> xlint, List<String> misc, List<String> jvmOpts) {
-
- this.sourceVersion = sourceVersion;
- this.targetVersion = targetVersion;
- this.encoding = encoding;
-
+ public JavaToolchainData(
+ String sourceVersion,
+ String targetVersion,
+ String encoding,
+ List<String> xlint,
+ List<String> misc,
+ List<String> jvmOpts) {
+ this.sourceVersion = checkNotNull(sourceVersion, "sourceVersion must not be null");
+ this.targetVersion = checkNotNull(targetVersion, "targetVersion must not be null");
+ this.encoding = checkNotNull(encoding, "encoding must not be null");
+
this.jvmOpts = ImmutableList.copyOf(jvmOpts);
Builder<String> builder = ImmutableList.<String>builder();
if (!sourceVersion.isEmpty()) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainProvider.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainProvider.java
index 6063896923..1457935c20 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainProvider.java
@@ -13,7 +13,10 @@
// limitations under the License.
package com.google.devtools.build.lib.rules.java;
+import static com.google.devtools.build.lib.util.Preconditions.checkNotNull;
+
import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
@@ -22,55 +25,16 @@ import com.google.devtools.build.lib.packages.BuildType;
import java.util.List;
+import javax.annotation.Nullable;
+
/**
* Information about the JDK used by the <code>java_*</code> rules.
*/
@Immutable
public final class JavaToolchainProvider implements TransitiveInfoProvider {
- private final String sourceVersion;
- private final String targetVersion;
- private final String encoding;
- private final ImmutableList<String> javacOptions;
- private final ImmutableList<String> javacJvmOptions;
-
- public JavaToolchainProvider(JavaToolchainData data, List<String> defaultJavacFlags,
- List<String> defaultJavacJvmOpts) {
-
- this.sourceVersion = data.getSourceVersion();
- this.targetVersion = data.getTargetVersion();
- this.encoding = data.getEncoding();
-
- // merges the defaultJavacFlags from
- // {@link JavaConfiguration} with the flags from the {@code java_toolchain} rule.
- this.javacOptions = ImmutableList.<String>builder()
- .addAll(data.getJavacOptions())
- .addAll(defaultJavacFlags)
- .build();
- // merges the defaultJavaBuilderJvmFlags from
- // {@link JavaConfiguration} with the flags from the {@code java_toolchain} rule.
- this.javacJvmOptions = ImmutableList.<String>builder()
- .addAll(data.getJavacJvmOptions())
- .addAll(defaultJavacJvmOpts)
- .build();
- }
-
/**
- * @return the list of default options for the java compiler
- */
- public ImmutableList<String> getJavacOptions() {
- return javacOptions;
- }
-
- /**
- * @return the list of default options for the JVM running the java compiler
- */
- public ImmutableList<String> getJavacJvmOptions() {
- return javacJvmOptions;
- }
-
- /**
- * An helper method to construct the list of javac options.
+ * Constructs the list of javac options.
*
* @param ruleContext The rule context of the current rule.
* @return the list of flags provided by the {@code java_toolchain} rule merged with the one
@@ -87,14 +51,14 @@ public final class JavaToolchainProvider implements TransitiveInfoProvider {
}
/**
- * An helper method to construct the list of options to pass to the JVM running the java compiler.
+ * Constructs the list of options to pass to the JVM running the java compiler.
*
* @param ruleContext The rule context of the current rule.
* @return the list of flags provided by the {@code java_toolchain} rule merged with the one
* provided by the {@link JavaConfiguration} fragment.
*/
public static List<String> getDefaultJavacJvmOptions(RuleContext ruleContext) {
- if (!ruleContext.getRule().isAttrDefined(":java_toolchain", BuildType.LABEL)) {
+ if (!ruleContext.getRule().isAttrDefined(":java_toolchain", BuildType.LABEL)) {
// As some rules might not have java_toolchain dependency (e.g., java_import), we silently
// ignore it. The rules needing it will error in #getDefaultJavacOptions(RuleContext) anyway.
return ImmutableList.of();
@@ -108,15 +72,77 @@ public final class JavaToolchainProvider implements TransitiveInfoProvider {
return javaToolchain.getJavacJvmOptions();
}
+ /** Returns the {@link Artifact} of the header compiler deploy jar. */
+ public static Artifact getHeaderCompilerJar(RuleContext ruleContext) {
+ JavaToolchainProvider javaToolchain =
+ ruleContext.getPrerequisite(":java_toolchain", Mode.TARGET, JavaToolchainProvider.class);
+ if (javaToolchain == null) {
+ ruleContext.ruleError("The --java_toolchain option does not point to a java_toolchain rule.");
+ return null;
+ }
+ return javaToolchain.getHeaderCompiler();
+ }
+
+ private final String sourceVersion;
+ private final String targetVersion;
+ private final String encoding;
+ private final ImmutableList<String> javacOptions;
+ private final ImmutableList<String> javacJvmOptions;
+ @Nullable private final Artifact headerCompiler;
+
+ public JavaToolchainProvider(
+ JavaToolchainData data,
+ List<String> defaultJavacFlags,
+ List<String> defaultJavacJvmOpts,
+ @Nullable Artifact headerCompiler) {
+ this.sourceVersion = checkNotNull(data.getSourceVersion(), "sourceVersion must not be null");
+ this.targetVersion = checkNotNull(data.getTargetVersion(), "targetVersion must not be null");
+ this.encoding = checkNotNull(data.getEncoding(), "encoding must not be null");
+ this.headerCompiler = headerCompiler;
+
+ // merges the defaultJavacFlags from
+ // {@link JavaConfiguration} with the flags from the {@code java_toolchain} rule.
+ this.javacOptions =
+ ImmutableList.<String>builder()
+ .addAll(data.getJavacOptions())
+ .addAll(defaultJavacFlags)
+ .build();
+ // merges the defaultJavaBuilderJvmFlags from
+ // {@link JavaConfiguration} with the flags from the {@code java_toolchain} rule.
+ this.javacJvmOptions =
+ ImmutableList.<String>builder()
+ .addAll(data.getJavacJvmOptions())
+ .addAll(defaultJavacJvmOpts)
+ .build();
+ }
+
+ /** @return the list of default options for the java compiler */
+ public ImmutableList<String> getJavacOptions() {
+ return javacOptions;
+ }
+
+ /** @return the list of default options for the JVM running the java compiler */
+ public ImmutableList<String> getJavacJvmOptions() {
+ return javacJvmOptions;
+ }
+
+ /** @return the input Java language level */
public String getSourceVersion() {
return sourceVersion;
}
+ /** @return the target Java language level */
public String getTargetVersion() {
return targetVersion;
}
+ /** @return the encoding for Java source files */
public String getEncoding() {
return encoding;
}
+
+ /** @return the {@link Artifact} of the Header Compiler deploy jar */
+ public Artifact getHeaderCompiler() {
+ return headerCompiler;
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainRule.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainRule.java
index b79cfab469..d1c982c2fe 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainRule.java
@@ -13,7 +13,9 @@
// limitations under the License.
package com.google.devtools.build.lib.rules.java;
+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 static com.google.devtools.build.lib.syntax.Type.STRING;
import static com.google.devtools.build.lib.syntax.Type.STRING_LIST;
@@ -23,6 +25,7 @@ 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.util.FileTypeSet;
/**
* Rule definition for {@code java_toolchain}
@@ -30,7 +33,8 @@ import com.google.devtools.build.lib.packages.RuleClass.Builder;
public final class JavaToolchainRule implements RuleDefinition {
@Override
public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
- return builder.requiresConfigurationFragments(JavaConfiguration.class)
+ return builder
+ .requiresConfigurationFragments(JavaConfiguration.class)
/* <!-- #BLAZE_RULE(java_toolchain).ATTRIBUTE(source_version) -->
The Java source version (e.g., '6' or '7'). It specifies which set of code structures
are allowed in the Java source code.
@@ -60,6 +64,7 @@ public final class JavaToolchainRule implements RuleDefinition {
virtual machine documentation for the extensive list of possible flags for this option.
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(attr("jvm_opts", STRING_LIST).value(ImmutableList.<String>of("-client")))
+ .add(attr("header_compiler", LABEL).cfg(HOST).allowedFileTypes(FileTypeSet.ANY_FILE).exec())
.build();
}