// Copyright 2017 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.analysis.constraints;
import com.google.common.base.Joiner;
import com.google.common.base.Verify;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.OutputFileConfiguredTarget;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.ViewCreationFailedException;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.packages.EnvironmentGroup;
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.pkgcache.PackageManager;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
/**
* Constraint semantics that apply to top-level targets.
*
*
Top-level targets are "special" because they have no parents that can assert expected
* environment compatibility. So these expectations have to be declared by other means.
*
*
For all other targets see {@link ConstraintSemantics}.
*/
public class TopLevelConstraintSemantics {
/**
* Checks that if this is an environment-restricted build, all top-level targets support
* expected top-level environments. Expected top-level environments can be declared explicitly
* through {@code --target_environment} or implicitly through
* {@code --experimental_auto_cpu_environment_group}. For the latter, top-level targets must
* be compatible with the build's target configuration CPU.
*
*
If any target doesn't support an explicitly expected environment declared through
* {@link BuildConfiguration.Options#targetEnvironments}, the entire build fails with an error.
*
*
If any target doesn't support an implicitly expected environment declared through
* {@link BuildConfiguration.Options#autoCpuEnvironmentGroup}, the target is skipped during
* execution while remaining targets execute as normal.
*
* @param topLevelTargets the build's top-level targets
* @param packageManager object for retrieving loaded targets
* @param eventHandler the build's event handler
*
* @return the set of bad top-level targets.
* @throws ViewCreationFailedException if any target doesn't support an explicitly expected
* environment declared through {@link BuildConfiguration.Options#targetEnvironments}
*/
public static Set checkTargetEnvironmentRestrictions(
Iterable topLevelTargets, PackageManager packageManager,
ExtendedEventHandler eventHandler)
throws ViewCreationFailedException, InterruptedException {
ImmutableSet.Builder badTargets = ImmutableSet.builder();
// Maps targets that are missing *explicitly* required environments to the set of environments
// they're missing. These targets trigger a ViewCreationFailedException, which halts the build.
// Targets with missing *implicitly* required environments don't belong here, since the build
// continues while skipping them.
Multimap exceptionInducingTargets = ArrayListMultimap.create();
for (ConfiguredTarget topLevelTarget : topLevelTargets) {
BuildConfiguration config = topLevelTarget.getConfiguration();
boolean failBuildIfTargetIsBad = true;
if (config == null) {
// TODO(bazel-team): support file targets (they should apply package-default constraints).
continue;
} else if (!config.enforceConstraints()) {
continue;
}
List