diff options
author | Greg Estren <gregce@google.com> | 2016-06-24 16:47:31 +0000 |
---|---|---|
committer | Dmitry Lomov <dslomov@google.com> | 2016-06-27 11:39:09 +0000 |
commit | 3e6f29fcddf4c2d0306e29da01a6d2a49c036249 (patch) | |
tree | d1e0fd23dee74e01accae7700a02bc70256ed53f /src/main/java/com/google/devtools/build/lib/analysis/constraints/ConstraintSemantics.java | |
parent | 28711af16c337976ba10d54cc50db8bc193e3bb3 (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.java | 65 |
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; } /** |