blob: 1ad26548352972fe17ebb03c442d76a969ab9aa4 [file] [log] [blame]
// Copyright 2014 The Bazel Authors. 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.lib.rules.java;
import com.google.common.base.Ascii;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.CoreOptionConverters.StrictDepsMode;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.analysis.skylark.annotations.SkylarkConfigurationField;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.skylarkbuildapi.java.JavaConfigurationApi;
import com.google.devtools.common.options.TriState;
import java.util.Map;
import javax.annotation.Nullable;
/** A java compiler configuration containing the flags required for compilation. */
@Immutable
public final class JavaConfiguration extends Fragment implements JavaConfigurationApi {
/** Values for the --java_classpath option */
public enum JavaClasspathMode {
/** Use full transitive classpaths, the default behavior. */
OFF,
/** JavaBuilder computes the reduced classpath before invoking javac. */
JAVABUILDER,
/** Bazel computes the reduced classpath and tries it in a separate action invocation. */
BAZEL
}
/** Values for the --experimental_one_version_enforcement option */
public enum OneVersionEnforcementLevel {
/** Don't attempt to check for one version violations (the default) */
OFF,
/**
* Check for one version violations, emit warnings to stderr if any are found, but don't break
* the binary.
*/
WARNING,
/**
* Check for one version violations, emit warnings to stderr if any are found, and break the
* rule if it's found.
*/
ERROR
}
/** Values for the --experimental_import_deps_checking option */
public enum ImportDepsCheckingLevel {
/** Turn off the import_deps checking. */
OFF,
/** Emit warnings when the dependencies of java_import/aar_import are not complete. */
WARNING,
/** Emit errors when the dependencies of java_import/aar_import are not complete. */
ERROR
}
private final ImmutableList<String> commandLineJavacFlags;
private final Label javaLauncherLabel;
private final boolean useIjars;
private final boolean useHeaderCompilation;
private final boolean generateJavaDeps;
private final boolean strictDepsJavaProtos;
private final boolean isDisallowStrictDepsForJpl;
private final OneVersionEnforcementLevel enforceOneVersion;
private final boolean enforceOneVersionOnJavaTests;
private final ImportDepsCheckingLevel importDepsCheckingLevel;
private final boolean allowRuntimeDepsOnNeverLink;
private final JavaClasspathMode javaClasspath;
private final boolean inmemoryJdepsFiles;
private final ImmutableList<String> defaultJvmFlags;
private final ImmutableList<String> checkedConstraints;
private final StrictDepsMode strictJavaDeps;
private final String fixDepsTool;
private final Label proguardBinary;
private final ImmutableList<Label> extraProguardSpecs;
private final TriState bundleTranslations;
private final ImmutableList<Label> translationTargets;
private final ImmutableMap<String, Optional<Label>> bytecodeOptimizers;
private final boolean enforceProguardFileExtension;
private final Label toolchainLabel;
private final Label runtimeLabel;
private final boolean explicitJavaTestDeps;
private final boolean jplPropagateCcLinkParamsStore;
private final boolean addTestSupportToCompileTimeDeps;
private final boolean isJlplStrictDepsEnforced;
private final ImmutableList<Label> pluginList;
private final boolean requireJavaToolchainHeaderCompilerDirect;
private final boolean disallowResourceJars;
private final boolean loadJavaRulesFromBzl;
private final boolean disallowLegacyJavaToolchainFlags;
private final boolean experimentalTurbineAnnotationProcessing;
// TODO(dmarting): remove once we have a proper solution for #2539
private final boolean useLegacyBazelJavaTest;
JavaConfiguration(JavaOptions javaOptions) throws InvalidConfigurationException {
this.commandLineJavacFlags =
ImmutableList.copyOf(JavaHelper.tokenizeJavaOptions(javaOptions.javacOpts));
this.javaLauncherLabel = javaOptions.javaLauncher;
this.useIjars = javaOptions.useIjars;
this.useHeaderCompilation = javaOptions.headerCompilation;
this.generateJavaDeps =
javaOptions.javaDeps || javaOptions.javaClasspath != JavaClasspathMode.OFF;
this.javaClasspath = javaOptions.javaClasspath;
this.inmemoryJdepsFiles = javaOptions.inmemoryJdepsFiles;
this.defaultJvmFlags = ImmutableList.copyOf(javaOptions.jvmOpts);
this.checkedConstraints = ImmutableList.copyOf(javaOptions.checkedConstraints);
this.strictJavaDeps = javaOptions.strictJavaDeps;
this.fixDepsTool = javaOptions.fixDepsTool;
this.proguardBinary = javaOptions.proguard;
this.extraProguardSpecs = ImmutableList.copyOf(javaOptions.extraProguardSpecs);
this.enforceProguardFileExtension = javaOptions.enforceProguardFileExtension;
this.bundleTranslations = javaOptions.bundleTranslations;
this.toolchainLabel = javaOptions.javaToolchain;
this.runtimeLabel = javaOptions.javaBase;
this.useLegacyBazelJavaTest = javaOptions.legacyBazelJavaTest;
this.strictDepsJavaProtos = javaOptions.strictDepsJavaProtos;
this.isDisallowStrictDepsForJpl = javaOptions.isDisallowStrictDepsForJpl;
this.enforceOneVersion = javaOptions.enforceOneVersion;
this.enforceOneVersionOnJavaTests = javaOptions.enforceOneVersionOnJavaTests;
this.importDepsCheckingLevel = javaOptions.importDepsCheckingLevel;
this.allowRuntimeDepsOnNeverLink = javaOptions.allowRuntimeDepsOnNeverLink;
this.explicitJavaTestDeps = javaOptions.explicitJavaTestDeps;
this.jplPropagateCcLinkParamsStore = javaOptions.jplPropagateCcLinkParamsStore;
this.isJlplStrictDepsEnforced = javaOptions.isJlplStrictDepsEnforced;
this.disallowResourceJars = javaOptions.disallowResourceJars;
this.loadJavaRulesFromBzl = javaOptions.loadJavaRulesFromBzl;
this.addTestSupportToCompileTimeDeps = javaOptions.addTestSupportToCompileTimeDeps;
ImmutableList.Builder<Label> translationsBuilder = ImmutableList.builder();
for (String s : javaOptions.translationTargets) {
try {
Label label = Label.parseAbsolute(s, ImmutableMap.of());
translationsBuilder.add(label);
} catch (LabelSyntaxException e) {
throw new InvalidConfigurationException(
"Invalid translations target '"
+ s
+ "', make "
+ "sure it uses correct absolute path syntax.",
e);
}
}
this.translationTargets = translationsBuilder.build();
ImmutableMap.Builder<String, Optional<Label>> optimizersBuilder = ImmutableMap.builder();
for (Map.Entry<String, Label> optimizer : javaOptions.bytecodeOptimizers.entrySet()) {
String mnemonic = optimizer.getKey();
if (optimizer.getValue() == null && !"Proguard".equals(mnemonic)) {
throw new InvalidConfigurationException("Must supply label for optimizer " + mnemonic);
}
optimizersBuilder.put(mnemonic, Optional.fromNullable(optimizer.getValue()));
}
this.bytecodeOptimizers = optimizersBuilder.build();
this.pluginList = ImmutableList.copyOf(javaOptions.pluginList);
this.requireJavaToolchainHeaderCompilerDirect =
javaOptions.requireJavaToolchainHeaderCompilerDirect;
this.disallowLegacyJavaToolchainFlags = javaOptions.disallowLegacyJavaToolchainFlags;
this.experimentalTurbineAnnotationProcessing =
javaOptions.experimentalTurbineAnnotationProcessing;
if (javaOptions.disallowLegacyJavaToolchainFlags) {
if (!javaOptions.javaBase.equals(javaOptions.defaultJavaBase())) {
throw new InvalidConfigurationException(
String.format(
"--javabase=%s is no longer supported, use --platforms instead (see #7849)",
javaOptions.javaBase));
}
if (!javaOptions.getHostJavaBase().equals(javaOptions.defaultHostJavaBase())) {
throw new InvalidConfigurationException(
String.format(
"--host_javabase=%s is no longer supported, use --platforms instead (see #7849)",
javaOptions.getHostJavaBase()));
}
if (!javaOptions.javaToolchain.equals(javaOptions.defaultJavaToolchain())) {
throw new InvalidConfigurationException(
String.format(
"--java_toolchain=%s is no longer supported, use --platforms instead (see #7849)",
javaOptions.javaToolchain));
}
if (!javaOptions.hostJavaToolchain.equals(javaOptions.defaultJavaToolchain())) {
throw new InvalidConfigurationException(
String.format(
"--host_java_toolchain=%s is no longer supported, use --platforms instead (see"
+ " #7849)",
javaOptions.hostJavaToolchain));
}
}
}
@Override
// TODO(bazel-team): this is the command-line passed options, we should remove from skylark
// probably.
public ImmutableList<String> getDefaultJavacFlags() {
return commandLineJavacFlags;
}
@Override
public String getStrictJavaDepsName() {
return Ascii.toLowerCase(strictJavaDeps.name());
}
@Override
public void reportInvalidOptions(EventHandler reporter, BuildOptions buildOptions) {
if ((bundleTranslations == TriState.YES) && translationTargets.isEmpty()) {
reporter.handle(
Event.error(
"Translations enabled, but no message translations specified. "
+ "Use '--message_translations' to select the message translations to use"));
}
}
/** Returns true iff Java compilation should use ijars. */
public boolean getUseIjars() {
return useIjars;
}
/** Returns true iff Java header compilation is enabled. */
public boolean useHeaderCompilation() {
return useHeaderCompilation;
}
/** Returns true iff dependency information is generated after compilation. */
public boolean getGenerateJavaDeps() {
return generateJavaDeps;
}
public JavaClasspathMode getReduceJavaClasspath() {
return javaClasspath;
}
public boolean inmemoryJdepsFiles() {
return inmemoryJdepsFiles;
}
public ImmutableList<String> getDefaultJvmFlags() {
return defaultJvmFlags;
}
public ImmutableList<String> getCheckedConstraints() {
return checkedConstraints;
}
public StrictDepsMode getStrictJavaDeps() {
return strictJavaDeps;
}
public StrictDepsMode getFilteredStrictJavaDeps() {
StrictDepsMode strict = getStrictJavaDeps();
switch (strict) {
case STRICT:
case DEFAULT:
return StrictDepsMode.ERROR;
default: // OFF, WARN, ERROR
return strict;
}
}
/** Which tool to use for fixing dependency errors. */
public String getFixDepsTool() {
return fixDepsTool;
}
/** @return proper label only if --java_launcher= is specified, otherwise null. */
public Label getJavaLauncherLabel() {
return javaLauncherLabel;
}
/** Returns the label provided with --proguard_top, if any. */
@SkylarkConfigurationField(
name = "proguard_top",
doc = "Returns the label provided with --proguard_top, if any.",
defaultInToolRepository = true)
@Nullable
public Label getProguardBinary() {
return proguardBinary;
}
/** Returns all labels provided with --extra_proguard_specs. */
public ImmutableList<Label> getExtraProguardSpecs() {
return extraProguardSpecs;
}
/** Returns whether ProGuard configuration files are required to use a *.pgcfg extension. */
public boolean enforceProguardFileExtension() {
return enforceProguardFileExtension;
}
/** Returns the raw translation targets. */
public ImmutableList<Label> getTranslationTargets() {
return translationTargets;
}
/** Returns true if the we should build translations. */
public boolean buildTranslations() {
return (bundleTranslations != TriState.NO) && !translationTargets.isEmpty();
}
/** Returns whether translations were explicitly disabled. */
public boolean isTranslationsDisabled() {
return bundleTranslations == TriState.NO;
}
/** Returns the label of the default java_toolchain rule */
@SkylarkConfigurationField(
name = "java_toolchain",
doc = "Returns the label of the default java_toolchain rule.",
defaultLabel = "//tools/jdk:toolchain",
defaultInToolRepository = true)
public Label getToolchainLabel() {
if (disallowLegacyJavaToolchainFlags) {
throw new IllegalStateException("--java_toolchain is no longer supported");
}
return toolchainLabel;
}
/** Returns the label of the {@code java_runtime} rule representing the JVM in use. */
public Label getRuntimeLabel() {
return runtimeLabel;
}
/** Returns ordered list of optimizers to run. */
public ImmutableMap<String, Optional<Label>> getBytecodeOptimizers() {
return bytecodeOptimizers;
}
/**
* Returns true if java_test in Bazel should behave in legacy mode that existed before we
* open-sourced our test runner.
*/
public boolean useLegacyBazelJavaTest() {
return useLegacyBazelJavaTest;
}
/**
* Make it mandatory for java_test targets to explicitly declare any JUnit or Hamcrest
* dependencies instead of accidentally obtaining them from the TestRunner's dependencies.
*/
public boolean explicitJavaTestDeps() {
return explicitJavaTestDeps;
}
/**
* Returns an enum representing whether or not Bazel should attempt to enforce one-version
* correctness on java_binary rules using the 'oneversion' tool in the java_toolchain.
*
* <p>One-version correctness will inspect for multiple non-identical versions of java classes in
* the transitive dependencies for a java_binary.
*/
public OneVersionEnforcementLevel oneVersionEnforcementLevel() {
return enforceOneVersion;
}
public boolean enforceOneVersionOnJavaTests() {
return enforceOneVersionOnJavaTests;
}
public ImportDepsCheckingLevel getImportDepsCheckingLevel() {
return importDepsCheckingLevel;
}
public boolean getAllowRuntimeDepsOnNeverLink() {
return allowRuntimeDepsOnNeverLink;
}
public boolean strictDepsJavaProtos() {
return strictDepsJavaProtos;
}
public boolean isDisallowStrictDepsForJpl() {
return isDisallowStrictDepsForJpl;
}
public boolean jplPropagateCcLinkParamsStore() {
return jplPropagateCcLinkParamsStore;
}
public boolean addTestSupportToCompileTimeDeps() {
return addTestSupportToCompileTimeDeps;
}
public boolean isJlplStrictDepsEnforced() {
return isJlplStrictDepsEnforced;
}
@Override
public ImmutableList<Label> getPlugins() {
return pluginList;
}
public boolean requireJavaToolchainHeaderCompilerDirect() {
return requireJavaToolchainHeaderCompilerDirect;
}
public boolean disallowResourceJars() {
return disallowResourceJars;
}
public boolean loadJavaRulesFromBzl() {
return loadJavaRulesFromBzl;
}
public boolean experimentalTurbineAnnotationProcessing() {
return experimentalTurbineAnnotationProcessing;
}
}