Internal change
PiperOrigin-RevId: 372613466
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 12d4e85..c975fbc 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
@@ -41,6 +41,7 @@
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.rules.java.JavaConfiguration.JavaClasspathMode;
import com.google.devtools.build.lib.rules.java.JavaPluginInfo.JavaPluginData;
+import com.google.devtools.build.lib.rules.java.JavaToolchainProvider.JspecifyInfo;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
@@ -200,6 +201,21 @@
}
JavaTargetAttributes attributes = getAttributes();
+
+ JspecifyInfo jspecifyInfo = javaToolchain.jspecifyInfo();
+ boolean jspecify =
+ getJavaConfiguration().experimentalEnableJspecify()
+ && jspecifyInfo != null
+ && jspecifyInfo.matches(ruleContext.getLabel());
+ if (jspecify) {
+ // JSpecify requires these on the compile-time classpath; see b/187113128
+ // Add them as non-direct deps (for the purposes of Strict Java Deps) to still require an
+ // explicit dep if they're directly used by the compiled source.
+ attributes =
+ attributes.appendAdditionalTransitiveClassPathEntries(
+ jspecifyInfo.jspecifyImplicitDeps());
+ }
+
ImmutableList<Artifact> sourceJars = attributes.getSourceJars();
JavaPluginData plugins = attributes.plugins().plugins();
List<Artifact> resourceJars = new ArrayList<>();
@@ -250,6 +266,19 @@
createResourceJarAction(originalOutput, ImmutableList.copyOf(resourceJars));
}
+ ImmutableList<String> javacopts = customJavacOpts;
+ if (jspecify) {
+ plugins =
+ JavaPluginInfo.JavaPluginData.merge(
+ ImmutableList.of(plugins, jspecifyInfo.jspecifyProcessor()));
+ javacopts =
+ ImmutableList.<String>builder()
+ .addAll(javacopts)
+ // Add JSpecify options last to discourage overridding them, at least for now.
+ .addAll(jspecifyInfo.jspecifyJavacopts())
+ .build();
+ }
+
JavaCompileActionBuilder builder = new JavaCompileActionBuilder(ruleContext, javaToolchain);
JavaClasspathMode classpathMode = getJavaConfiguration().getReduceJavaClasspath();
@@ -298,7 +327,7 @@
ImmutableSet<Artifact> sourceFiles = attributes.getSourceFiles();
builder.setSourceFiles(sourceFiles);
builder.setSourceJars(sourceJars);
- builder.setJavacOpts(customJavacOpts);
+ builder.setJavacOpts(javacopts);
builder.setJavacExecutionInfo(getExecutionInfo());
builder.setCompressJar(true);
builder.setBuiltinProcessorNames(javaToolchain.getHeaderCompilerBuiltinProcessors());
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
index 618f33d..a8cce20 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
@@ -105,6 +105,7 @@
private final boolean disallowResourceJars;
private final boolean disallowLegacyJavaToolchainFlags;
private final boolean experimentalTurbineAnnotationProcessing;
+ private final boolean experimentalEnableJspecify;
// TODO(dmarting): remove once we have a proper solution for #2539
private final boolean useLegacyBazelJavaTest;
@@ -163,6 +164,7 @@
this.disallowLegacyJavaToolchainFlags = javaOptions.disallowLegacyJavaToolchainFlags;
this.experimentalTurbineAnnotationProcessing =
javaOptions.experimentalTurbineAnnotationProcessing;
+ this.experimentalEnableJspecify = javaOptions.experimentalEnableJspecify;
if (javaOptions.disallowLegacyJavaToolchainFlags) {
checkLegacyToolchainFlagIsUnset(
@@ -387,4 +389,8 @@
public boolean experimentalTurbineAnnotationProcessing() {
return experimentalTurbineAnnotationProcessing;
}
+
+ public boolean experimentalEnableJspecify() {
+ return experimentalEnableJspecify;
+ }
}
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 ce38280..c891d02 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
@@ -651,6 +651,14 @@
help = "Deprecated no-op.")
public boolean experimentalPublishJavaCcLinkParamsInfo;
+ @Option(
+ name = "experimental_enable_jspecify",
+ defaultValue = "true",
+ documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
+ effectTags = {OptionEffectTag.UNKNOWN},
+ help = "Enable experimental jspecify integration.")
+ public boolean experimentalEnableJspecify;
+
Label defaultJavaBase() {
return Label.parseAbsoluteUnchecked(DEFAULT_JAVABASE);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java
index c5d3ea9..b95bc07 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaTargetAttributes.java
@@ -473,6 +473,34 @@
strictJavaDeps);
}
+ JavaTargetAttributes appendAdditionalTransitiveClassPathEntries(
+ NestedSet<Artifact> additionalClassPathEntries) {
+ NestedSet<Artifact> compileTimeClassPath =
+ NestedSetBuilder.fromNestedSet(this.compileTimeClassPath)
+ .addTransitive(additionalClassPathEntries)
+ .build();
+ return new JavaTargetAttributes(
+ sourceFiles,
+ runtimeClassPath,
+ compileTimeClassPath,
+ bootClassPath,
+ sourcePath,
+ nativeLibraries,
+ plugins,
+ resources,
+ resourceJars,
+ messages,
+ sourceJars,
+ classPathResources,
+ additionalOutputs,
+ directJars,
+ compileTimeDependencyArtifacts,
+ targetLabel,
+ injectingRuleKind,
+ excludedArtifacts,
+ strictJavaDeps);
+ }
+
public NestedSet<Artifact> getDirectJars() {
return directJars;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchain.java
index 63bc552..cedc95f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchain.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchain.java
@@ -15,6 +15,8 @@
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.devtools.build.lib.collect.nestedset.Order.STABLE_ORDER;
+import static com.google.devtools.build.lib.packages.Type.STRING;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
@@ -25,6 +27,7 @@
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
+import com.google.devtools.build.lib.analysis.PackageSpecificationProvider;
import com.google.devtools.build.lib.analysis.PrerequisiteArtifacts;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory;
@@ -36,6 +39,8 @@
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.Type;
+import com.google.devtools.build.lib.rules.java.JavaPluginInfo.JavaPluginData;
+import com.google.devtools.build.lib.rules.java.JavaToolchainProvider.JspecifyInfo;
import java.util.List;
import java.util.Map;
@@ -94,6 +99,33 @@
JavaToolchainTool.fromFilesToRunProvider(
ruleContext.getExecutablePrerequisite("header_compiler_direct"));
+ JspecifyInfo jspecifyInfo;
+ String jspecifyProcessorClass =
+ ruleContext.attributes().get("jspecify_processor_class", STRING);
+ if (jspecifyProcessorClass.isEmpty()) {
+ jspecifyInfo = null;
+ } else {
+ JavaPluginData jspecifyProcessor =
+ JavaPluginData.create(
+ NestedSetBuilder.create(STABLE_ORDER, jspecifyProcessorClass),
+ NestedSetBuilder.create(
+ STABLE_ORDER, ruleContext.getPrerequisiteArtifact("jspecify_processor")),
+ PrerequisiteArtifacts.nestedSet(ruleContext, "jspecify_stubs"));
+ NestedSet<Artifact> jspecifyImplicitDeps =
+ NestedSetBuilder.create(
+ STABLE_ORDER, ruleContext.getPrerequisiteArtifact("jspecify_implicit_deps"));
+ ImmutableList<String> jspecifyJavacopts =
+ ImmutableList.copyOf(
+ ruleContext.attributes().get("jspecify_javacopts", Type.STRING_LIST));
+ ImmutableList<PackageSpecificationProvider> jspecifyPackages =
+ ImmutableList.copyOf(
+ ruleContext.getPrerequisites(
+ "jspecify_packages", PackageSpecificationProvider.class));
+ jspecifyInfo =
+ JspecifyInfo.create(
+ jspecifyProcessor, jspecifyImplicitDeps, jspecifyJavacopts, jspecifyPackages);
+ }
+
AndroidLintTool androidLint = AndroidLintTool.fromRuleContext(ruleContext);
ImmutableList<JavaPackageConfigurationProvider> packageConfiguration =
@@ -119,6 +151,7 @@
headerCompiler,
headerCompilerDirect,
androidLint,
+ jspecifyInfo,
headerCompilerBuiltinProcessors,
reducedClasspathIncompatibleProcessors,
forciblyDisableHeaderCompilation,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainProvider.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainProvider.java
index 06c4cd6..1e48be8 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainProvider.java
@@ -15,11 +15,13 @@
import static com.google.common.base.StandardSystemProperty.JAVA_SPECIFICATION_VERSION;
+import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
+import com.google.devtools.build.lib.analysis.PackageSpecificationProvider;
import com.google.devtools.build.lib.analysis.ProviderCollection;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.RuleErrorConsumer;
@@ -31,7 +33,9 @@
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.BuiltinProvider;
import com.google.devtools.build.lib.packages.NativeInfo;
+import com.google.devtools.build.lib.packages.PackageSpecification.PackageGroupContents;
import com.google.devtools.build.lib.packages.Provider;
+import com.google.devtools.build.lib.rules.java.JavaPluginInfo.JavaPluginData;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.lib.starlarkbuildapi.java.JavaToolchainStarlarkApiProviderApi;
@@ -96,6 +100,7 @@
@Nullable JavaToolchainTool headerCompiler,
@Nullable JavaToolchainTool headerCompilerDirect,
@Nullable AndroidLintTool androidLint,
+ JspecifyInfo jspecifyInfo,
ImmutableSet<String> headerCompilerBuiltinProcessors,
ImmutableSet<String> reducedClasspathIncompatibleProcessors,
boolean forciblyDisableHeaderCompilation,
@@ -120,6 +125,7 @@
headerCompiler,
headerCompilerDirect,
androidLint,
+ jspecifyInfo,
headerCompilerBuiltinProcessors,
reducedClasspathIncompatibleProcessors,
forciblyDisableHeaderCompilation,
@@ -149,6 +155,7 @@
@Nullable private final JavaToolchainTool headerCompiler;
@Nullable private final JavaToolchainTool headerCompilerDirect;
@Nullable private final AndroidLintTool androidLint;
+ @Nullable private final JspecifyInfo jspecifyInfo;
private final ImmutableSet<String> headerCompilerBuiltinProcessors;
private final ImmutableSet<String> reducedClasspathIncompatibleProcessors;
private final boolean forciblyDisableHeaderCompilation;
@@ -179,6 +186,7 @@
@Nullable JavaToolchainTool headerCompiler,
@Nullable JavaToolchainTool headerCompilerDirect,
@Nullable AndroidLintTool androidLint,
+ @Nullable JspecifyInfo jspecifyInfo,
ImmutableSet<String> headerCompilerBuiltinProcessors,
ImmutableSet<String> reducedClasspathIncompatibleProcessors,
boolean forciblyDisableHeaderCompilation,
@@ -207,6 +215,7 @@
this.headerCompiler = headerCompiler;
this.headerCompilerDirect = headerCompilerDirect;
this.androidLint = androidLint;
+ this.jspecifyInfo = jspecifyInfo;
this.headerCompilerBuiltinProcessors = headerCompilerBuiltinProcessors;
this.reducedClasspathIncompatibleProcessors = reducedClasspathIncompatibleProcessors;
this.forciblyDisableHeaderCompilation = forciblyDisableHeaderCompilation;
@@ -269,6 +278,11 @@
return androidLint;
}
+ @Nullable
+ public JspecifyInfo jspecifyInfo() {
+ return jspecifyInfo;
+ }
+
/** Returns class names of annotation processors that are built in to the header compiler. */
public ImmutableSet<String> getHeaderCompilerBuiltinProcessors() {
return headerCompilerBuiltinProcessors;
@@ -441,4 +455,36 @@
public Provider getProvider() {
return PROVIDER;
}
+
+ @AutoValue
+ abstract static class JspecifyInfo {
+
+ abstract JavaPluginData jspecifyProcessor();
+
+ abstract NestedSet<Artifact> jspecifyImplicitDeps();
+
+ abstract ImmutableList<String> jspecifyJavacopts();
+
+ abstract ImmutableList<PackageSpecificationProvider> jspecifyPackages();
+
+ boolean matches(Label label) {
+ for (PackageSpecificationProvider provider : jspecifyPackages()) {
+ for (PackageGroupContents specifications : provider.getPackageSpecifications().toList()) {
+ if (specifications.containsPackage(label.getPackageIdentifier())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ static JspecifyInfo create(
+ JavaPluginData jspecifyProcessor,
+ NestedSet<Artifact> jspecifyImplicitDeps,
+ ImmutableList<String> jspecifyJavacopts,
+ ImmutableList<PackageSpecificationProvider> jspecifyPackages) {
+ return new AutoValue_JavaToolchainProvider_JspecifyInfo(
+ jspecifyProcessor, jspecifyImplicitDeps, jspecifyJavacopts, jspecifyPackages);
+ }
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainRule.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainRule.java
index a471252..8ce70a3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainRule.java
@@ -25,6 +25,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
+import com.google.devtools.build.lib.analysis.PackageSpecificationProvider;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.analysis.config.ExecutionTransitionFactory;
@@ -327,6 +328,34 @@
.cfg(ExecutionTransitionFactory.create())
.mandatoryBuiltinProviders(
ImmutableList.of(JavaPackageConfigurationProvider.class)))
+ .add(attr("jspecify_processor_class", STRING).value("").undocumented("experimental"))
+ .add(
+ attr("jspecify_processor", LABEL)
+ .cfg(ExecutionTransitionFactory.create())
+ .allowedFileTypes(FileTypeSet.ANY_FILE)
+ .exec()
+ .undocumented("experimental"))
+ .add(
+ attr("jspecify_implicit_deps", LABEL)
+ .cfg(ExecutionTransitionFactory.create())
+ .allowedFileTypes(FileTypeSet.ANY_FILE)
+ .exec()
+ .undocumented("experimental"))
+ .add(
+ attr("jspecify_javacopts", STRING_LIST)
+ .value(ImmutableList.<String>of())
+ .undocumented("experimental"))
+ .add(
+ attr("jspecify_stubs", LABEL_LIST)
+ .cfg(ExecutionTransitionFactory.create())
+ .allowedFileTypes(FileTypeSet.ANY_FILE)
+ .undocumented("experimental"))
+ .add(
+ attr("jspecify_packages", LABEL_LIST)
+ .cfg(ExecutionTransitionFactory.create())
+ .allowedFileTypes()
+ .mandatoryBuiltinProviders(ImmutableList.of(PackageSpecificationProvider.class))
+ .undocumented("experimental"))
.build();
}