diff options
author | tomlu <tomlu@google.com> | 2018-02-13 11:06:45 -0800 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-02-13 11:08:35 -0800 |
commit | f365d3f3451c3aac00990d7c5c9a2610d96cc2cd (patch) | |
tree | 171cd5c28e280e2f805890d13064e6fa7d010352 /src/java_tools/buildjar | |
parent | 49ecd1f37ae2abcfe5a68951fe6b118345509907 (diff) |
Accept --target_label, --injecting_rule_kind in JavaBuilder and Turbine.
The values (if present) are written into the manifest with this format:
Target-Label: <label>
Injecting-Rule-Kind: <kind>
In the future, JavaBuilder will make sure of this instead of command line arguments to find owners for jars for its add_dep commands.
PiperOrigin-RevId: 185557317
Diffstat (limited to 'src/java_tools/buildjar')
7 files changed, 131 insertions, 22 deletions
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java index 2f7a6045aa..01ba5f1cd9 100644 --- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java +++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/JavaLibraryBuildRequest.java @@ -62,6 +62,8 @@ public final class JavaLibraryBuildRequest { private final Path outputJar; private final Path nativeHeaderOutput; + @Nullable private final String targetLabel; + @Nullable private final String injectingRuleKind; private final Path classDir; private final Path tempDir; @@ -183,6 +185,8 @@ public final class JavaLibraryBuildRequest { this.sourceGenDir = asPath(optionsParser.getSourceGenDir()); this.generatedSourcesOutputJar = asPath(optionsParser.getGeneratedSourcesOutputJar()); this.generatedClassOutputJar = asPath(optionsParser.getManifestProtoPath()); + this.targetLabel = optionsParser.getTargetLabel(); + this.injectingRuleKind = optionsParser.getInjectingRuleKind(); } private static ImmutableList<Path> asPaths(Collection<String> paths) { @@ -288,6 +292,16 @@ public final class JavaLibraryBuildRequest { return plugins; } + @Nullable + public String getTargetLabel() { + return targetLabel; + } + + @Nullable + public String getInjectingRuleKind() { + return injectingRuleKind; + } + public BlazeJavacArguments toBlazeJavacArguments(ImmutableList<Path> classPath) { BlazeJavacArguments.Builder builder = BlazeJavacArguments.builder() diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/OptionsParser.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/OptionsParser.java index f2cdeea4ee..5413e5312d 100644 --- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/OptionsParser.java +++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/OptionsParser.java @@ -83,7 +83,8 @@ public final class OptionsParser { private String ruleKind; private String targetLabel; - + private String injectingRuleKind; + private boolean testOnly; /** @@ -219,6 +220,9 @@ public final class OptionsParser { case "--target_label": targetLabel = getArgument(argQueue, arg); break; + case "--injecting_rule_kind": + injectingRuleKind = getArgument(argQueue, arg); + break; case "--testonly": testOnly = true; break; @@ -524,7 +528,11 @@ public final class OptionsParser { public String getTargetLabel() { return targetLabel; } - + + public String getInjectingRuleKind() { + return injectingRuleKind; + } + public boolean testOnly() { return testOnly; } diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/SimpleJavaLibraryBuilder.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/SimpleJavaLibraryBuilder.java index d5dd08688d..50c936ac43 100644 --- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/SimpleJavaLibraryBuilder.java +++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/SimpleJavaLibraryBuilder.java @@ -152,6 +152,7 @@ public class SimpleJavaLibraryBuilder implements Closeable { jar.setNormalize(true); jar.setCompression(build.compressJar()); jar.addDirectory(build.getClassDir()); + jar.setJarOwner(build.getTargetLabel(), build.getInjectingRuleKind()); JacocoInstrumentationProcessor processor = build.getJacocoInstrumentationProcessor(); if (processor != null) { processor.processRequest(build, processor.isNewCoverageImplementation() ? jar : null); diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarCreator.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarCreator.java index bb8be68004..b0bcb2bb48 100644 --- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarCreator.java +++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarCreator.java @@ -45,6 +45,8 @@ public class JarCreator extends JarHelper { private final TreeMap<String, Path> jarEntries = new TreeMap<>(); private String manifestFile; private String mainClass; + private String targetLabel; + private String injectingRuleKind; /** @deprecated use {@link JarCreator(Path)} instead */ @Deprecated @@ -182,6 +184,11 @@ public class JarCreator extends JarHelper { this.mainClass = mainClass; } + public void setJarOwner(String targetLabel, String injectingRuleKind) { + this.targetLabel = targetLabel; + this.injectingRuleKind = injectingRuleKind; + } + /** * Sets filename for the manifest content. If this is set the manifest will be read from this file * otherwise the manifest content will get generated on the fly. @@ -207,11 +214,17 @@ public class JarCreator extends JarHelper { attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0"); Attributes.Name createdBy = new Attributes.Name("Created-By"); if (attributes.getValue(createdBy) == null) { - attributes.put(createdBy, "blaze"); + attributes.put(createdBy, "bazel"); } if (mainClass != null) { attributes.put(Attributes.Name.MAIN_CLASS, mainClass); } + if (targetLabel != null) { + attributes.put(JarHelper.TARGET_LABEL, targetLabel); + } + if (injectingRuleKind != null) { + attributes.put(JarHelper.INJECTING_RULE_KIND, injectingRuleKind); + } ByteArrayOutputStream out = new ByteArrayOutputStream(); manifest.write(out); return out.toByteArray(); diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarHelper.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarHelper.java index 719fcdbee5..2860fa4965 100644 --- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarHelper.java +++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarHelper.java @@ -22,6 +22,7 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.util.HashSet; import java.util.Set; +import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; @@ -46,6 +47,13 @@ public class JarHelper { .atZone(ZoneId.systemDefault()) .toInstant() .toEpochMilli(); + // These attributes are used by JavaBuilder, Turbine, and ijar. + // They must all be kept in sync. + public static final Attributes.Name TARGET_LABEL = new Attributes.Name("Target-Label"); + public static final Attributes.Name INJECTING_RULE_KIND = + new Attributes.Name("Injecting-Rule-Kind"); + + public static final long DOS_EPOCH_IN_JAVA_TIME = 315561600000L; // ZIP timestamps have a resolution of 2 seconds. // see http://www.info-zip.org/FAQ.html#limits diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbine.java b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbine.java index 876e9c0309..99c195d55b 100644 --- a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbine.java +++ b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbine.java @@ -32,6 +32,7 @@ import com.google.turbine.options.TurbineOptionsParser; import com.sun.tools.javac.util.Context; import java.io.BufferedOutputStream; import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; @@ -47,6 +48,9 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; import java.util.regex.Pattern; import java.util.zip.ZipOutputStream; import org.objectweb.asm.ClassReader; @@ -64,6 +68,13 @@ import org.objectweb.asm.Opcodes; */ public class JavacTurbine implements AutoCloseable { + // These attributes are used by JavaBuilder, Turbine, and ijar. + // They must all be kept in sync. + static final String MANIFEST_DIR = "META-INF/"; + static final String MANIFEST_NAME = JarFile.MANIFEST_NAME; + static final Attributes.Name TARGET_LABEL = new Attributes.Name("Target-Label"); + static final Attributes.Name INJECTING_RULE_KIND = new Attributes.Name("Injecting-Rule-Kind"); + public static void main(String[] args) throws IOException { System.exit(compile(TurbineOptionsParser.parse(Arrays.asList(args))).exitCode()); } @@ -192,9 +203,7 @@ public class JavacTurbine implements AutoCloseable { if (sources.isEmpty()) { // accept compilations with an empty source list for compatibility with JavaBuilder emitClassJar( - Paths.get(turbineOptions.outputFile()), - /* files= */ ImmutableMap.of(), - /* transitive= */ ImmutableMap.of()); + turbineOptions, /* files= */ ImmutableMap.of(), /* transitive= */ ImmutableMap.of()); dependencyModule.emitDependencyInformation( /*classpath=*/ ImmutableList.of(), /*successful=*/ true); return Result.OK_WITH_REDUCED_CLASSPATH; @@ -238,9 +247,7 @@ public class JavacTurbine implements AutoCloseable { if (result.ok()) { emitClassJar( - Paths.get(turbineOptions.outputFile()), - compileResult.files(), - transitive.collectTransitiveDependencies()); + turbineOptions, compileResult.files(), transitive.collectTransitiveDependencies()); dependencyModule.emitDependencyInformation(actualClasspath, compileResult.success()); } else { out.print(compileResult.output()); @@ -292,8 +299,9 @@ public class JavacTurbine implements AutoCloseable { /** Write the class output from a successful compilation to the output jar. */ private static void emitClassJar( - Path outputJar, Map<String, byte[]> files, Map<String, byte[]> transitive) + TurbineOptions turbineOptions, Map<String, byte[]> files, Map<String, byte[]> transitive) throws IOException { + Path outputJar = Paths.get(turbineOptions.outputFile()); try (OutputStream fos = Files.newOutputStream(outputJar); ZipOutputStream zipOut = new ZipOutputStream(new BufferedOutputStream(fos, ZIPFILE_BUFFER_SIZE))) { @@ -313,7 +321,31 @@ public class JavacTurbine implements AutoCloseable { } ZipUtil.storeEntry(name, bytes, zipOut); } + + if (turbineOptions.targetLabel().isPresent()) { + ZipUtil.storeEntry(MANIFEST_DIR, new byte[] {}, zipOut); + ZipUtil.storeEntry(MANIFEST_NAME, manifestContent(turbineOptions), zipOut); + } + } + } + + private static byte[] manifestContent(TurbineOptions turbineOptions) throws IOException { + Manifest manifest = new Manifest(); + Attributes attributes = manifest.getMainAttributes(); + attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0"); + Attributes.Name createdBy = new Attributes.Name("Created-By"); + if (attributes.getValue(createdBy) == null) { + attributes.put(createdBy, "bazel"); + } + if (turbineOptions.targetLabel().isPresent()) { + attributes.put(TARGET_LABEL, turbineOptions.targetLabel().get()); + } + if (turbineOptions.injectingRuleKind().isPresent()) { + attributes.put(INJECTING_RULE_KIND, turbineOptions.injectingRuleKind().get()); } + ByteArrayOutputStream out = new ByteArrayOutputStream(); + manifest.write(out); + return out.toByteArray(); } /** diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java index 5849eb851e..d6159d96f5 100644 --- a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java +++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java @@ -16,6 +16,7 @@ package com.google.devtools.build.java.turbine.javac; import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.stream.Collectors.toSet; import com.google.common.base.Function; import com.google.common.base.Joiner; @@ -53,6 +54,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; @@ -61,9 +64,11 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; @@ -105,7 +110,7 @@ public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest { Map<String, byte[]> outputs = collectOutputs(); - assertThat(outputs.keySet()).containsExactly("Hello.class"); + assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Hello.class"); String text = textify(outputs.get("Hello.class")); String[] expected = { @@ -136,7 +141,7 @@ public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest { Map<String, byte[]> outputs = collectOutputs(); - assertThat(outputs.keySet()).containsExactly("Hello.class"); + assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Hello.class"); String text = textify(outputs.get("Hello.class")); String[] expected = { @@ -228,7 +233,7 @@ public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest { compile(); Map<String, byte[]> outputs = collectOutputs(); - assertThat(outputs.keySet()) + assertThat(filterManifestEntries(outputs.keySet())) .containsExactly( "Generated.class", "MyAnnotation.class", "Hello.class", "com/foo/hello.txt"); @@ -629,7 +634,7 @@ public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest { Map<String, byte[]> outputs = collectOutputs(); - assertThat(outputs.keySet()).containsExactly("Const.class"); + assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Const.class"); String text = textify(outputs.get("Const.class")); String[] expected = { @@ -678,7 +683,7 @@ public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest { compile(); Map<String, byte[]> outputs = collectOutputs(); // just don't crash; enum constants need to be preserved - assertThat(outputs.keySet()).containsExactly("TheEnum.class"); + assertThat(filterManifestEntries(outputs.keySet())).containsExactly("TheEnum.class"); String text = textify(outputs.get("TheEnum.class")); String[] expected = { @@ -790,7 +795,8 @@ public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest { Map<String, byte[]> outputs = collectOutputs(); - assertThat(outputs.keySet()).containsExactly("Super.class", "Hello.class"); + assertThat(filterManifestEntries(outputs.keySet())) + .containsExactly("Super.class", "Hello.class"); String text = textify(outputs.get("Hello.class")); String[] expected = { @@ -825,7 +831,8 @@ public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest { Map<String, byte[]> outputs = collectOutputs(); - assertThat(outputs.keySet()).containsExactly("Anno.class", "Hello.class"); + assertThat(filterManifestEntries(outputs.keySet())) + .containsExactly("Anno.class", "Hello.class"); String text = textify(outputs.get("Hello.class")); String[] expected = { @@ -880,7 +887,7 @@ public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest { Map<String, byte[]> outputs = collectOutputs(); - assertThat(outputs.keySet()).containsExactly("Hello.class"); + assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Hello.class"); String text = textify(outputs.get("Hello.class")); String[] expected = { @@ -953,7 +960,7 @@ public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest { // don't set up any source files compile(); Map<String, byte[]> outputs = collectOutputs(); - assertThat(outputs.keySet()).isEmpty(); + assertThat(filterManifestEntries(outputs.keySet())).isEmpty(); } /** An annotation processor that violates the contract. */ @@ -1067,7 +1074,7 @@ public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest { compile(); Map<String, byte[]> outputs = collectOutputs(); - assertThat(outputs.keySet()).containsExactly("Hello.class"); + assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Hello.class"); } public static class Lib {} @@ -1115,7 +1122,7 @@ public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest { Map<String, byte[]> outputs = collectOutputs(); - assertThat(outputs.keySet()).containsExactly("Hello.class"); + assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Hello.class"); String text = textify(outputs.get("Hello.class")); String[] expected = { @@ -1148,7 +1155,7 @@ public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest { Map<String, byte[]> outputs = collectOutputs(); - assertThat(outputs.keySet()).containsExactly("Bridge.class"); + assertThat(filterManifestEntries(outputs.keySet())).containsExactly("Bridge.class"); String text = textify(outputs.get("Bridge.class")); String[] expected = { @@ -1326,5 +1333,31 @@ public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest { assertThat(javacopts).contains("--release"); assertThat(javacopts).containsNoneOf("-source", "-target"); } + + @Test + public void testManifestEntries() throws Exception { + optionsBuilder.setTargetLabel("//foo:foo"); + optionsBuilder.setInjectingRuleKind("foo_library"); + compile(); + try (JarFile jarFile = new JarFile(output.toFile())) { + Manifest manifest = jarFile.getManifest(); + Attributes attributes = manifest.getMainAttributes(); + assertThat(attributes.getValue("Target-Label")).isEqualTo("//foo:foo"); + assertThat(attributes.getValue("Injecting-Rule-Kind")).isEqualTo("foo_library"); + assertThat(jarFile.getEntry(JarFile.MANIFEST_NAME).getLastModifiedTime().toInstant()) + .isEqualTo( + LocalDateTime.of(2010, 1, 1, 0, 0, 0).atZone(ZoneId.systemDefault()).toInstant()); + } + } + + private static Set<String> filterManifestEntries(Set<String> entries) { + return entries + .stream() + .filter( + name -> + !(name.equals(JavacTurbine.MANIFEST_DIR) + || name.equals(JavacTurbine.MANIFEST_NAME))) + .collect(toSet()); + } } |