diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java | 161 |
1 files changed, 149 insertions, 12 deletions
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 fec64a367a..9ae2dbee79 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 @@ -23,6 +23,8 @@ import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType; import com.google.devtools.build.lib.analysis.AnalysisEnvironment; import com.google.devtools.build.lib.analysis.AnalysisUtils; +import com.google.devtools.build.lib.analysis.FileProvider; +import com.google.devtools.build.lib.analysis.FilesToRunProvider; 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; @@ -34,6 +36,7 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.rules.java.JavaConfiguration.JavaClasspathMode; import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector; +import com.google.devtools.build.lib.util.FileType; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.PathFragment; @@ -50,8 +53,12 @@ import javax.annotation.Nullable; * <p> * Also supports the creation of resource and source only Jars. */ -public final class JavaCompilationHelper extends BaseJavaCompilationHelper { +public final class JavaCompilationHelper { + private final RuleContext ruleContext; + private final JavaToolchainProvider javaToolchain; + private final NestedSet<Artifact> hostJavabase; + private final Iterable<Artifact> jacocoInstrumentation; private JavaTargetAttributes.Builder attributes; private JavaTargetAttributes builtAttributes; private final ImmutableList<String> customJavacOpts; @@ -59,13 +66,18 @@ public final class JavaCompilationHelper extends BaseJavaCompilationHelper { private final List<Artifact> translations = new ArrayList<>(); private boolean translationsFrozen; private final JavaSemantics semantics; - private final String implicitAttributesSuffix; + + private static final String DEFAULT_ATTRIBUTES_SUFFIX = ""; public JavaCompilationHelper(RuleContext ruleContext, JavaSemantics semantics, ImmutableList<String> javacOpts, JavaTargetAttributes.Builder attributes, - String implicitAttributesSuffix) { - super(ruleContext, implicitAttributesSuffix); - this.implicitAttributesSuffix = implicitAttributesSuffix; + JavaToolchainProvider javaToolchainProvider, + NestedSet<Artifact> hostJavabase, + Iterable<Artifact> jacocoInstrumentation) { + this.ruleContext = ruleContext; + this.javaToolchain = javaToolchainProvider; + this.hostJavabase = hostJavabase; + this.jacocoInstrumentation = jacocoInstrumentation; this.attributes = attributes; this.customJavacOpts = javacOpts; this.customJavacJvmOpts = javaToolchain.getJvmOptions(); @@ -74,7 +86,10 @@ public final class JavaCompilationHelper extends BaseJavaCompilationHelper { public JavaCompilationHelper(RuleContext ruleContext, JavaSemantics semantics, ImmutableList<String> javacOpts, JavaTargetAttributes.Builder attributes) { - this(ruleContext, semantics, javacOpts, attributes, ""); + this(ruleContext, semantics, javacOpts, attributes, + getJavaToolchainProvider(ruleContext), + getHostJavabaseInputsNonStatic(ruleContext), + getInstrumentationJars(ruleContext)); } public JavaCompilationHelper(RuleContext ruleContext, JavaSemantics semantics, @@ -138,7 +153,7 @@ public final class JavaCompilationHelper extends BaseJavaCompilationHelper { builder.setGensrcOutputJar(gensrcOutputJar); builder.setOutputDepsProto(outputDepsProto); builder.setMetadata(outputMetadata); - builder.setInstrumentationJars(getInstrumentationJars()); + builder.setInstrumentationJars(jacocoInstrumentation); builder.addSourceFiles(attributes.getSourceFiles()); builder.addSourceJars(attributes.getSourceJars()); builder.setJavacOpts(customJavacOpts); @@ -267,7 +282,7 @@ public final class JavaCompilationHelper extends BaseJavaCompilationHelper { JavaTargetAttributes attributes = getAttributes(); JavaHeaderCompileAction.Builder builder = - new JavaHeaderCompileAction.Builder(getRuleContext(), implicitAttributesSuffix); + new JavaHeaderCompileAction.Builder(getRuleContext()); builder.addSourceFiles(attributes.getSourceFiles()); builder.addSourceJars(attributes.getSourceJars()); builder.setClasspathEntries(attributes.getCompileTimeClassPath()); @@ -287,9 +302,9 @@ public final class JavaCompilationHelper extends BaseJavaCompilationHelper { builder.setDirectJars(attributes.getDirectJars()); builder.setRuleKind(attributes.getRuleKind()); builder.setTargetLabel(attributes.getTargetLabel()); - builder.setJavaBaseInputs(getHostJavabaseInputsNonStatic(ruleContext)); + builder.setJavaBaseInputs(hostJavabase); builder.setJavacJar(javaToolchain.getJavac()); - builder.build(); + builder.build(javaToolchain); artifactBuilder.setCompileTimeDependencies(headerDeps); return headerJar; @@ -451,7 +466,7 @@ public final class JavaCompilationHelper extends BaseJavaCompilationHelper { JavaCompileAction.Builder builder = new JavaCompileAction.Builder(ruleContext, semantics); builder.setJavaExecutable( ruleContext.getHostConfiguration().getFragment(Jvm.class).getJavaExecutable()); - builder.setJavaBaseInputs(getHostJavabaseInputsNonStatic(ruleContext)); + builder.setJavaBaseInputs(hostJavabase); builder.setTargetLabel(ruleContext.getLabel()); return builder; } @@ -518,7 +533,7 @@ public final class JavaCompilationHelper extends BaseJavaCompilationHelper { if (shouldUseHeaderCompilation()) { jar = createHeaderCompilationAction(runtimeJar, builder); } else if (getJavaConfiguration().getUseIjars()) { - jar = createIjarAction(runtimeJar, false); + jar = createIjarAction(ruleContext, javaToolchain, runtimeJar, false); } else { jar = runtimeJar; } @@ -631,4 +646,126 @@ public final class JavaCompilationHelper extends BaseJavaCompilationHelper { translationsFrozen = true; return ImmutableList.copyOf(translations); } + + public static JavaToolchainProvider getJavaToolchainProvider( + RuleContext ruleContext, String implicitAttributesSuffix) { + return ruleContext.getPrerequisite( + ":java_toolchain" + implicitAttributesSuffix, Mode.TARGET, JavaToolchainProvider.class); + } + + public static JavaToolchainProvider getJavaToolchainProvider(RuleContext ruleContext) { + return getJavaToolchainProvider(ruleContext, DEFAULT_ATTRIBUTES_SUFFIX); + } + + /** + * Returns the artifacts required to invoke {@code javahome} relative binary + * in the action. + */ + public static NestedSet<Artifact> getHostJavabaseInputsNonStatic( + RuleContext ruleContext, String implicitAttributesSuffix) { + // This must have a different name than above, because the middleman creation uses the rule's + // configuration, although it should use the host configuration. + return AnalysisUtils.getMiddlemanFor(ruleContext, ":host_jdk" + implicitAttributesSuffix); + } + + public static NestedSet<Artifact> getHostJavabaseInputsNonStatic(RuleContext ruleContext) { + return getHostJavabaseInputsNonStatic(ruleContext, DEFAULT_ATTRIBUTES_SUFFIX); + } + + /** + * Returns the instrumentation jar in the given semantics. + */ + public static Iterable<Artifact> getInstrumentationJars( + RuleContext ruleContext, String implicitAttributesSuffix) { + TransitiveInfoCollection instrumentationTarget = ruleContext.getPrerequisite( + "$jacoco_instrumentation" + implicitAttributesSuffix, Mode.HOST); + if (instrumentationTarget == null) { + return ImmutableList.<Artifact>of(); + } + return FileType.filter( + instrumentationTarget.getProvider(FileProvider.class).getFilesToBuild(), + JavaSemantics.JAR); + } + + public static Iterable<Artifact> getInstrumentationJars(RuleContext ruleContext) { + return getInstrumentationJars(ruleContext, DEFAULT_ATTRIBUTES_SUFFIX); + } + + /** + * Returns the javac bootclasspath artifacts from the given toolchain (if it has any) or the rule. + */ + public static ImmutableList<Artifact> getBootClasspath(JavaToolchainProvider javaToolchain) { + return ImmutableList.copyOf(javaToolchain.getBootclasspath()); + } + + private ImmutableList<Artifact> getBootClasspath() { + return ImmutableList.copyOf(javaToolchain.getBootclasspath()); + } + + /** + * Returns the extdir artifacts. + */ + private final ImmutableList<Artifact> getExtdirInputs() { + return ImmutableList.copyOf(javaToolchain.getExtclasspath()); + } + + /** + * Creates the Action that creates ijars from Jar files. + * + * @param inputJar the Jar to create the ijar for + * @param addPrefix whether to prefix the path of the generated ijar with the package and + * name of the current rule + * @return the Artifact to create with the Action + */ + protected static Artifact createIjarAction( + RuleContext ruleContext, + JavaToolchainProvider javaToolchain, + Artifact inputJar, boolean addPrefix) { + Artifact interfaceJar = getIjarArtifact(ruleContext, inputJar, addPrefix); + FilesToRunProvider ijarTarget = javaToolchain.getIjar(); + if (!ruleContext.hasErrors()) { + ruleContext.registerAction(new SpawnAction.Builder() + .addInput(inputJar) + .addOutput(interfaceJar) + .setExecutable(ijarTarget) + // On Windows, ijar.exe needs msys-2.0.dll and zlib1.dll in PATH. + // Use default shell environment so that those can be found. + // TODO(dslomov): revisit this. If ijar is not msys-dependent, this is not needed. + .useDefaultShellEnvironment() + .addArgument(inputJar.getExecPathString()) + .addArgument(interfaceJar.getExecPathString()) + .setProgressMessage("Extracting interface " + ruleContext.getLabel()) + .setMnemonic("JavaIjar") + .build(ruleContext)); + } + return interfaceJar; + } + + private static Artifact getIjarArtifact( + RuleContext ruleContext, Artifact jar, boolean addPrefix) { + if (addPrefix) { + PathFragment ruleBase = ruleContext.getUniqueDirectory("_ijar"); + PathFragment artifactDirFragment = jar.getRootRelativePath().getParentDirectory(); + String ijarBasename = FileSystemUtils.removeExtension(jar.getFilename()) + "-ijar.jar"; + return ruleContext.getDerivedArtifact( + ruleBase.getRelative(artifactDirFragment).getRelative(ijarBasename), + ruleContext.getConfiguration().getGenfilesDirectory( + ruleContext.getRule().getRepository())); + } else { + return derivedArtifact(ruleContext, jar, "", "-ijar.jar"); + } + } + + /** + * Creates a derived artifact from the given artifact by adding the given + * prefix and removing the extension and replacing it by the given suffix. + * The new artifact will have the same root as the given one. + */ + private static Artifact derivedArtifact( + RuleContext ruleContext, Artifact artifact, String prefix, String suffix) { + PathFragment path = artifact.getRootRelativePath(); + String basename = FileSystemUtils.removeExtension(path.getBaseName()) + suffix; + path = path.replaceName(prefix + basename); + return ruleContext.getDerivedArtifact(path, artifact.getRoot()); + } } |