From d08b27fa9701fecfdb69e1b0d1ac2459efc2129b Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 25 Feb 2015 16:45:20 +0100 Subject: Update from Google. -- MOE_MIGRATED_REVID=85702957 --- .../build/lib/packages/EnvironmentGroup.java | 241 +++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 src/main/java/com/google/devtools/build/lib/packages/EnvironmentGroup.java (limited to 'src/main/java/com/google/devtools/build/lib/packages/EnvironmentGroup.java') diff --git a/src/main/java/com/google/devtools/build/lib/packages/EnvironmentGroup.java b/src/main/java/com/google/devtools/build/lib/packages/EnvironmentGroup.java new file mode 100644 index 0000000000..07da227daf --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/packages/EnvironmentGroup.java @@ -0,0 +1,241 @@ +// Copyright 2015 Google Inc. 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.packages; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.events.Event; +import com.google.devtools.build.lib.events.Location; +import com.google.devtools.build.lib.syntax.Label; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Model for the "environment_group' rule: the piece of Bazel's rule constraint system that binds + * thematically related environments together and determines which environments a rule supports + * by default. See {@link com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics} + * for precise semantic details of how this information is used. + * + *

Note that "environment_group" is implemented as a loading-time function, not a rule. This is + * to support proper discovery of defaults: Say rule A has no explicit constraints and depends + * on rule B, which is explicitly constrained to environment ":bar". Since A declares nothing + * explicitly, it's implicitly constrained to DEFAULTS (whatever that is). Therefore, the + * dependency is only allowed if DEFAULTS doesn't include environments beyond ":bar". To figure + * that out, we need to be able to look up the environment group for ":bar", which is what this + * class provides. + * + *

If we implemented this as a rule, we'd have to provide that lookup via rule dependencies, + * e.g. something like: + * + * + * environment( + * name = 'bar', + * group = [':sample_environments'], + * is_default = 1 + * ) + * + * + *

But this won't work. This would let us find the environment group for ":bar", but the only way + * to determine what other environments belong to the group is to have the group somehow reference + * them. That would produce circular dependencies in the build graph, which is no good. + */ +@Immutable +public class EnvironmentGroup implements Target { + private final Label label; + private final Location location; + private final Package containingPackage; + private final Set

Does not check that the referenced environments exist (see + * {@link #checkEnvironmentsExist). + * + * @return a list of validation errors that occurred + */ + List validateMembership() { + List events = new ArrayList<>(); + + // All environments should belong to the same package as this group. + for (Label environment : + Iterables.filter(environments, new DifferentPackage(containingPackage))) { + events.add(Event.error(location, + environment + " is not in the same package as group " + label)); + } + + // The defaults must be a subset of the member environments. + for (Label unknownDefault : Sets.difference(defaults, environments)) { + events.add(Event.error(location, "default " + unknownDefault + " is not a " + + "declared environment for group " + getLabel())); + } + + return events; + } + + /** + * Given the set of targets in this group's package, checks that all of the group's declared + * environments are part of that set (i.e. the group doesn't reference non-existant labels). + * + * @param pkgTargets mapping from label name to target instance for this group's package + * @return a list of validation errors that occurred + */ + List checkEnvironmentsExist(Map pkgTargets) { + List events = new ArrayList<>(); + for (Label envName : environments) { + Target env = pkgTargets.get(envName.getName()); + if (env == null) { + events.add(Event.error(location, "environment " + envName + " does not exist")); + } else if (!env.getTargetKind().equals("environment rule")) { + events.add(Event.error(location, env.getLabel() + " is not a valid environment")); + } + } + return events; + } + + /** + * Returns the environments that belong to this group. + */ + public Set