diff options
author | Alex Humesky <ahumesky@google.com> | 2015-07-08 18:18:33 +0000 |
---|---|---|
committer | Han-Wen Nienhuys <hanwen@google.com> | 2015-07-10 17:15:23 +0000 |
commit | d3f7eda5548fae0d9c022d9e1a0761b8e8ba22a6 (patch) | |
tree | 8cbca5cb9298446be3ac2c539526b7714a647790 | |
parent | 525019b7bd8810ef8401ecb80247fa4226eba8c2 (diff) |
Adds gen jar and manifest proto outputs.
Adds a jar output to Java and Android rules which contains the class files for source files generated from Java annotation processors. For a java_binary foo, the jar will be foo-gen.jar, and for a java_library foo the jar will be libfoo-gen.jar, and similarly for Android. Also adds a binary serialized proto manifest file output to Java and Android rules which describes the contents of the output class jar of those rules, which is used to create the -gen.jar. See src/main/protobuf/java_compilation.proto.
--
MOS_MIGRATED_REVID=97793715
29 files changed, 577 insertions, 75 deletions
diff --git a/compile.sh b/compile.sh index 30b97d0fac..581136d57d 100755 --- a/compile.sh +++ b/compile.sh @@ -106,6 +106,8 @@ if [ $DO_TOOLS_COMPILATION ]; then tools/jdk/SingleJar_deploy.jar bazel_bootstrap //src/java_tools/buildjar:JavaBuilder_deploy.jar \ tools/jdk/JavaBuilder_deploy.jar + bazel_bootstrap //src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass:GenClass_deploy.jar \ + tools/jdk/GenClass_deploy.jar if [[ $PLATFORM == "darwin" ]]; then bazel_bootstrap //src/tools/xcode-common/java/com/google/devtools/build/xcode/actoolzip:actoolzip_deploy.jar \ tools/objc/precomp_actoolzip_deploy.jar diff --git a/scripts/bootstrap/bootstrap.sh b/scripts/bootstrap/bootstrap.sh index bd5721c49c..3c0f7ff222 100755 --- a/scripts/bootstrap/bootstrap.sh +++ b/scripts/bootstrap/bootstrap.sh @@ -32,6 +32,7 @@ fi : ${JAVA_VERSION:="1.8"} : ${BAZEL_ARGS="--singlejar_top=//src/java_tools/singlejar:bootstrap_deploy.jar \ --javabuilder_top=//src/java_tools/buildjar:bootstrap_deploy.jar \ + --genclass_top=//src/java_tools/buildjar:bootstrap_genclass_deploy.jar \ --ijar_top=//third_party/ijar"} function bazel_bootstrap() { diff --git a/scripts/get_all_bazel_paths.sh b/scripts/get_all_bazel_paths.sh index c945ea0a08..b64ff407e2 100755 --- a/scripts/get_all_bazel_paths.sh +++ b/scripts/get_all_bazel_paths.sh @@ -25,8 +25,12 @@ function query() { } # Compile bazel -([ -f "output/bazel" ] && [ -f "tools/jdk/JavaBuilder_deploy.jar" ] && [ -f "tools/jdk/ijar" ] \ - && [ -f "tools/jdk/SingleJar_deploy.jar" ] && [ -e "tools/jdk/jdk" ]) || ./compile.sh >&2 || exit $? +([ -f "output/bazel" ] \ + && [ -f "tools/jdk/JavaBuilder_deploy.jar" ] \ + && [ -f "tools/jdk/ijar" ] \ + && [ -f "tools/jdk/SingleJar_deploy.jar" ] \ + && [ -f "tools/jdk/GenClass_deploy.jar" ] \ + && [ -e "tools/jdk/jdk" ]) || ./compile.sh >&2 || exit $? # Build almost everything. # //third_party/ijar/test/... is disabled due to #273. diff --git a/scripts/setup-eclipse.sh b/scripts/setup-eclipse.sh index 2dd01050c1..5bac977d26 100755 --- a/scripts/setup-eclipse.sh +++ b/scripts/setup-eclipse.sh @@ -30,9 +30,12 @@ EXTRA_JARS="bazel-bazel/external/local-jdk/lib/tools.jar" cd $(dirname $(dirname "$0")) # Compile bazel -([ -f "output/bazel" ] && [ -f "tools/jdk/JavaBuilder_deploy.jar" ] \ - && [ -f "tools/jdk/ijar" ] && [ -f "tools/jdk/SingleJar_deploy.jar" ] \ - && [ -e "tools/jdk/jdk" ]) || ./compile.sh >&2 || exit $? +([ -f "output/bazel" ] \ + && [ -f "tools/jdk/JavaBuilder_deploy.jar" ] \ + && [ -f "tools/jdk/ijar" ] \ + && [ -f "tools/jdk/SingleJar_deploy.jar" ] \ + && [ -f "tools/jdk/GenClass_deploy.jar" ] \ + && [ -e "tools/jdk/jdk" ]) || ./compile.sh >&2 || exit $? # Make the script use actual bazel function bazel() { @@ -105,6 +105,7 @@ filegroup( name = "tools", srcs = [ "//src/java_tools/buildjar:JavaBuilder_deploy.jar", + "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass:GenClass_deploy.jar", "//src/java_tools/singlejar:SingleJar_deploy.jar", "//third_party/ijar", ], diff --git a/src/java_tools/buildjar/BUILD b/src/java_tools/buildjar/BUILD index 28773711e8..a9f6276cf0 100644 --- a/src/java_tools/buildjar/BUILD +++ b/src/java_tools/buildjar/BUILD @@ -151,6 +151,21 @@ java_library( deps = [":BazelJavaCompiler"], ) +# JarHelper library for GenClass so it can create the gen jar. +java_library( + name = "jarhelper", + srcs = [ + "java/com/google/devtools/build/buildjar/JarCreator.java", + "java/com/google/devtools/build/buildjar/JarHelper.java", + ], + visibility = [ + "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass:__pkg__", + ], + deps = [ + "//third_party:guava", + ], +) + # For the -Xbootclasspath option of the java_test of buildjar genrule( name = "langtools-test", @@ -206,3 +221,11 @@ bootstrap_java_binary( visibility = ["//visibility:public"], deps = [":skylark-deps"], ) + +bootstrap_java_binary( + name = "bootstrap_genclass", + srcs = glob(["java/com/google/devtools/build/buildjar/genclass/*.java"]), + main_class = "com.google.devtools.build.buildjar.genclass.GenClass", + visibility = ["//visibility:public"], + deps = [":skylark-deps"], +) diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/BUILD b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/BUILD new file mode 100644 index 0000000000..c5e0e4b1fa --- /dev/null +++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/BUILD @@ -0,0 +1,16 @@ +java_binary( + name = "GenClass", + main_class = "com.google.devtools.build.buildjar.genclass.GenClass", + visibility = ["//visibility:public"], + runtime_deps = [":genclass_lib"], +) + +java_library( + name = "genclass_lib", + srcs = glob(["*.java"]), + deps = [ + "//src/java_tools/buildjar:jarhelper", + "//src/main/protobuf:proto_java_compilation", + "//third_party:guava", + ], +) diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/GenClass.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/GenClass.java new file mode 100644 index 0000000000..7ae607ae2b --- /dev/null +++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/GenClass.java @@ -0,0 +1,121 @@ +// 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.buildjar.genclass; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableSet; +import com.google.devtools.build.buildjar.JarCreator; +import com.google.devtools.build.buildjar.proto.JavaCompilation.CompilationUnit; +import com.google.devtools.build.buildjar.proto.JavaCompilation.Manifest; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +/** + * GenClass post-processes the output of a Java compilation, and produces + * a jar containing only the class files for sources that were generated + * by annotation processors. + */ +public class GenClass { + + public static void main(String[] args) throws IOException { + GenClassOptions options = GenClassOptionsParser.parse(Arrays.asList(args)); + Manifest manifest = readManifest(options.manifest()); + extractGeneratedClasses(options.classJar(), manifest, options.tempDir()); + writeOutputJar(options); + } + + /** + * Reads the compilation manifest. + */ + private static Manifest readManifest(Path path) throws IOException { + Manifest manifest; + try (InputStream inputStream = Files.newInputStream(path)) { + manifest = Manifest.parseFrom(inputStream); + } + return manifest; + } + + /** + * For each top-level class in the compilation, determine the path prefix + * of classes corresponding to that compilation unit. + * + * <p>Prefixes are used to correctly handle inner classes, e.g. the top-level + * class "c.g.Foo" may correspond to "c/g/Foo.class" and also + * "c/g/Foo$Inner.class" or "c/g/Foo$0.class". + */ + @VisibleForTesting + static ImmutableSet<String> getGeneratedPrefixes(Manifest manifest) { + ImmutableSet.Builder<String> prefixes = ImmutableSet.builder(); + for (CompilationUnit unit : manifest.getCompilationUnitList()) { + if (!unit.getGeneratedByAnnotationProcessor()) { + continue; + } + String pkg; + if (unit.hasPkg()) { + pkg = unit.getPkg().replace('.', '/') + "/"; + } else { + pkg = ""; + } + for (String toplevel : unit.getTopLevelList()) { + prefixes.add(pkg + toplevel); + } + } + return prefixes.build(); + } + + /** + * Unzip all the class files that correspond to annotation processor- + * generated sources into the temporary directory. + */ + private static void extractGeneratedClasses(Path classJar, Manifest manifest, Path tempDir) + throws IOException { + ImmutableSet<String> generatedPrefixes = getGeneratedPrefixes(manifest); + try (JarFile jar = new JarFile(classJar.toFile())) { + Enumeration<JarEntry> entries = jar.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + String name = entry.getName(); + if (!name.endsWith(".class")) { + continue; + } + String prefix = name.substring(0, name.length() - ".class".length()); + int idx = prefix.indexOf('$'); + if (idx > 0) { + prefix = prefix.substring(0, idx); + } + if (generatedPrefixes.contains(prefix)) { + Files.createDirectories(tempDir.resolve(name).getParent()); + Files.copy(jar.getInputStream(entry), tempDir.resolve(name)); + } + } + } + } + + /** Writes the generated class files to the output jar. */ + private static void writeOutputJar(GenClassOptions options) throws IOException { + JarCreator output = new JarCreator(options.outputJar().toString()); + output.setCompression(true); + output.setNormalize(true); + output.addDirectory(options.tempDir().toString()); + output.execute(); + } +} diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/GenClassOptions.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/GenClassOptions.java new file mode 100644 index 0000000000..58b6544aec --- /dev/null +++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/GenClassOptions.java @@ -0,0 +1,90 @@ +// 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.buildjar.genclass; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.nio.file.Path; + +/** The options for a {@GenClass} action. */ +public final class GenClassOptions { + + /** A builder for {@link GenClassOptions}. */ + public static final class Builder { + private Path manifest; + private Path classJar; + private Path outputJar; + private Path tempDir; + + public Builder() {} + + public void setManifest(Path manifest) { + this.manifest = manifest; + } + + public void setClassJar(Path classJar) { + this.classJar = classJar; + } + + public void setOutputJar(Path outputJar) { + this.outputJar = outputJar; + } + + public void setTempDir(Path tempDir) { + this.tempDir = tempDir; + } + + GenClassOptions build() { + return new GenClassOptions(manifest, classJar, outputJar, tempDir); + } + } + + private final Path manifest; + private final Path classJar; + private final Path outputJar; + private final Path tempDir; + + private GenClassOptions(Path manifest, Path classJar, Path outputJar, Path tempDir) { + this.manifest = checkNotNull(manifest); + this.classJar = checkNotNull(classJar); + this.outputJar = checkNotNull(outputJar); + this.tempDir = checkNotNull(tempDir); + } + + /** The path to the compilation manifest proto. */ + public Path manifest() { + return manifest; + } + + /** The path to the compilation's class jar. */ + public Path classJar() { + return classJar; + } + + /** The path to write the output to. */ + public Path outputJar() { + return outputJar; + } + + /** The path to the temp directory. */ + public Path tempDir() { + return tempDir; + } + + /** Returns a builder for {@link GenClassOptions}. */ + public static Builder builder() { + return new Builder(); + } +} diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/GenClassOptionsParser.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/GenClassOptionsParser.java new file mode 100644 index 0000000000..80fb6ed5c5 --- /dev/null +++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/GenClassOptionsParser.java @@ -0,0 +1,56 @@ +// 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.buildjar.genclass; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Iterator; + +/** A command line parser for {@link GenClassOptions}. */ +public class GenClassOptionsParser { + public static GenClassOptions parse(Iterable<String> args) { + Iterator<String> it = args.iterator(); + GenClassOptions.Builder builder = GenClassOptions.builder(); + + while (it.hasNext()) { + String arg = it.next(); + switch (arg) { + case "--manifest_proto": + builder.setManifest(readPath(it)); + break; + case "--class_jar": + builder.setClassJar(readPath(it)); + break; + case "--output_jar": + builder.setOutputJar(readPath(it)); + break; + case "--temp_dir": + builder.setTempDir(readPath(it)); + break; + default: + throw new IllegalArgumentException( + String.format("Unexpected argument: '%s' in %s", arg, args)); + } + } + return builder.build(); + } + + private static Path readPath(Iterator<String> it) { + if (!it.hasNext()) { + throw new IllegalArgumentException(String.format("Expected more arguments")); + } + return Paths.get(it.next()); + } +} 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 00fe3c9f32..8a88e0d8b7 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 @@ -51,11 +51,18 @@ public class BazelJavaRuleClasses { PackageNameConstraint.ANY_SEGMENT, "java", "javatests"); public static final ImplicitOutputsFunction JAVA_BINARY_IMPLICIT_OUTPUTS = - fromFunctions(JavaSemantics.JAVA_BINARY_CLASS_JAR, JavaSemantics.JAVA_BINARY_SOURCE_JAR, - JavaSemantics.JAVA_BINARY_DEPLOY_JAR, JavaSemantics.JAVA_BINARY_DEPLOY_SOURCE_JAR); + fromFunctions( + JavaSemantics.JAVA_BINARY_CLASS_JAR, + JavaSemantics.JAVA_BINARY_GEN_JAR, + JavaSemantics.JAVA_BINARY_SOURCE_JAR, + JavaSemantics.JAVA_BINARY_DEPLOY_JAR, + JavaSemantics.JAVA_BINARY_DEPLOY_SOURCE_JAR); static final ImplicitOutputsFunction JAVA_LIBRARY_IMPLICIT_OUTPUTS = - fromFunctions(JavaSemantics.JAVA_LIBRARY_CLASS_JAR, JavaSemantics.JAVA_LIBRARY_SOURCE_JAR); + fromFunctions( + JavaSemantics.JAVA_LIBRARY_CLASS_JAR, + JavaSemantics.JAVA_LIBRARY_GEN_JAR, + JavaSemantics.JAVA_LIBRARY_SOURCE_JAR); /** * Common attributes for rules that depend on ijar. @@ -99,6 +106,8 @@ public class BazelJavaRuleClasses { .value(env.getLabel(JavaSemantics.JAVABUILDER_LABEL))) .add(attr("$singlejar", LABEL).cfg(HOST) .value(env.getLabel(JavaSemantics.SINGLEJAR_LABEL))) + .add(attr("$genclass", LABEL).cfg(HOST) + .value(env.getLabel(JavaSemantics.GENCLASS_LABEL))) .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java index 11aefb8d13..4ca8ca2ab7 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java @@ -239,6 +239,7 @@ public class BazelJavaSemantics implements JavaSemantics { List<String> jvmFlags, Artifact classJar, Artifact srcJar, + Artifact genJar, Artifact gensrcJar, ImmutableMap<Artifact, Artifact> compilationToRuntimeJarMap, JavaCompilationHelper helper, diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java index c856d52f23..e617bca52d 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java @@ -248,8 +248,13 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { } JavaTargetAttributes resourceClasses = androidCommon.init( - javaSemantics, androidSemantics, resourceApk, AndroidIdlProvider.EMPTY, - ruleContext.getConfiguration().isCodeCoverageEnabled(), true); + javaSemantics, + androidSemantics, + resourceApk, + AndroidIdlProvider.EMPTY, + ruleContext.getConfiguration().isCodeCoverageEnabled(), + true /* collectJavaCompilationArgs */, + AndroidRuleClasses.ANDROID_BINARY_GEN_JAR); if (resourceClasses == null) { return null; } diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java index a0321a0dc2..8af0c76269 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java @@ -40,6 +40,7 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration.StrictDe 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.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; import com.google.devtools.build.lib.packages.Type; import com.google.devtools.build.lib.rules.android.AndroidResourcesProvider.ResourceContainer; import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.MultidexMode; @@ -243,8 +244,12 @@ public class AndroidCommon { Artifact outputDepsProto = javacHelper.createOutputDepsProtoArtifact(binaryResourcesJar, javaArtifactsBuilder); - javacHelper.createCompileActionWithInstrumentation(binaryResourcesJar, null /* gensrcJar */, - outputDepsProto, javaArtifactsBuilder); + javacHelper.createCompileActionWithInstrumentation( + binaryResourcesJar, + null /* manifestProtoOutput */, + null /* gensrcJar */, + outputDepsProto, + javaArtifactsBuilder); } private void createJarJarActions( @@ -308,7 +313,8 @@ public class AndroidCommon { public JavaTargetAttributes init( JavaSemantics javaSemantics, AndroidSemantics androidSemantics, ResourceApk resourceApk, AndroidIdlProvider transitiveIdlImportData, - boolean addCoverageSupport, boolean collectJavaCompilationArgs) { + boolean addCoverageSupport, boolean collectJavaCompilationArgs, + SafeImplicitOutputsFunction genClassJarImplicitOutput) { ImmutableList<Artifact> extraSources = resourceApk.isLegacy() || resourceApk.getResourceJavaSrcJar() == null ? ImmutableList.<Artifact>of() @@ -337,7 +343,8 @@ public class AndroidCommon { } initJava( - helper, artifactsBuilder, collectJavaCompilationArgs, resourceApk.getResourceJavaSrcJar()); + helper, artifactsBuilder, collectJavaCompilationArgs, resourceApk.getResourceJavaSrcJar(), + genClassJarImplicitOutput); return helper.getAttributes(); } @@ -420,7 +427,8 @@ public class AndroidCommon { JavaCompilationHelper helper, JavaCompilationArtifacts.Builder javaArtifactsBuilder, boolean collectJavaCompilationArgs, - @Nullable Artifact additionalSourceJar) { + @Nullable Artifact additionalSourceJar, + SafeImplicitOutputsFunction genClassJarImplicitOutput) { NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.<Artifact>stableOrder(); if (additionalSourceJar != null) { filesBuilder.add(additionalSourceJar); @@ -453,9 +461,14 @@ public class AndroidCommon { filesBuilder.add(classJar); - // The gensrcJar is only created if the target uses annotation processing. Otherwise, + // The gensrc jar is created only if the target uses annotation processing. Otherwise, // it is null, and the source jar action will not depend on the compile action. gensrcJar = helper.createGensrcJar(classJar); + Artifact manifestProtoOutput = helper.createManifestProtoOutput(classJar); + + // AndroidBinary will pass its -gen.jar output, and AndroidLibrary will pass its own. + Artifact genClassJar = ruleContext.getImplicitOutputArtifact(genClassJarImplicitOutput); + helper.createGenJarAction(classJar, manifestProtoOutput, genClassJar); srcJar = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_LIBRARY_SOURCE_JAR); helper.createSourceJarAction(srcJar, gensrcJar); @@ -465,8 +478,8 @@ public class AndroidCommon { if (outputDepsProto != null) { compileTimeDependenciesBuilder.add(outputDepsProto); } - helper.createCompileActionWithInstrumentation(classJar, gensrcJar, outputDepsProto, - javaArtifactsBuilder); + helper.createCompileActionWithInstrumentation(classJar, manifestProtoOutput, gensrcJar, + outputDepsProto, javaArtifactsBuilder); compileTimeDependencyArtifacts = compileTimeDependenciesBuilder.build(); filesToBuild = filesBuilder.build(); diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java index 338282bc4e..fa40809201 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java @@ -37,6 +37,7 @@ import com.google.devtools.build.lib.rules.java.JavaCommon; import com.google.devtools.build.lib.rules.java.JavaNeverlinkInfoProvider; import com.google.devtools.build.lib.rules.java.JavaSemantics; import com.google.devtools.build.lib.rules.java.JavaSourceJarsProvider; +import com.google.devtools.build.lib.rules.java.JavaTargetAttributes; import com.google.devtools.build.lib.rules.java.JavaUtil; import com.google.devtools.build.lib.vfs.PathFragment; @@ -94,8 +95,15 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory { false, null /* proguardCfgOut */); - if (androidCommon.init(javaSemantics, androidSemantics, - resourceApk, transitiveIdlImportData, false, true) == null) { + JavaTargetAttributes javaTargetAttributes = androidCommon.init( + javaSemantics, + androidSemantics, + resourceApk, + transitiveIdlImportData, + false /* addCoverageSupport */, + true /* collectJavaCompilationArgs */, + AndroidRuleClasses.ANDROID_LIBRARY_GEN_JAR); + if (javaTargetAttributes == null) { return null; } @@ -144,8 +152,16 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory { JavaCommon javaCommon = new JavaCommon(ruleContext, javaSemantics); AndroidCommon androidCommon = new AndroidCommon(ruleContext, javaCommon); ResourceApk resourceApk = ResourceApk.fromTransitiveResources(transitiveResources); - if (androidCommon.init(javaSemantics, androidSemantics, - resourceApk, transitiveIdlImportData, false, true) == null) { + + JavaTargetAttributes javaTargetAttributes = androidCommon.init( + javaSemantics, + androidSemantics, + resourceApk, + transitiveIdlImportData, + false /* addCoverageSupport */, + true /* collectJavaCompilationArgs */, + AndroidRuleClasses.ANDROID_LIBRARY_GEN_JAR); + if (javaTargetAttributes == null) { return null; } diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java index d14b307fed..fe2a2f9c46 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java @@ -65,6 +65,8 @@ public final class AndroidRuleClasses { JavaSemantics.JAVA_LIBRARY_SOURCE_JAR; public static final SafeImplicitOutputsFunction ANDROID_LIBRARY_CLASS_JAR = JavaSemantics.JAVA_LIBRARY_CLASS_JAR; + public static final SafeImplicitOutputsFunction ANDROID_LIBRARY_GEN_JAR = + JavaSemantics.JAVA_LIBRARY_GEN_JAR; public static final SafeImplicitOutputsFunction ANDROID_LIBRARY_JACK_FILE = fromTemplates("lib%{name}.jack"); public static final SafeImplicitOutputsFunction ANDROID_LIBRARY_AAR = @@ -83,6 +85,8 @@ public final class AndroidRuleClasses { fromTemplates("%{name}_unsigned.apk"); public static final SafeImplicitOutputsFunction ANDROID_BINARY_SIGNED_APK = fromTemplates("%{name}_signed.apk"); + public static final SafeImplicitOutputsFunction ANDROID_BINARY_GEN_JAR = + JavaSemantics.JAVA_BINARY_GEN_JAR; public static final SafeImplicitOutputsFunction ANDROID_BINARY_DEPLOY_JAR = fromTemplates("%{name}_deploy.jar"); public static final SafeImplicitOutputsFunction ANDROID_BINARY_PROGUARD_JAR = @@ -211,10 +215,11 @@ public final class AndroidRuleClasses { @Override public Iterable<String> getImplicitOutputs(AttributeMap rule) { boolean mapping = rule.get("proguard_generate_mapping", Type.BOOLEAN); - List<SafeImplicitOutputsFunction> functions = Lists.newArrayListWithCapacity(6); + List<SafeImplicitOutputsFunction> functions = Lists.newArrayList(); functions.add(AndroidRuleClasses.ANDROID_BINARY_APK); functions.add(AndroidRuleClasses.ANDROID_BINARY_UNSIGNED_APK); functions.add(AndroidRuleClasses.ANDROID_BINARY_DEPLOY_JAR); + functions.add(AndroidRuleClasses.ANDROID_BINARY_GEN_JAR); // The below is a hack to support configurable attributes (proguard_specs seems like // too valuable an attribute to make nonconfigurable, and we don't currently @@ -251,23 +256,25 @@ public final class AndroidRuleClasses { new ImplicitOutputsFunction() { @Override public Iterable<String> getImplicitOutputs(AttributeMap attributes) { + + ImmutableList.Builder<SafeImplicitOutputsFunction> implicitOutputs = + ImmutableList.builder(); + + implicitOutputs.add( + AndroidRuleClasses.ANDROID_LIBRARY_CLASS_JAR, + AndroidRuleClasses.ANDROID_LIBRARY_GEN_JAR, + AndroidRuleClasses.ANDROID_LIBRARY_SOURCE_JAR, + AndroidRuleClasses.ANDROID_LIBRARY_JACK_FILE, + AndroidRuleClasses.ANDROID_LIBRARY_AAR); + if (LocalResourceContainer.definesAndroidResources(attributes)) { - return fromFunctions( - AndroidRuleClasses.ANDROID_JAVA_SOURCE_JAR, - AndroidRuleClasses.ANDROID_RESOURCES_APK, - AndroidRuleClasses.ANDROID_LIBRARY_CLASS_JAR, - AndroidRuleClasses.ANDROID_LIBRARY_JACK_FILE, - AndroidRuleClasses.ANDROID_LIBRARY_SOURCE_JAR, - AndroidRuleClasses.ANDROID_LIBRARY_AAR, - AndroidRuleClasses.ANDROID_R_TXT) - .getImplicitOutputs(attributes); + implicitOutputs.add( + AndroidRuleClasses.ANDROID_JAVA_SOURCE_JAR, + AndroidRuleClasses.ANDROID_RESOURCES_APK, + AndroidRuleClasses.ANDROID_R_TXT); } - return fromFunctions( - AndroidRuleClasses.ANDROID_LIBRARY_CLASS_JAR, - AndroidRuleClasses.ANDROID_LIBRARY_JACK_FILE, - AndroidRuleClasses.ANDROID_LIBRARY_SOURCE_JAR, - AndroidRuleClasses.ANDROID_LIBRARY_AAR) - .getImplicitOutputs(attributes); + + return fromFunctions(implicitOutputs.build()).getImplicitOutputs(attributes); } }; diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java index 2a6b77f5ec..763bcf6acc 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java @@ -149,13 +149,18 @@ public class JavaBinary implements RuleConfiguredTargetFactory { common.setJavaCompilationArtifacts(javaArtifactsBuilder.build()); - // The gensrcJar is only created if the target uses annotation processing. Otherwise, + // The gensrc jar is created only if the target uses annotation processing. Otherwise, // it is null, and the source jar action will not depend on the compile action. Artifact gensrcJar = helper.createGensrcJar(classJar); + Artifact manifestProtoOutput = helper.createManifestProtoOutput(classJar); - helper.createCompileAction(classJar, gensrcJar, outputDepsProto, instrumentationMetadata); + helper.createCompileAction( + classJar, manifestProtoOutput, gensrcJar, outputDepsProto, instrumentationMetadata); helper.createSourceJarAction(srcJar, gensrcJar); + Artifact genClassJar = ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_GEN_JAR); + helper.createGenJarAction(classJar, manifestProtoOutput, genClassJar); + common.setClassPathFragment(new ClasspathConfiguredFragment( common.getJavaCompilationArtifacts(), attributes, false)); @@ -187,7 +192,7 @@ public class JavaBinary implements RuleConfiguredTargetFactory { RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext); - semantics.addProviders(ruleContext, common, jvmFlags, classJar, srcJar, gensrcJar, + semantics.addProviders(ruleContext, common, jvmFlags, classJar, srcJar, genClassJar, gensrcJar, ImmutableMap.<Artifact, Artifact>of(), helper, filesBuilder, builder); NestedSet<Artifact> filesToBuild = filesBuilder.build(); 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 1cfecc6ed4..b570c46e27 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 @@ -21,9 +21,13 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType; import com.google.devtools.build.lib.analysis.AnalysisUtils; +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.analysis.config.BuildConfiguration.StrictDepsMode; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; @@ -44,6 +48,12 @@ import javax.annotation.Nullable; * Also supports the creation of resource and source only Jars. */ public class JavaCompilationHelper extends BaseJavaCompilationHelper { + + /** + * Maximum memory to use for GenClass for generating the gen jar. + */ + private static final String GENCLASS_MAX_MEMORY = "-Xmx64m"; + private Artifact outputDepsProtoArtifact; private JavaTargetAttributes.Builder attributes; private JavaTargetAttributes builtAttributes; @@ -79,14 +89,20 @@ public class JavaCompilationHelper extends BaseJavaCompilationHelper { * Creates the Action that compiles Java source files. * * @param outputJar the class jar Artifact to create with the Action + * @param manifestProtoOutput the output artifact for the manifest proto emitted from JavaBuilder * @param gensrcOutputJar the generated sources jar Artifact to create with the Action * (null if no sources will be generated). * @param outputDepsProto the compiler-generated jdeps file to create with the Action * (null if not requested) * @param outputMetadata metadata file (null if no instrumentation is needed). */ - public void createCompileAction(Artifact outputJar, @Nullable Artifact gensrcOutputJar, - @Nullable Artifact outputDepsProto, @Nullable Artifact outputMetadata) { + public void createCompileAction( + Artifact outputJar, + Artifact manifestProtoOutput, + @Nullable Artifact gensrcOutputJar, + @Nullable Artifact outputDepsProto, + @Nullable Artifact outputMetadata) { + JavaTargetAttributes attributes = getAttributes(); JavaCompileAction.Builder builder = createJavaCompileActionBuilder(semantics); builder.setClasspathEntries(attributes.getCompileTimeClassPath()); @@ -103,6 +119,7 @@ public class JavaCompilationHelper extends BaseJavaCompilationHelper { builder.setJavaBuilderJar(getJavaBuilderJar()); builder.addTranslations(getTranslations()); builder.setOutputJar(outputJar); + builder.setManifestProtoOutput(manifestProtoOutput); builder.setGensrcOutputJar(gensrcOutputJar); builder.setOutputDepsProto(outputDepsProto); builder.setMetadata(outputMetadata); @@ -130,13 +147,22 @@ public class JavaCompilationHelper extends BaseJavaCompilationHelper { * coverage. * * @param outputJar the class jar Artifact to create with the Action + * @param manifestProtoOutput the output artifact for the manifest proto emitted from JavaBuilder * @param gensrcJar the generated sources jar Artifact to create with the Action * @param outputDepsProto the compiler-generated jdeps file to create with the Action * @param javaArtifactsBuilder the build to store the instrumentation metadata in */ - public void createCompileActionWithInstrumentation(Artifact outputJar, Artifact gensrcJar, - Artifact outputDepsProto, JavaCompilationArtifacts.Builder javaArtifactsBuilder) { - createCompileAction(outputJar, gensrcJar, outputDepsProto, + public void createCompileActionWithInstrumentation( + Artifact outputJar, + Artifact manifestProtoOutput, + @Nullable Artifact gensrcJar, + @Nullable Artifact outputDepsProto, + JavaCompilationArtifacts.Builder javaArtifactsBuilder) { + createCompileAction( + outputJar, + manifestProtoOutput, + gensrcJar, + outputDepsProto, createInstrumentationMetadata(outputJar, javaArtifactsBuilder)); } @@ -170,16 +196,17 @@ public class JavaCompilationHelper extends BaseJavaCompilationHelper { } /** - * Returns the artifact for a jar file containing source files that were generated by an - * annotation processor or null if no annotation processors are used. + * Returns the artifact for a jar file containing source files that were generated by + * annotation processors or null if no annotation processors are used. */ public Artifact createGensrcJar(@Nullable Artifact outputJar) { - if (!usesAnnotationProcessing()) { + if (usesAnnotationProcessing()) { + return getAnalysisEnvironment().getDerivedArtifact( + FileSystemUtils.appendWithoutExtension(outputJar.getRootRelativePath(), "-gensrc"), + outputJar.getRoot()); + } else { return null; } - return getAnalysisEnvironment().getDerivedArtifact( - FileSystemUtils.appendWithoutExtension(outputJar.getRootRelativePath(), "-gensrc"), - outputJar.getRoot()); } /** @@ -190,9 +217,53 @@ public class JavaCompilationHelper extends BaseJavaCompilationHelper { return getJavacOpts().contains("-processor") || !attributes.getProcessorNames().isEmpty(); } + /** + * 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 + */ + public Artifact createManifestProtoOutput(Artifact outputJar) { + return getAnalysisEnvironment().getDerivedArtifact( + FileSystemUtils.appendExtension(outputJar.getRootRelativePath(), "_manifest_proto"), + outputJar.getRoot()); + } + + /** + * Creates the action for creating the gen jar. + * + * @param classJar The artifact for the class jar emitted from JavaBuilder + * @param manifestProto The artifact for the manifest proto emitted from JavaBuilder + * @param genClassJar The artifact for the gen jar to output + */ + public void createGenJarAction(Artifact classJar, Artifact manifestProto, + Artifact genClassJar) { + getRuleContext().registerAction(new SpawnAction.Builder() + .addInput(manifestProto) + .addInput(classJar) + .addOutput(genClassJar) + .addTransitiveInputs(JavaCompilationHelper.getHostJavabaseInputs(getRuleContext())) + .setJarExecutable( + getRuleContext().getHostConfiguration().getFragment(Jvm.class).getJavaExecutable(), + getRuleContext().getPrerequisiteArtifact("$genclass", Mode.HOST), + ImmutableList.of("-client", GENCLASS_MAX_MEMORY)) + .setCommandLine(CustomCommandLine.builder() + .addExecPath("--manifest_proto", manifestProto) + .addExecPath("--class_jar", classJar) + .addExecPath("--output_jar", genClassJar) + .add("--temp_dir").addPath(tempDir(genClassJar)) + .build()) + .useParameterFile(ParameterFileType.SHELL_QUOTED) + .setProgressMessage("Building genclass jar " + genClassJar.prettyPrint()) + .setMnemonic("JavaSourceJar") + .build(getRuleContext())); + } + public Artifact getOutputDepsProtoArtifact() { return outputDepsProtoArtifact; } + /** * Creates the jdeps file artifact if needed. Returns null if the target can't emit dependency * information (i.e there is no compilation step, the target acts as an alias). 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 6b9fcbb9a8..4b6b50bdb9 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 @@ -19,6 +19,8 @@ import static java.nio.charset.StandardCharsets.ISO_8859_1; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; +import com.google.common.base.Predicates; +import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; @@ -64,6 +66,7 @@ import com.google.devtools.build.lib.vfs.PathFragment; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; @@ -488,6 +491,7 @@ public class JavaCompileAction extends AbstractAction { PathFragment tempDirectory, Artifact outputJar, Artifact gensrcOutputJar, + Artifact manifestProto, boolean compressJar, Artifact outputDepsProto, final NestedSet<Artifact> classpath, @@ -518,11 +522,18 @@ public class JavaCompileAction extends AbstractAction { result.addExecPath("--output", outputJar); } - if (gensrcOutputJar != null) { + if (sourceGenDirectory != null) { result.add("--sourcegendir").addPath(sourceGenDirectory); + } + + if (gensrcOutputJar != null) { result.addExecPath("--generated_sources_output", gensrcOutputJar); } + if (manifestProto != null) { + result.addExecPath("--output_manifest_proto", manifestProto); + } + if (compressJar) { result.add("--compress_jar"); } @@ -730,6 +741,7 @@ public class JavaCompileAction extends AbstractAction { private List<Artifact> javabaseInputs = ImmutableList.of(); private Artifact outputJar; private Artifact gensrcOutputJar; + private Artifact manifestProtoOutput; private Artifact outputDepsProto; private Artifact paramFile; private Artifact metadata; @@ -829,19 +841,12 @@ public class JavaCompileAction extends AbstractAction { Preconditions.checkState(javaExecutable.isAbsolute() ^ !javabaseInputs.isEmpty(), javaExecutable); - Collection<Artifact> outputs; - ImmutableList.Builder<Artifact> outputsBuilder = ImmutableList.builder(); - outputsBuilder.add(outputJar); - if (metadata != null) { - outputsBuilder.add(metadata); - } - if (gensrcOutputJar != null) { - outputsBuilder.add(gensrcOutputJar); - } - if (outputDepsProto != null) { - outputsBuilder.add(outputDepsProto); - } - outputs = outputsBuilder.build(); + Collection<Artifact> outputs = Collections2.filter(Arrays.asList( + outputJar, + metadata, + gensrcOutputJar, + manifestProtoOutput, + outputDepsProto), Predicates.notNull()); CustomCommandLine.Builder paramFileContentsBuilder = javaCompileCommandLine( semantics, @@ -851,6 +856,7 @@ public class JavaCompileAction extends AbstractAction { tempDirectory, outputJar, gensrcOutputJar, + manifestProtoOutput, compressJar, outputDepsProto, classpathEntries, @@ -935,6 +941,11 @@ public class JavaCompileAction extends AbstractAction { return this; } + public Builder setManifestProtoOutput(Artifact manifestProtoOutput) { + this.manifestProtoOutput = manifestProtoOutput; + return this; + } + public Builder setOutputDepsProto(Artifact outputDepsProto) { this.outputDepsProto = outputDepsProto; return this; diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaImport.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaImport.java index 477563ff1e..77850f9a99 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaImport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaImport.java @@ -111,8 +111,17 @@ public class JavaImport implements RuleConfiguredTargetFactory { filesBuilder.addAll(jars); semantics.addProviders( - ruleContext, common, ImmutableList.<String>of(), null, - srcJar, null, compilationToRuntimeJarMap.build(), helper, filesBuilder, ruleBuilder); + ruleContext, + common, + ImmutableList.<String>of(), + null /* classJar */, + srcJar /* srcJar */, + null /* genJar */, + null /* gensrcJar */, + compilationToRuntimeJarMap.build(), + helper, + filesBuilder, + ruleBuilder); NestedSet<Artifact> filesToBuild = filesBuilder.build(); diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java index b22f172945..1355e6f23f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java @@ -117,14 +117,19 @@ public class JavaLibrary implements RuleConfiguredTargetFactory { filesBuilder.add(classJar); - // The gensrcJar is only created if the target uses annotation processing. Otherwise, - // it is null, and the source jar action will not depend on the compile action. + // The gensrc jar is created only if the target uses annotation processing. + // Otherwise, it is null, and the source jar action will not depend on the compile action. Artifact gensrcJar = helper.createGensrcJar(classJar); + Artifact manifestProtoOutput = helper.createManifestProtoOutput(classJar); + + Artifact genClassJar = ruleContext.getImplicitOutputArtifact( + JavaSemantics.JAVA_LIBRARY_GEN_JAR); + helper.createGenJarAction(classJar, manifestProtoOutput, genClassJar); Artifact outputDepsProto = helper.createOutputDepsProtoArtifact(classJar, javaArtifactsBuilder); - helper.createCompileActionWithInstrumentation(classJar, gensrcJar, outputDepsProto, - javaArtifactsBuilder); + helper.createCompileActionWithInstrumentation(classJar, manifestProtoOutput, gensrcJar, + outputDepsProto, javaArtifactsBuilder); helper.createSourceJarAction(srcJar, gensrcJar); if ((attributes.hasSourceFiles() || attributes.hasSourceJars()) && jar != null) { @@ -209,7 +214,7 @@ public class JavaLibrary implements RuleConfiguredTargetFactory { new RuleConfiguredTargetBuilder(ruleContext); semantics.addProviders( - ruleContext, common, ImmutableList.<String>of(), classJar, srcJar, gensrcJar, + ruleContext, common, ImmutableList.<String>of(), classJar, srcJar, genClassJar, gensrcJar, ImmutableMap.<Artifact, Artifact>of(), helper, filesBuilder, builder); NestedSet<Artifact> filesToBuild = filesBuilder.build(); diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java index a28d7fd1af..b8210e226c 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java @@ -239,7 +239,12 @@ public final class JavaLibraryHelper { JavaCompilationHelper helper = new JavaCompilationHelper(ruleContext, semantics, javacOpts, attributes); Artifact outputDepsProto = helper.createOutputDepsProtoArtifact(output, artifactsBuilder); - helper.createCompileAction(output, null, outputDepsProto, null); + helper.createCompileAction( + output, + null /* manifestProtoOutput */, + null /* gensrcOutputJar */, + outputDepsProto, + null /* outputMetadata */); helper.createCompileTimeJarAction(output, outputDepsProto, artifactsBuilder); artifactsBuilder.addRuntimeJar(output); JavaCompilationArtifacts compilationArtifacts = artifactsBuilder.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 0e42112b1f..32549643c2 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 @@ -46,6 +46,7 @@ public class JavaOptions extends FragmentOptions { static final String DEFAULT_LANGTOOLS_EXTDIR = "//tools/jdk:extdir"; static final String DEFAULT_JAVABUILDER = "//tools/jdk:JavaBuilder_deploy.jar"; static final String DEFAULT_SINGLEJAR = "//tools/jdk:SingleJar_deploy.jar"; + static final String DEFAULT_GENCLASS = "//tools/jdk:GenClass_deploy.jar"; static final String DEFAULT_JAVABASE = "//tools/jdk:jdk"; static final String DEFAULT_IJAR = "//tools/jdk:ijar"; static final String DEFAULT_TOOLCHAIN = "//tools/jdk:toolchain"; @@ -225,6 +226,13 @@ public class JavaOptions extends FragmentOptions { help = "Label of the filegroup that contains the SingleJar jar.") public Label singleJarTop; + @Option(name = "genclass_top", + defaultValue = DEFAULT_GENCLASS, + category = "version", + converter = LabelConverter.class, + help = "Label of the filegroup that contains the GenClass jar.") + public Label genClassTop; + @Option(name = "ijar_top", defaultValue = DEFAULT_IJAR, category = "version", @@ -295,6 +303,7 @@ public class JavaOptions extends FragmentOptions { host.javaBuilderTop = javaBuilderTop; host.javaToolchain = javaToolchain; host.singleJarTop = singleJarTop; + host.genClassTop = genClassTop; host.iJarTop = iJarTop; // Java builds often contain complicated code generators for which @@ -316,6 +325,7 @@ public class JavaOptions extends FragmentOptions { } labelMap.put("javabuilder", javaBuilderTop); labelMap.put("singlejar", singleJarTop); + labelMap.put("genclass", genClassTop); labelMap.put("ijar", iJarTop); labelMap.put("java_toolchain", javaToolchain); labelMap.putAll("translation", getTranslationLabels()); @@ -333,6 +343,7 @@ public class JavaOptions extends FragmentOptions { result.put("JAVAC_EXTDIR", ImmutableSet.of(javacExtdir)); result.put("JAVABUILDER", ImmutableSet.of(javaBuilderTop)); result.put("SINGLEJAR", ImmutableSet.of(singleJarTop)); + result.put("GENCLASS", ImmutableSet.of(genClassTop)); result.put("IJAR", ImmutableSet.of(iJarTop)); result.put("JAVA_TOOLCHAIN", ImmutableSet.of(javaToolchain)); diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java index a68dcd46d2..5f17262706 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java @@ -55,12 +55,18 @@ public interface JavaSemantics { public static final SafeImplicitOutputsFunction JAVA_LIBRARY_CLASS_JAR = fromTemplates("lib%{name}.jar"); + public static final SafeImplicitOutputsFunction JAVA_LIBRARY_GEN_JAR = + fromTemplates("lib%{name}-gen.jar"); public static final SafeImplicitOutputsFunction JAVA_LIBRARY_SOURCE_JAR = fromTemplates("lib%{name}-src.jar"); + public static final SafeImplicitOutputsFunction JAVA_BINARY_CLASS_JAR = fromTemplates("%{name}.jar"); + public static final SafeImplicitOutputsFunction JAVA_BINARY_GEN_JAR = + fromTemplates("%{name}-gen.jar"); public static final SafeImplicitOutputsFunction JAVA_BINARY_SOURCE_JAR = fromTemplates("%{name}-src.jar"); + public static final SafeImplicitOutputsFunction JAVA_BINARY_DEPLOY_JAR = fromTemplates("%{name}_deploy.jar"); public static final SafeImplicitOutputsFunction JAVA_BINARY_DEPLOY_SOURCE_JAR = @@ -119,6 +125,12 @@ public interface JavaSemantics { public static final String SINGLEJAR_LABEL = "//tools/defaults:singlejar"; /** + * Label of the GenClass JAR used for creating the jar for classes from sources generated from + * annotation processors. + */ + public static final String GENCLASS_LABEL = "//tools/defaults:genclass"; + + /** * Label of pseudo-cc_binary that tells Blaze a java target's JAVABIN is never to be replaced by * the contents of --java_launcher; only the JDK's launcher will ever be used. */ @@ -279,6 +291,7 @@ public interface JavaSemantics { List<String> jvmFlags, Artifact classJar, Artifact srcJar, + Artifact genJar, Artifact gensrcJar, ImmutableMap<Artifact, Artifact> compilationToRuntimeJarMap, JavaCompilationHelper helper, diff --git a/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java b/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java index 8a66f0f006..7c922494e2 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java @@ -56,7 +56,7 @@ public class BazelAnalysisMock extends AnalysisMock { // "dummy" is needed so that RedirectChaser stops here "filegroup(name='java', srcs = ['jdk/jre/bin/java', 'dummy'])", "exports_files(['JavaBuilder_deploy.jar','SingleJar_deploy.jar',", - " 'JavaBuilderCanary_deploy.jar', 'ijar'])"); + " 'JavaBuilderCanary_deploy.jar', 'ijar', 'GenClass_deploy.jar'])"); config.create("tools/cpp/BUILD", "filegroup(name = 'toolchain', srcs = [':cc-compiler-local', ':empty'])", "cc_toolchain(name = 'cc-compiler-k8', all_files = ':empty', compiler_files = ':empty',", diff --git a/src/test/shell/bazel/BUILD b/src/test/shell/bazel/BUILD index 116b1367e6..3880ce0258 100644 --- a/src/test/shell/bazel/BUILD +++ b/src/test/shell/bazel/BUILD @@ -21,6 +21,7 @@ filegroup( "//external:jdk-default", "//src:bazel", "//src/java_tools/buildjar:JavaBuilder_deploy.jar", + "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass:GenClass_deploy.jar", "//src/java_tools/singlejar:SingleJar_deploy.jar", "//src/test/shell:bashunit", "//third_party:srcs", diff --git a/src/test/shell/bazel/test-setup.sh b/src/test/shell/bazel/test-setup.sh index 21eb3772fc..1d71f29d08 100755 --- a/src/test/shell/bazel/test-setup.sh +++ b/src/test/shell/bazel/test-setup.sh @@ -212,6 +212,7 @@ function create_new_workspace() { ln -s "${javabuilder_path}" tools/jdk/JavaBuilder_deploy.jar ln -s "${singlejar_path}" tools/jdk/SingleJar_deploy.jar + ln -s "${genclass_path}" tools/jdk/GenClass_deploy.jar ln -s "${ijar_path}" tools/jdk/ijar setup_android_support diff --git a/src/test/shell/bazel/testenv.sh b/src/test/shell/bazel/testenv.sh index 12afe3635f..44d15f35c0 100755 --- a/src/test/shell/bazel/testenv.sh +++ b/src/test/shell/bazel/testenv.sh @@ -41,6 +41,7 @@ EXTRA_BAZELRC="build --java_langtools=//tools/jdk:test-langtools" javabuilder_path="${TEST_SRCDIR}/src/java_tools/buildjar/JavaBuilder_deploy.jar" langtools_path="${TEST_SRCDIR}/third_party/java/jdk/langtools/javac.jar" singlejar_path="${TEST_SRCDIR}/src/java_tools/singlejar/SingleJar_deploy.jar" +genclass_path="${TEST_SRCDIR}/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/genclass/GenClass_deploy.jar" ijar_path="${TEST_SRCDIR}/third_party/ijar/ijar" # Third-party diff --git a/tools/jdk/BUILD b/tools/jdk/BUILD index de26dd9ecd..e15e8bf175 100644 --- a/tools/jdk/BUILD +++ b/tools/jdk/BUILD @@ -82,6 +82,7 @@ exports_files([ "JavaBuilder_deploy.jar", "ijar", "SingleJar_deploy.jar", + "GenClass_deploy.jar", ]) filegroup( |