aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationHelper.java32
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java29
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java71
4 files changed, 130 insertions, 10 deletions
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 ed229fee77..2e7f0c5bd0 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
@@ -175,7 +175,8 @@ public class JavaBinary implements RuleConfiguredTargetFactory {
executableForRunfiles,
instrumentationMetadata,
javaArtifactsBuilder,
- mainClass);
+ mainClass,
+ ruleContext.getConfiguration().isExperimentalJavaCoverage());
}
} else {
filesBuilder.add(classJar);
@@ -262,6 +263,8 @@ public class JavaBinary implements RuleConfiguredTargetFactory {
jvmFlags,
executableForRunfiles,
mainClass,
+ originalMainClass,
+ filesBuilder,
javaExecutable);
if (!executableToRun.equals(executableForRunfiles)) {
filesBuilder.add(executableToRun);
@@ -526,7 +529,8 @@ public class JavaBinary implements RuleConfiguredTargetFactory {
builder.addTargets(runtimeDeps, RunfilesProvider.DEFAULT_RUNFILES);
semantics.addDependenciesForRunfiles(ruleContext, builder);
- if (ruleContext.getConfiguration().isCodeCoverageEnabled()) {
+ if (ruleContext.getConfiguration().isCodeCoverageEnabled()
+ && !ruleContext.getConfiguration().isExperimentalJavaCoverage()) {
Artifact instrumentedJar = javaArtifacts.getInstrumentedJar();
if (instrumentedJar != null) {
builder.addArtifact(instrumentedJar);
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 64140170cf..75877350ac 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
@@ -168,14 +168,15 @@ public final class JavaCompilationHelper {
* (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).
+ * @param instrumentationMetadataJar metadata file (null if no instrumentation is needed or if
+ * --experimental_java_coverage is true).
*/
public void createCompileAction(
Artifact outputJar,
Artifact manifestProtoOutput,
@Nullable Artifact gensrcOutputJar,
@Nullable Artifact outputDepsProto,
- @Nullable Artifact outputMetadata) {
+ @Nullable Artifact instrumentationMetadataJar) {
JavaTargetAttributes attributes = getAttributes();
@@ -196,6 +197,7 @@ public final class JavaCompilationHelper {
}
JavaCompileAction.Builder builder = createJavaCompileActionBuilder(semantics);
+ builder.setArtifactForExperimentalCoverage(maybeCreateExperimentalCoverageArtifact(outputJar));
builder.setClasspathEntries(attributes.getCompileTimeClassPath());
builder.setBootclasspathEntries(getBootclasspathOrDefault());
builder.setSourcePathEntries(attributes.getSourcePath());
@@ -208,7 +210,7 @@ public final class JavaCompilationHelper {
builder.setGensrcOutputJar(gensrcOutputJar);
builder.setOutputDepsProto(outputDepsProto);
builder.setAdditionalOutputs(attributes.getAdditionalOutputs());
- builder.setMetadata(outputMetadata);
+ builder.setMetadata(instrumentationMetadataJar);
builder.setInstrumentationJars(jacocoInstrumentation);
builder.setSourceFiles(attributes.getSourceFiles());
builder.addSourceJars(attributes.getSourceJars());
@@ -253,6 +255,26 @@ public final class JavaCompilationHelper {
}
/**
+ * Creates an {@link Artifact} needed by {@code JacocoCoverageRunner} when
+ * {@code --experimental_java_coverage} is true.
+ *
+ * <p> The {@link Artifact} is created in the same directory as the given {@code compileJar} and
+ * has the suffix {@code -paths-for-coverage.txt}.
+ *
+ * <p> Returns {@code null} if {@code compileJar} should not be instrumented.
+ */
+ private Artifact maybeCreateExperimentalCoverageArtifact(Artifact compileJar) {
+ if (!shouldInstrumentJar() || !getConfiguration().isExperimentalJavaCoverage()) {
+ return null;
+ }
+ PathFragment packageRelativePath =
+ compileJar.getRootRelativePath().relativeTo(ruleContext.getPackageDirectory());
+ PathFragment path =
+ FileSystemUtils.replaceExtension(packageRelativePath, "-paths-for-coverage.txt");
+ return ruleContext.getPackageRelativeArtifact(path, compileJar.getRoot());
+ }
+
+ /**
* Returns the instrumentation metadata files to be generated for a given output jar.
*
* <p>Only called if the output jar actually needs to be instrumented.
@@ -299,6 +321,10 @@ public final class JavaCompilationHelper {
@Nullable
public Artifact createInstrumentationMetadata(Artifact outputJar,
JavaCompilationArtifacts.Builder javaArtifactsBuilder) {
+ // In the experimental java coverage we don't create the .em jar for instrumentation.
+ if (getConfiguration().isExperimentalJavaCoverage()) {
+ return null;
+ }
// If we need to instrument the jar, add additional output (the coverage metadata file) to the
// JavaCompileAction.
Artifact instrumentationMetadata = null;
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 1dbd8b73c4..304d3f2d44 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
@@ -48,6 +48,7 @@ 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.CustomCommandLine.VectorArg;
+import com.google.devtools.build.lib.analysis.actions.LazyWritePathsFileAction;
import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
@@ -511,6 +512,7 @@ public final class JavaCompileAction extends SpawnAction {
private Collection<Artifact> additionalOutputs;
private Artifact paramFile;
private Artifact metadata;
+ private Artifact artifactForExperimentalCoverage;
private ImmutableSet<Artifact> sourceFiles = ImmutableSet.of();
private final Collection<Artifact> sourceJars = new ArrayList<>();
private BuildConfiguration.StrictDepsMode strictJavaDeps =
@@ -625,6 +627,11 @@ public final class JavaCompileAction extends SpawnAction {
semantics.getJavaBuilderMainClass(),
pathSeparator);
+ if (artifactForExperimentalCoverage != null) {
+ analysisEnvironment.registerAction(new LazyWritePathsFileAction(
+ owner, artifactForExperimentalCoverage, sourceFiles, false));
+ }
+
// The actual params-file-based command line executed for a compile action.
CommandLine javaBuilderCommandLine =
CustomCommandLine.builder()
@@ -640,7 +647,7 @@ public final class JavaCompileAction extends SpawnAction {
.addAll(instrumentationJars)
.build();
- NestedSet<Artifact> inputs =
+ NestedSetBuilder<Artifact> inputsBuilder =
NestedSetBuilder.<Artifact>stableOrder()
.addTransitive(classpathEntries)
.addTransitive(compileTimeDependencyArtifacts)
@@ -652,8 +659,11 @@ public final class JavaCompileAction extends SpawnAction {
.addAll(sourcePathEntries)
.addAll(extdirInputs)
.add(paramFile)
- .addTransitive(tools)
- .build();
+ .addTransitive(tools);
+ if (artifactForExperimentalCoverage != null) {
+ inputsBuilder.add(artifactForExperimentalCoverage);
+ }
+ NestedSet<Artifact> inputs = inputsBuilder.build();
return new JavaCompileAction(
owner,
@@ -768,9 +778,13 @@ public final class JavaCompileAction extends SpawnAction {
}
}
}
- if (metadata != null) {
+
+ // Chose what artifact to pass to JavaBuilder, as input to jacoco instrumentation processor.
+ // metadata should be null when --experimental_java_coverage is true.
+ Artifact coverageArtifact = metadata != null ? metadata : artifactForExperimentalCoverage;
+ if (coverageArtifact != null) {
result.add("--post_processor");
- result.addExecPath(JACOCO_INSTRUMENTATION_PROCESSOR, metadata);
+ result.addExecPath(JACOCO_INSTRUMENTATION_PROCESSOR, coverageArtifact);
result.addPath(
configuration
.getCoverageMetadataDirectory(targetLabel.getPackageIdentifier().getRepository())
@@ -1006,6 +1020,11 @@ public final class JavaCompileAction extends SpawnAction {
return this;
}
+ public Builder setArtifactForExperimentalCoverage(Artifact artifactForExperimentalCoverage) {
+ this.artifactForExperimentalCoverage = artifactForExperimentalCoverage;
+ return this;
+ }
+
public Builder setRuleKind(String ruleKind) {
this.ruleKind = ruleKind;
return this;
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 c4af1dfd93..76e0376a8a 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
@@ -21,6 +21,7 @@ import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fro
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Streams;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.LanguageDependentFragment.LibraryLanguage;
import com.google.devtools.build.lib.analysis.OutputGroupProvider;
@@ -31,6 +32,7 @@ import com.google.devtools.build.lib.analysis.Runfiles;
import com.google.devtools.build.lib.analysis.Runfiles.Builder;
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.TemplateExpansionAction.ComputedSubstitution;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
@@ -45,8 +47,10 @@ import com.google.devtools.build.lib.rules.java.proto.GeneratedExtensionRegistry
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.vfs.PathFragment;
+import java.io.File;
import java.util.Collection;
import java.util.List;
+import java.util.stream.Collectors;
import javax.annotation.Nullable;
/**
@@ -85,6 +89,9 @@ public interface JavaSemantics {
SafeImplicitOutputsFunction JAVA_ONE_VERSION_ARTIFACT =
fromTemplates("%{name}-one-version.txt");
+ SafeImplicitOutputsFunction JAVA_COVERAGE_RUNTIME_CLASS_PATH_TXT =
+ fromTemplates("%{name}-runtime-classpath.txt");
+
SafeImplicitOutputsFunction JAVA_BINARY_DEPLOY_SOURCE_JAR =
fromTemplates("%{name}_deploy-src.jar");
@@ -212,6 +219,35 @@ public interface JavaSemantics {
String IJAR_LABEL = "//tools/defaults:ijar";
+ String JACOCO_METADATA_PLACEHOLDER = "%set_jacoco_metadata%";
+ String JACOCO_MAIN_CLASS_PLACEHOLDER = "%set_jacoco_main_class%";
+ String JACOCO_JAVA_RUNFILES_ROOT_PLACEHOLDER = "%set_jacoco_java_runfiles_root%";
+
+ /**
+ * Substitution for exporting the jars needed for jacoco coverage.
+ */
+ class ComputedJacocoSubstitution extends ComputedSubstitution {
+ private final NestedSet<Artifact> jars;
+ private final String pathPrefix;
+
+ public ComputedJacocoSubstitution(NestedSet<Artifact> jars, String workspacePrefix) {
+ super(JACOCO_METADATA_PLACEHOLDER);
+ this.jars = jars;
+ this.pathPrefix = "${JAVA_RUNFILES}/" + workspacePrefix;
+ }
+
+ /**
+ * Concatenating the root relative paths of the artifacts. Each relative path entry is prepended
+ * with "${JAVA_RUNFILES}" and the workspace prefix.
+ */
+ @Override
+ public String getValue() {
+ return Streams.stream(jars)
+ .map(artifact -> pathPrefix + "/" + artifact.getRootRelativePathString())
+ .collect(Collectors.joining(File.pathSeparator, "export JACOCO_METADATA_JARS=", ""));
+ }
+ }
+
/**
* Verifies if the rule contains any errors.
*
@@ -293,6 +329,24 @@ public interface JavaSemantics {
String javaExecutable);
/**
+ * Same as {@link #createStubAction(RuleContext, JavaCommon, List, Artifact, String, String)}.
+ *
+ * <p> In *experimental* coverage mode creates a txt file containing the runtime jars names.
+ * {@code JacocoCoverageRunner} will use it to retrieve the name of the jars considered for
+ * collecting coverage. {@code JacocoCoverageRunner} will *not* collect coverage implicitly
+ * for all the runtime jars, only for those that pack a file ending in "-paths-for-coverage.txt".
+ */
+ public Artifact createStubAction(
+ RuleContext ruleContext,
+ JavaCommon javaCommon,
+ List<String> jvmFlags,
+ Artifact executable,
+ String javaStartClass,
+ String coverageStartClass,
+ NestedSetBuilder<Artifact> filesBuilder,
+ String javaExecutable);
+
+ /**
* Returns true if {@code createStubAction} considers {@code javaExecutable} as a substitution.
* Returns false if {@code createStubAction} considers {@code javaExecutable} as a file path.
*/
@@ -345,6 +399,23 @@ public interface JavaSemantics {
throws InterruptedException;
/**
+ * Same as {@link #addCoverageSupport(JavaCompilationHelper, JavaTargetAttributes.Builder,
+ * Artifact, Artifact, JavaCompilationArtifacts.Builder, String)}.
+ *
+ * <p> In *experimental* coverage mode omits dealing with instrumentation metadata and does not
+ * create the instrumented jar.
+ */
+ String addCoverageSupport(
+ JavaCompilationHelper helper,
+ JavaTargetAttributes.Builder attributes,
+ Artifact executable,
+ Artifact instrumentationMetadata,
+ JavaCompilationArtifacts.Builder javaArtifactsBuilder,
+ String mainClass,
+ boolean isExperimentalCoverage)
+ throws InterruptedException;
+
+ /**
* Return the JVM flags to be used in a Java binary.
*/
Iterable<String> getJvmFlags(