aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/analysis/constraints/ConstraintSemantics.java
diff options
context:
space:
mode:
authorGravatar Greg Estren <gregce@google.com>2016-06-24 16:47:31 +0000
committerGravatar Dmitry Lomov <dslomov@google.com>2016-06-27 11:39:09 +0000
commit3e6f29fcddf4c2d0306e29da01a6d2a49c036249 (patch)
treed1e0fd23dee74e01accae7700a02bc70256ed53f /src/main/java/com/google/devtools/build/lib/analysis/constraints/ConstraintSemantics.java
parent28711af16c337976ba10d54cc50db8bc193e3bb3 (diff)
Provide clearer messaging when a build fails because a rule's
supported environments get refined away by incompatible select paths. This is a fix of TODO: https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/analysis/constraints/ConstraintSemantics.java#L597 Old message: ERROR: /workspace/foo/BUILD:3:1: in cc_binary rule //foo:main: all environments have been refined out of the following groups: //buildenv:environment_group New message: ERROR: /workspace/foo/BUILD:3:1: in cc_binary rule //foo:main: the current command-line flags disqualify all supported environments because of incompatible select() paths: environment: //buildenv:gce removed by: //util/lib:some_dep_with_select (/workspace/util/lib/BUILD:12:1) -- MOS_MIGRATED_REVID=125788804
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/analysis/constraints/ConstraintSemantics.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/constraints/ConstraintSemantics.java65
1 files changed, 55 insertions, 10 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/constraints/ConstraintSemantics.java b/src/main/java/com/google/devtools/build/lib/analysis/constraints/ConstraintSemantics.java
index 398056c2e1..cab7c42832 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/constraints/ConstraintSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/constraints/ConstraintSemantics.java
@@ -511,9 +511,13 @@ public class ConstraintSemantics {
* value of {@link #getSupportedEnvironments}. In particular, for any environment group that's
* not in this collection, the rule is assumed to support the defaults for that group.
* @param refinedEnvironments a builder for populating this rule's refined environments
+ * @param removedEnvironmentCulprits a builder for populating the core dependencies that trigger
+ * pruning away environments through refinement. If multiple dependencies qualify (e.g.
+ * two direct deps under the current rule), one is arbitrarily chosen.
*/
public static void checkConstraints(RuleContext ruleContext,
- EnvironmentCollection staticEnvironments, EnvironmentCollection.Builder refinedEnvironments) {
+ EnvironmentCollection staticEnvironments, EnvironmentCollection.Builder refinedEnvironments,
+ Map<Label, Target> removedEnvironmentCulprits) {
Set<EnvironmentWithGroup> refinedEnvironmentsSoFar = new LinkedHashSet<>();
// Start with the full set of static environments:
refinedEnvironmentsSoFar.addAll(staticEnvironments.getGroupedEnvironments());
@@ -565,11 +569,13 @@ public class ConstraintSemantics {
}
refinedEnvironmentsSoFar.remove(envToPrune);
groupsWithEnvironmentsRemoved.add(envToPrune.group());
+ removedEnvironmentCulprits.put(envToPrune.environment(),
+ findOriginalRefiner(ruleContext, depEnvironments, envToPrune));
}
}
checkRefinedEnvironmentConstraints(ruleContext, groupsWithEnvironmentsRemoved,
- refinedEnvironmentsSoFar, refinedEnvironments);
+ refinedEnvironmentsSoFar, refinedEnvironments, removedEnvironmentCulprits);
}
/**
@@ -582,9 +588,11 @@ public class ConstraintSemantics {
* <p>Violations of this expectation trigger rule analysis errors.
*/
private static void checkRefinedEnvironmentConstraints(
- RuleContext ruleContext, Set<EnvironmentGroup> groupsWithEnvironmentsRemoved,
+ RuleContext ruleContext,
+ Set<EnvironmentGroup> groupsWithEnvironmentsRemoved,
Set<EnvironmentWithGroup> refinedEnvironmentsSoFar,
- EnvironmentCollection.Builder refinedEnvironments) {
+ EnvironmentCollection.Builder refinedEnvironments,
+ Map<Label, Target> removedEnvironmentCulprits) {
Set<EnvironmentGroup> refinedGroups = new LinkedHashSet<>();
for (EnvironmentWithGroup envWithGroup : refinedEnvironmentsSoFar) {
refinedEnvironments.put(envWithGroup.group(), envWithGroup.environment());
@@ -594,14 +602,51 @@ public class ConstraintSemantics {
? ImmutableSet.<EnvironmentGroup>of()
: Sets.difference(groupsWithEnvironmentsRemoved, refinedGroups);
if (!newlyEmptyGroups.isEmpty()) {
- // TODO(bazel-team): specify exactly which deps violated expectations.
- Set<Label> groupsAsLabels = new LinkedHashSet<>();
- for (EnvironmentGroup group : newlyEmptyGroups) {
- groupsAsLabels.add(group.getLabel());
+ ruleContext.ruleError(getOverRefinementError(newlyEmptyGroups, removedEnvironmentCulprits));
+ }
+ }
+
+ /**
+ * Constructs an error message for when all environments have been pruned out of one
+ * or more environment groups due to refining.
+ */
+ private static String getOverRefinementError(Set<EnvironmentGroup> newlyEmptyGroups,
+ Map<Label, Target> removedEnvironmentCulprits) {
+ StringBuilder message = new StringBuilder("the current command-line flags disqualify "
+ + "all supported environments because of incompatible select() paths:");
+ for (EnvironmentGroup group : newlyEmptyGroups) {
+ if (newlyEmptyGroups.size() > 1) {
+ message.append("\n\nenvironment group: " + group.getLabel() + ":");
+ }
+ for (Label prunedEnvironment : group.getEnvironments()) {
+ Target culprit = removedEnvironmentCulprits.get(prunedEnvironment);
+ if (culprit != null) { // Only environments this rule declared support for have culprits.
+ message.append("\n environment: " + prunedEnvironment
+ + " removed by: " + culprit.getLabel() + " (" + culprit.getLocation() + ")");
+ }
}
- ruleContext.ruleError("all environments have been refined out of the following groups: "
- + Joiner.on(", ").join(groupsAsLabels));
}
+ return message.toString();
+ }
+
+ /**
+ * Given an environment that should be refined out of the current rule because of the given dep,
+ * returns the original dep that caused the removal.
+ *
+ * <p>For example, say we have R -> D1 -> D2 and all rules support environment E. If the
+ * refinement happens because D2 has
+ * <pre>
+ * deps = select({":foo": ["restricted_to_E"], ":bar": ["restricted_to_F"]}} # Choose F.
+ * </pre>
+ *
+ * <p>then D2 is the original refiner (even though D1 and R inherit the same pruning).
+ */
+ private static Target findOriginalRefiner(RuleContext ruleContext,
+ SupportedEnvironmentsProvider dep, EnvironmentWithGroup envToPrune) {
+ Target depCulprit = dep.getRemovedEnvironmentCulprit(envToPrune.environment());
+ // If the dep has no record of this environment being refined, that means the current rule
+ // is the culprit.
+ return depCulprit == null ? ruleContext.getTarget() : depCulprit;
}
/**