Move most license checking logic into a module to make it easier to eventually remove.
There's basically four groups of license-related logic in Bazel:
1) Syntactic support in BUILD files
2) Semantics that checks third_party rules have licenses() declared
3) LicenseProvider, which collects rules' transitive license declarations
4) Semantics that checks if a build's licenses are valid
This change only covers 4).
This also simplifies AnalysisPhaseRunner and License.
Part of #7444.
PiperOrigin-RevId: 235585865
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index a05ecf9..6a92c8b 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -808,6 +808,22 @@
)
java_library(
+ name = "bazel/LicenseCheckingModule",
+ srcs = ["bazel/LicenseCheckingModule.java"],
+ deps = [
+ ":build-base",
+ ":events",
+ ":packages-internal",
+ ":runtime",
+ "//src/main/java/com/google/devtools/build/lib/cmdline",
+ "//src/main/java/com/google/devtools/build/lib/collect",
+ "//src/main/java/com/google/devtools/build/lib/collect/nestedset",
+ "//src/main/java/com/google/devtools/build/lib/profiler",
+ "//third_party:guava",
+ ],
+)
+
+java_library(
name = "bazel-main",
srcs = ["bazel/Bazel.java"],
resources = [
@@ -845,8 +861,10 @@
exclude = [
"bazel/Bazel.java",
"bazel/BazelRepositoryModule.java",
+ "bazel/LicenseCheckingModule.java",
],
),
+ exports = [":bazel/LicenseCheckingModule"],
deps = [
":build-base",
":build-info",
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/Bazel.java b/src/main/java/com/google/devtools/build/lib/bazel/Bazel.java
index f2829af..4ece65e 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/Bazel.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/Bazel.java
@@ -43,6 +43,7 @@
com.google.devtools.build.lib.bazel.BazelWorkspaceStatusModule.class,
com.google.devtools.build.lib.bazel.BazelDiffAwarenessModule.class,
com.google.devtools.build.lib.bazel.BazelRepositoryModule.class,
+ com.google.devtools.build.lib.bazel.LicenseCheckingModule.class,
com.google.devtools.build.lib.bazel.debug.WorkspaceRuleModule.class,
com.google.devtools.build.lib.bazel.coverage.BazelCoverageReportModule.class,
com.google.devtools.build.lib.skylarkdebug.module.SkylarkDebuggerModule.class,
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/LicenseCheckingModule.java b/src/main/java/com/google/devtools/build/lib/bazel/LicenseCheckingModule.java
new file mode 100644
index 0000000..869b9a0
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/LicenseCheckingModule.java
@@ -0,0 +1,256 @@
+// Copyright 2019 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.bazel;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.ImmutableTable;
+import com.google.common.collect.Table;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.LicensesProvider;
+import com.google.devtools.build.lib.analysis.LicensesProvider.TargetLicense;
+import com.google.devtools.build.lib.analysis.StaticallyLinkedMarkerProvider;
+import com.google.devtools.build.lib.analysis.ViewCreationFailedException;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.config.BuildOptions;
+import com.google.devtools.build.lib.buildtool.BuildRequest;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.events.Event;
+import com.google.devtools.build.lib.events.EventHandler;
+import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.InputFile;
+import com.google.devtools.build.lib.packages.License;
+import com.google.devtools.build.lib.packages.License.DistributionType;
+import com.google.devtools.build.lib.packages.License.LicenseType;
+import com.google.devtools.build.lib.packages.NoSuchPackageException;
+import com.google.devtools.build.lib.packages.NoSuchTargetException;
+import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.packages.TargetUtils;
+import com.google.devtools.build.lib.profiler.ProfilePhase;
+import com.google.devtools.build.lib.profiler.Profiler;
+import com.google.devtools.build.lib.profiler.SilentCloseable;
+import com.google.devtools.build.lib.runtime.BlazeModule;
+import com.google.devtools.build.lib.runtime.CommandEnvironment;
+import java.util.EnumSet;
+import java.util.Set;
+
+/**
+ * Module responsible for checking third party license compliance.
+ *
+ * <p><b>This is outdated logic marked for removal.</b> See <a
+ * href="https://github.com/bazelbuild/bazel/issues/7444">#7444</a> for details.
+ */
+public class LicenseCheckingModule extends BlazeModule {
+
+ private boolean shouldCheckLicenses(BuildOptions buildOptions) {
+ return buildOptions.get(BuildConfiguration.Options.class).checkLicenses;
+ }
+
+ @Override
+ public void afterAnalysis(
+ CommandEnvironment env,
+ BuildRequest request,
+ BuildOptions buildOptions,
+ Iterable<ConfiguredTarget> configuredTargets)
+ throws InterruptedException, ViewCreationFailedException {
+ // Check licenses.
+ // We check licenses if the first target configuration has license checking enabled. Right
+ // now, it is not possible to have multiple target configurations with different settings
+ // for this flag, which allows us to take this short cut.
+ if (shouldCheckLicenses(buildOptions)) {
+ Profiler.instance().markPhase(ProfilePhase.LICENSE);
+ try (SilentCloseable c = Profiler.instance().profile("validateLicensingForTargets")) {
+ validateLicensingForTargets(env, configuredTargets, request.getKeepGoing());
+ }
+ }
+ }
+
+ /**
+ * Takes a set of configured targets, and checks if the distribution methods declared for the
+ * targets are compatible with the constraints imposed by their prerequisites' licenses.
+ *
+ * @param configuredTargets the targets to check
+ * @param keepGoing if false, and a licensing error is encountered, both generates an error
+ * message on the reporter, <em>and</em> throws an exception. If true, then just generates a
+ * message on the reporter.
+ * @throws ViewCreationFailedException if the license checking failed (and not --keep_going)
+ */
+ private static void validateLicensingForTargets(
+ CommandEnvironment env, Iterable<ConfiguredTarget> configuredTargets, boolean keepGoing)
+ throws ViewCreationFailedException {
+ for (ConfiguredTarget configuredTarget : configuredTargets) {
+ Target target = null;
+ try {
+ target = env.getPackageManager().getTarget(env.getReporter(), configuredTarget.getLabel());
+ } catch (NoSuchPackageException | NoSuchTargetException | InterruptedException e) {
+ env.getReporter().handle(Event.error("Failed to get target to validate license"));
+ throw new ViewCreationFailedException(
+ "Build aborted due to issue getting targets to validate licenses", e);
+ }
+
+ if (TargetUtils.isTestRule(target)) {
+ continue; // Tests are exempt from license checking
+ }
+
+ final Set<DistributionType> distribs = target.getDistributions();
+ StaticallyLinkedMarkerProvider markerProvider =
+ configuredTarget.getProvider(StaticallyLinkedMarkerProvider.class);
+ boolean staticallyLinked = markerProvider != null && markerProvider.isLinkedStatically();
+
+ LicensesProvider provider = configuredTarget.getProvider(LicensesProvider.class);
+ if (provider != null) {
+ NestedSet<TargetLicense> licenses = provider.getTransitiveLicenses();
+ for (TargetLicense targetLicense : licenses) {
+ if (!checkCompatibility(
+ targetLicense.getLicense(),
+ distribs,
+ target,
+ targetLicense.getLabel(),
+ env.getReporter(),
+ staticallyLinked)) {
+ if (!keepGoing) {
+ throw new ViewCreationFailedException("Build aborted due to licensing error");
+ }
+ }
+ }
+ } else if (target instanceof InputFile) {
+ // Input file targets do not provide licenses because they do not
+ // depend on the rule where their license is taken from. This is usually
+ // not a problem, because the transitive collection of licenses always
+ // hits the rule they come from, except when the input file is a
+ // top-level target. Thus, we need to handle that case specially here.
+ //
+ // See FileTarget#getLicense for more information about the handling of
+ // license issues with File targets.
+ License license = target.getLicense();
+ if (!checkCompatibility(
+ license,
+ distribs,
+ target,
+ configuredTarget.getLabel(),
+ env.getReporter(),
+ staticallyLinked)) {
+ if (!keepGoing) {
+ throw new ViewCreationFailedException("Build aborted due to licensing error");
+ }
+ }
+ }
+ }
+ }
+
+ private static final Object MARKER = new Object();
+
+ /**
+ * The license incompatibility set. This contains the set of (Distribution,License) pairs that
+ * should generate errors.
+ */
+ private static final Table<DistributionType, LicenseType, Object> licenseIncompatibilies =
+ createLicenseIncompatibilitySet();
+
+ private static Table<DistributionType, LicenseType, Object> createLicenseIncompatibilitySet() {
+ Table<DistributionType, LicenseType, Object> result = HashBasedTable.create();
+ result.put(DistributionType.CLIENT, LicenseType.RESTRICTED, MARKER);
+ result.put(DistributionType.EMBEDDED, LicenseType.RESTRICTED, MARKER);
+ result.put(DistributionType.INTERNAL, LicenseType.BY_EXCEPTION_ONLY, MARKER);
+ result.put(DistributionType.CLIENT, LicenseType.BY_EXCEPTION_ONLY, MARKER);
+ result.put(DistributionType.WEB, LicenseType.BY_EXCEPTION_ONLY, MARKER);
+ result.put(DistributionType.EMBEDDED, LicenseType.BY_EXCEPTION_ONLY, MARKER);
+ return ImmutableTable.copyOf(result);
+ }
+
+ /**
+ * The license warning set. This contains the set of (Distribution,License) pairs that should
+ * generate warnings when the user requests verbose license checking.
+ */
+ private static final Table<DistributionType, LicenseType, Object> licenseWarnings =
+ createLicenseWarningsSet();
+
+ private static Table<DistributionType, LicenseType, Object> createLicenseWarningsSet() {
+ Table<DistributionType, LicenseType, Object> result = HashBasedTable.create();
+ result.put(DistributionType.CLIENT, LicenseType.RECIPROCAL, MARKER);
+ result.put(DistributionType.EMBEDDED, LicenseType.RECIPROCAL, MARKER);
+ result.put(DistributionType.CLIENT, LicenseType.NOTICE, MARKER);
+ result.put(DistributionType.EMBEDDED, LicenseType.NOTICE, MARKER);
+ return ImmutableTable.copyOf(result);
+ }
+
+ /**
+ * Checks if the given license is compatible with distributing a particular target in some set of
+ * distribution modes.
+ *
+ * @param license the license to check
+ * @param dists the modes of distribution
+ * @param target the target which is being checked, and which will be used for checking exceptions
+ * @param licensedTarget the target which declared the license being checked.
+ * @param eventHandler a reporter where any licensing issues discovered should be reported
+ * @param staticallyLinked whether the target is statically linked under this command
+ * @return true if the license is compatible with the distributions
+ */
+ @VisibleForTesting
+ public static boolean checkCompatibility(
+ License license,
+ Set<DistributionType> dists,
+ Target target,
+ Label licensedTarget,
+ EventHandler eventHandler,
+ boolean staticallyLinked) {
+ Location location = (target instanceof Rule) ? ((Rule) target).getLocation() : null;
+
+ LicenseType leastRestrictiveLicense;
+ if (license.getLicenseTypes().contains(LicenseType.RESTRICTED_IF_STATICALLY_LINKED)) {
+ Set<LicenseType> tempLicenses = EnumSet.copyOf(license.getLicenseTypes());
+ tempLicenses.remove(LicenseType.RESTRICTED_IF_STATICALLY_LINKED);
+ if (staticallyLinked) {
+ tempLicenses.add(LicenseType.RESTRICTED);
+ } else {
+ tempLicenses.add(LicenseType.UNENCUMBERED);
+ }
+ leastRestrictiveLicense = License.leastRestrictive(tempLicenses);
+ } else {
+ leastRestrictiveLicense = License.leastRestrictive(license.getLicenseTypes());
+ }
+ for (DistributionType dt : dists) {
+ if (licenseIncompatibilies.contains(dt, leastRestrictiveLicense)) {
+ if (!license.getExceptions().contains(target.getLabel())) {
+ eventHandler.handle(
+ Event.error(
+ location,
+ "Build target '"
+ + target.getLabel()
+ + "' is not compatible with license '"
+ + license
+ + "' from target '"
+ + licensedTarget
+ + "'"));
+ return false;
+ }
+ } else if (licenseWarnings.contains(dt, leastRestrictiveLicense)) {
+ eventHandler.handle(
+ Event.warn(
+ location,
+ "Build target '"
+ + target
+ + "' has a potential licensing issue with a '"
+ + license
+ + "' license from target '"
+ + licensedTarget
+ + "'"));
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/AnalysisPhaseRunner.java b/src/main/java/com/google/devtools/build/lib/buildtool/AnalysisPhaseRunner.java
index 8cc38c0..6af3eb8 100644
--- a/src/main/java/com/google/devtools/build/lib/buildtool/AnalysisPhaseRunner.java
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/AnalysisPhaseRunner.java
@@ -21,9 +21,6 @@
import com.google.devtools.build.lib.analysis.AnalysisResult;
import com.google.devtools.build.lib.analysis.BuildView;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
-import com.google.devtools.build.lib.analysis.LicensesProvider;
-import com.google.devtools.build.lib.analysis.LicensesProvider.TargetLicense;
-import com.google.devtools.build.lib.analysis.StaticallyLinkedMarkerProvider;
import com.google.devtools.build.lib.analysis.ViewCreationFailedException;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
@@ -35,19 +32,13 @@
import com.google.devtools.build.lib.buildtool.buildevent.TestFilteringCompleteEvent;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.TargetParsingException;
-import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.events.Event;
-import com.google.devtools.build.lib.packages.InputFile;
-import com.google.devtools.build.lib.packages.License;
-import com.google.devtools.build.lib.packages.License.DistributionType;
-import com.google.devtools.build.lib.packages.NoSuchPackageException;
-import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.Target;
-import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.pkgcache.LoadingFailedException;
import com.google.devtools.build.lib.profiler.ProfilePhase;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.SilentCloseable;
+import com.google.devtools.build.lib.runtime.BlazeModule;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.skyframe.BuildConfigurationValue;
import com.google.devtools.build.lib.skyframe.TargetPatternPhaseValue;
@@ -118,16 +109,8 @@
runAnalysisPhase(request, loadingResult, buildOptions, request.getMultiCpus());
}
- // Check licenses.
- // We check licenses if the first target configuration has license checking enabled. Right
- // now, it is not possible to have multiple target configurations with different settings
- // for this flag, which allows us to take this short cut.
- boolean checkLicenses = buildOptions.get(BuildConfiguration.Options.class).checkLicenses;
- if (checkLicenses) {
- Profiler.instance().markPhase(ProfilePhase.LICENSE);
- try (SilentCloseable c = Profiler.instance().profile("validateLicensingForTargets")) {
- validateLicensingForTargets(analysisResult.getTargetsToBuild(), request.getKeepGoing());
- }
+ for (BlazeModule module : env.getRuntime().getBlazeModules()) {
+ module.afterAnalysis(env, request, buildOptions, analysisResult.getTargetsToBuild());
}
reportTargets(analysisResult);
@@ -288,73 +271,4 @@
"Found " + targetCount + (targetCount == 1 ? " target..." : " targets...")));
}
}
-
- /**
- * Takes a set of configured targets, and checks if the distribution methods declared for the
- * targets are compatible with the constraints imposed by their prerequisites' licenses.
- *
- * @param configuredTargets the targets to check
- * @param keepGoing if false, and a licensing error is encountered, both generates an error
- * message on the reporter, <em>and</em> throws an exception. If true, then just generates a
- * message on the reporter.
- * @throws ViewCreationFailedException if the license checking failed (and not --keep_going)
- */
- private void validateLicensingForTargets(
- Iterable<ConfiguredTarget> configuredTargets, boolean keepGoing)
- throws ViewCreationFailedException {
- for (ConfiguredTarget configuredTarget : configuredTargets) {
- Target target = null;
- try {
- target = env.getPackageManager().getTarget(env.getReporter(), configuredTarget.getLabel());
- } catch (NoSuchPackageException | NoSuchTargetException | InterruptedException e) {
- env.getReporter().handle(Event.error("Failed to get target to validate license"));
- throw new ViewCreationFailedException(
- "Build aborted due to issue getting targets to validate licenses", e);
- }
-
- if (TargetUtils.isTestRule(target)) {
- continue; // Tests are exempt from license checking
- }
-
- final Set<DistributionType> distribs = target.getDistributions();
- StaticallyLinkedMarkerProvider markerProvider =
- configuredTarget.getProvider(StaticallyLinkedMarkerProvider.class);
- boolean staticallyLinked = markerProvider != null && markerProvider.isLinkedStatically();
-
- LicensesProvider provider = configuredTarget.getProvider(LicensesProvider.class);
- if (provider != null) {
- NestedSet<TargetLicense> licenses = provider.getTransitiveLicenses();
- for (TargetLicense targetLicense : licenses) {
- if (!targetLicense
- .getLicense()
- .checkCompatibility(
- distribs,
- target,
- targetLicense.getLabel(),
- env.getReporter(),
- staticallyLinked)) {
- if (!keepGoing) {
- throw new ViewCreationFailedException("Build aborted due to licensing error");
- }
- }
- }
- } else if (target instanceof InputFile) {
- // Input file targets do not provide licenses because they do not
- // depend on the rule where their license is taken from. This is usually
- // not a problem, because the transitive collection of licenses always
- // hits the rule they come from, except when the input file is a
- // top-level target. Thus, we need to handle that case specially here.
- //
- // See FileTarget#getLicense for more information about the handling of
- // license issues with File targets.
- License license = target.getLicense();
- if (!license.checkCompatibility(
- distribs, target, configuredTarget.getLabel(), env.getReporter(), staticallyLinked)) {
- if (!keepGoing) {
- throw new ViewCreationFailedException("Build aborted due to licensing error");
- }
- }
- }
- }
- }
}
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/BuildRequest.java b/src/main/java/com/google/devtools/build/lib/buildtool/BuildRequest.java
index 87cf21a..e6213e4 100644
--- a/src/main/java/com/google/devtools/build/lib/buildtool/BuildRequest.java
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/BuildRequest.java
@@ -223,7 +223,7 @@
}
/** Returns the value of the --keep_going option. */
- boolean getKeepGoing() {
+ public boolean getKeepGoing() {
return getOptions(KeepGoingOption.class).keepGoing;
}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/License.java b/src/main/java/com/google/devtools/build/lib/packages/License.java
index 8c68447..c980444 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/License.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/License.java
@@ -15,19 +15,13 @@
package com.google.devtools.build.lib.packages;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Sets;
-import com.google.common.collect.Table;
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.concurrent.ThreadSafety.ThreadSafe;
-import com.google.devtools.build.lib.events.Event;
-import com.google.devtools.build.lib.events.EventHandler;
-import com.google.devtools.build.lib.events.Location;
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.skylarkbuildapi.LicenseApi;
@@ -75,15 +69,16 @@
}
/**
- * Gets the least restrictive license type from the list of licenses declared
- * for a target. For the purposes of license checking, the license type set of
- * a declared license can be reduced to its least restrictive member.
+ * Gets the least restrictive license type from the list of licenses declared for a target. For
+ * the purposes of license checking, the license type set of a declared license can be reduced to
+ * its least restrictive member.
*
* @param types a collection of license types
* @return the least restrictive license type
*/
@VisibleForTesting
- static LicenseType leastRestrictive(Collection<LicenseType> types) {
+ public static LicenseType leastRestrictive(Collection<LicenseType> types) {
+ // TODO(gregce): move this method to LicenseCheckingModule when Bazel's tests no longer use it
return types.isEmpty() ? LicenseType.BY_EXCEPTION_ONLY : Collections.max(types);
}
@@ -138,43 +133,6 @@
}
}
- private static final Object MARKER = new Object();
-
- /**
- * The license incompatibility set. This contains the set of
- * (Distribution,License) pairs that should generate errors.
- */
- private static Table<DistributionType, LicenseType, Object> LICENSE_INCOMPATIBILIES =
- createLicenseIncompatibilitySet();
-
- private static Table<DistributionType, LicenseType, Object> createLicenseIncompatibilitySet() {
- Table<DistributionType, LicenseType, Object> result = HashBasedTable.create();
- result.put(DistributionType.CLIENT, LicenseType.RESTRICTED, MARKER);
- result.put(DistributionType.EMBEDDED, LicenseType.RESTRICTED, MARKER);
- result.put(DistributionType.INTERNAL, LicenseType.BY_EXCEPTION_ONLY, MARKER);
- result.put(DistributionType.CLIENT, LicenseType.BY_EXCEPTION_ONLY, MARKER);
- result.put(DistributionType.WEB, LicenseType.BY_EXCEPTION_ONLY, MARKER);
- result.put(DistributionType.EMBEDDED, LicenseType.BY_EXCEPTION_ONLY, MARKER);
- return ImmutableTable.copyOf(result);
- }
-
- /**
- * The license warning set. This contains the set of
- * (Distribution,License) pairs that should generate warnings when the user
- * requests verbose license checking.
- */
- private static Table<DistributionType, LicenseType, Object> LICENSE_WARNINGS =
- createLicenseWarningsSet();
-
- private static Table<DistributionType, LicenseType, Object> createLicenseWarningsSet() {
- Table<DistributionType, LicenseType, Object> result = HashBasedTable.create();
- result.put(DistributionType.CLIENT, LicenseType.RECIPROCAL, MARKER);
- result.put(DistributionType.EMBEDDED, LicenseType.RECIPROCAL, MARKER);
- result.put(DistributionType.CLIENT, LicenseType.NOTICE, MARKER);
- result.put(DistributionType.EMBEDDED, LicenseType.NOTICE, MARKER);
- return ImmutableTable.copyOf(result);
- }
-
@AutoCodec.Instantiator
@VisibleForSerialization
License(ImmutableSet<LicenseType> licenseTypes, ImmutableSet<Label> exceptions) {
@@ -232,55 +190,6 @@
}
/**
- * Checks if this license is compatible with distributing a particular target
- * in some set of distribution modes.
- *
- * @param dists the modes of distribution
- * @param target the target which is being checked, and which will be used for
- * checking exceptions
- * @param licensedTarget the target which declared the license being checked.
- * @param eventHandler a reporter where any licensing issues discovered should be
- * reported
- * @param staticallyLinked whether the target is statically linked under this command
- * @return true if the license is compatible with the distributions
- */
- public boolean checkCompatibility(Set<DistributionType> dists,
- Target target, Label licensedTarget, EventHandler eventHandler,
- boolean staticallyLinked) {
- Location location = (target instanceof Rule) ? ((Rule) target).getLocation() : null;
-
- LicenseType leastRestrictiveLicense;
- if (licenseTypes.contains(LicenseType.RESTRICTED_IF_STATICALLY_LINKED)) {
- Set<LicenseType> tempLicenses = EnumSet.copyOf(licenseTypes);
- tempLicenses.remove(LicenseType.RESTRICTED_IF_STATICALLY_LINKED);
- if (staticallyLinked) {
- tempLicenses.add(LicenseType.RESTRICTED);
- } else {
- tempLicenses.add(LicenseType.UNENCUMBERED);
- }
- leastRestrictiveLicense = leastRestrictive(tempLicenses);
- } else {
- leastRestrictiveLicense = leastRestrictive(licenseTypes);
- }
- for (DistributionType dt : dists) {
- if (LICENSE_INCOMPATIBILIES.contains(dt, leastRestrictiveLicense)) {
- if (!exceptions.contains(target.getLabel())) {
- eventHandler.handle(Event.error(location, "Build target '" + target.getLabel()
- + "' is not compatible with license '" + this + "' from target '"
- + licensedTarget + "'"));
- return false;
- }
- } else if (LICENSE_WARNINGS.contains(dt, leastRestrictiveLicense)) {
- eventHandler.handle(
- Event.warn(location, "Build target '" + target
- + "' has a potential licensing issue "
- + "with a '" + this + "' license from target '" + licensedTarget + "'"));
- }
- }
- return true;
- }
-
- /**
* @return an immutable set of {@link LicenseType}s contained in this {@code
* License}
*/
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java
index 03bf031..dda1465 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java
@@ -19,7 +19,9 @@
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.ServerDirectories;
+import com.google.devtools.build.lib.analysis.ViewCreationFailedException;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.test.CoverageReportActionFactory;
import com.google.devtools.build.lib.buildtool.BuildRequest;
@@ -246,6 +248,22 @@
}
/**
+ * Called after Bazel analyzes the build's top-level targets. This is called once per build if
+ * --analyze is enabled. Modules can override this to perform extra checks on analysis results.
+ *
+ * @param env the command environment
+ * @param request the build request
+ * @param buildOptions the build's top-level options
+ * @param configuredTargets the build's requested top-level targets as {@link ConfiguredTarget}s
+ */
+ public void afterAnalysis(
+ CommandEnvironment env,
+ BuildRequest request,
+ BuildOptions buildOptions,
+ Iterable<ConfiguredTarget> configuredTargets)
+ throws InterruptedException, ViewCreationFailedException {}
+
+ /**
* Called when Bazel initializes the action execution subsystem. This is called once per build if
* action execution is enabled. Modules can override this method to affect how execution is
* performed.
diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD
index 6f17d30..13e090d 100644
--- a/src/test/java/com/google/devtools/build/lib/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/BUILD
@@ -650,6 +650,7 @@
"//src/main/java/com/google/devtools/build/lib:bazel-main",
"//src/main/java/com/google/devtools/build/lib:bazel-repository",
"//src/main/java/com/google/devtools/build/lib:bazel-rules",
+ "//src/main/java/com/google/devtools/build/lib:bazel/LicenseCheckingModule",
"//src/main/java/com/google/devtools/build/lib:build-base",
"//src/main/java/com/google/devtools/build/lib:build-request-options",
"//src/main/java/com/google/devtools/build/lib:core-rules",
@@ -859,6 +860,7 @@
":testutil",
"//src/main/java/com/google/devtools/build/lib:bazel-main",
"//src/main/java/com/google/devtools/build/lib:bazel-rules",
+ "//src/main/java/com/google/devtools/build/lib:bazel/LicenseCheckingModule",
"//src/main/java/com/google/devtools/build/lib:build-base",
"//src/main/java/com/google/devtools/build/lib:events",
"//src/main/java/com/google/devtools/build/lib:packages",
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/LicensingTests.java b/src/test/java/com/google/devtools/build/lib/analysis/LicensingTests.java
index 7bcb052..b70021a 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/LicensingTests.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/LicensingTests.java
@@ -26,6 +26,7 @@
import com.google.devtools.build.lib.analysis.LicensesProvider.TargetLicense;
import com.google.devtools.build.lib.analysis.util.AnalysisMock;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.bazel.LicenseCheckingModule;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.packages.License;
@@ -552,8 +553,13 @@
Maps.filterKeys(getTransitiveLicenses(used), AnalysisMock.get().ccSupport().labelFilter());
Label usedLabel = Label.parseAbsolute("//used", ImmutableMap.of());
License license = usedActual.get(usedLabel);
- license.checkCompatibility(EnumSet.of(DistributionType.CLIENT),
- getTarget("//user"), usedLabel, reporter, false);
+ LicenseCheckingModule.checkCompatibility(
+ license,
+ EnumSet.of(DistributionType.CLIENT),
+ getTarget("//user"),
+ usedLabel,
+ reporter,
+ false);
assertNoEvents();
}
@@ -576,8 +582,13 @@
Maps.filterKeys(getTransitiveLicenses(used), AnalysisMock.get().ccSupport().labelFilter());
Label usedLabel = Label.parseAbsolute("//used", ImmutableMap.of());
License license = usedActual.get(usedLabel);
- license.checkCompatibility(EnumSet.of(DistributionType.CLIENT),
- getTarget("//user"), usedLabel, reporter, false);
+ LicenseCheckingModule.checkCompatibility(
+ license,
+ EnumSet.of(DistributionType.CLIENT),
+ getTarget("//user"),
+ usedLabel,
+ reporter,
+ false);
assertNoEvents();
}