diff options
Diffstat (limited to 'src/main/java/com/google')
8 files changed, 262 insertions, 134 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java index 5d884515eb..5396334615 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java @@ -45,6 +45,7 @@ import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider; import com.google.devtools.build.lib.analysis.config.DynamicTransitionMapper; import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; import com.google.devtools.build.lib.analysis.config.PatchTransition; +import com.google.devtools.build.lib.analysis.constraints.TopLevelConstraintSemantics; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.cmdline.PackageIdentifier; import com.google.devtools.build.lib.collect.nestedset.NestedSet; @@ -335,8 +336,9 @@ public class BuildView { * Return value for {@link BuildView#update} and {@code BuildTool.prepareToBuild}. */ public static final class AnalysisResult { - private final ImmutableList<ConfiguredTarget> targetsToBuild; + private final ImmutableSet<ConfiguredTarget> targetsToBuild; @Nullable private final ImmutableList<ConfiguredTarget> targetsToTest; + private final ImmutableSet<ConfiguredTarget> targetsToSkip; @Nullable private final String error; private final ActionGraph actionGraph; private final ImmutableSet<Artifact> artifactsToBuild; @@ -351,6 +353,7 @@ public class BuildView { Collection<ConfiguredTarget> targetsToBuild, Collection<AspectValue> aspects, Collection<ConfiguredTarget> targetsToTest, + Collection<ConfiguredTarget> targetsToSkip, @Nullable String error, ActionGraph actionGraph, Collection<Artifact> artifactsToBuild, @@ -359,9 +362,10 @@ public class BuildView { TopLevelArtifactContext topLevelContext, ImmutableMap<PackageIdentifier, Path> packageRoots, String workspaceName) { - this.targetsToBuild = ImmutableList.copyOf(targetsToBuild); + this.targetsToBuild = ImmutableSet.copyOf(targetsToBuild); this.aspects = ImmutableList.copyOf(aspects); this.targetsToTest = targetsToTest == null ? null : ImmutableList.copyOf(targetsToTest); + this.targetsToSkip = ImmutableSet.copyOf(targetsToSkip); this.error = error; this.actionGraph = actionGraph; this.artifactsToBuild = ImmutableSet.copyOf(artifactsToBuild); @@ -375,7 +379,7 @@ public class BuildView { /** * Returns configured targets to build. */ - public Collection<ConfiguredTarget> getTargetsToBuild() { + public ImmutableSet<ConfiguredTarget> getTargetsToBuild() { return targetsToBuild; } @@ -406,6 +410,16 @@ public class BuildView { return targetsToTest; } + /** + * Returns the configured targets that should not be executed because they're not + * platform-compatible with the current build. + * + * <p>For example: tests that aren't intended for the designated CPU. + */ + public ImmutableSet<ConfiguredTarget> getTargetsToSkip() { + return targetsToSkip; + } + public ImmutableSet<Artifact> getAdditionalArtifactsToBuild() { return artifactsToBuild; } @@ -591,13 +605,20 @@ public class BuildView { LOG.info(msg); } + Set<ConfiguredTarget> targetsToSkip = + TopLevelConstraintSemantics.checkTargetEnvironmentRestrictions( + skyframeAnalysisResult.getConfiguredTargets(), + skyframeExecutor.getPackageManager(), + eventHandler); + AnalysisResult result = createResult( eventHandler, loadingResult, topLevelOptions, viewOptions, - skyframeAnalysisResult); + skyframeAnalysisResult, + targetsToSkip); LOG.info("Finished analysis"); return result; } @@ -607,17 +628,19 @@ public class BuildView { LoadingResult loadingResult, TopLevelArtifactContext topLevelOptions, BuildView.Options viewOptions, - SkyframeAnalysisResult skyframeAnalysisResult) + SkyframeAnalysisResult skyframeAnalysisResult, + Set<ConfiguredTarget> targetsToSkip) throws InterruptedException { Collection<Target> testsToRun = loadingResult.getTestsToRun(); - Collection<ConfiguredTarget> configuredTargets = skyframeAnalysisResult.getConfiguredTargets(); + Set<ConfiguredTarget> configuredTargets = + Sets.newLinkedHashSet(skyframeAnalysisResult.getConfiguredTargets()); Collection<AspectValue> aspects = skyframeAnalysisResult.getAspects(); - Collection<ConfiguredTarget> allTargetsToTest = null; + Set<ConfiguredTarget> allTargetsToTest = null; if (testsToRun != null) { // Determine the subset of configured targets that are meant to be run as tests. - allTargetsToTest = - Lists.newArrayList(filterTestsByTargets(configuredTargets, Sets.newHashSet(testsToRun))); + allTargetsToTest = Sets.newLinkedHashSet( + filterTestsByTargets(configuredTargets, Sets.newHashSet(testsToRun))); } Set<Artifact> artifactsToBuild = new HashSet<>(); @@ -682,6 +705,7 @@ public class BuildView { configuredTargets, aspects, allTargetsToTest, + targetsToSkip, error, actionGraph, artifactsToBuild, diff --git a/src/main/java/com/google/devtools/build/lib/analysis/constraints/TopLevelConstraintSemantics.java b/src/main/java/com/google/devtools/build/lib/analysis/constraints/TopLevelConstraintSemantics.java new file mode 100644 index 0000000000..6fd2a9b7fb --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/analysis/constraints/TopLevelConstraintSemantics.java @@ -0,0 +1,190 @@ +// 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. + * + * <p>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. + * + * <p>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. + * + * <p>If any target doesn't support an explicitly expected environment declared through + * {@link BuildConfiguration.Options#targetEnvironments}, the entire build fails with an error. + * + * <p>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<ConfiguredTarget> checkTargetEnvironmentRestrictions( + Iterable<ConfiguredTarget> topLevelTargets, PackageManager packageManager, + ExtendedEventHandler eventHandler) + throws ViewCreationFailedException, InterruptedException { + ImmutableSet.Builder<ConfiguredTarget> 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<ConfiguredTarget, Label> 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<Label> targetEnvironments = config.getTargetEnvironments(); + if (targetEnvironments.isEmpty()) { + try { + targetEnvironments = autoConfigureTargetEnvironments(config, + config.getAutoCpuEnvironmentGroup(), packageManager, eventHandler); + failBuildIfTargetIsBad = false; + } catch (NoSuchPackageException + | NoSuchTargetException + | ConstraintSemantics.EnvironmentLookupException e) { + throw new ViewCreationFailedException("invalid target environment", e); + } + } + + if (targetEnvironments.isEmpty()) { + continue; + } + + // Parse and collect this configuration's environments. + EnvironmentCollection.Builder builder = new EnvironmentCollection.Builder(); + for (Label envLabel : targetEnvironments) { + try { + Target env = packageManager.getTarget(eventHandler, envLabel); + builder.put(ConstraintSemantics.getEnvironmentGroup(env), envLabel); + } catch (NoSuchPackageException | NoSuchTargetException + | ConstraintSemantics.EnvironmentLookupException e) { + throw new ViewCreationFailedException("invalid target environment", e); + } + } + EnvironmentCollection expectedEnvironments = builder.build(); + + // Now check the target against those environments. + TransitiveInfoCollection asProvider; + if (topLevelTarget instanceof OutputFileConfiguredTarget) { + asProvider = ((OutputFileConfiguredTarget) topLevelTarget).getGeneratingRule(); + } else { + asProvider = topLevelTarget; + } + SupportedEnvironmentsProvider provider = + Verify.verifyNotNull(asProvider.getProvider(SupportedEnvironmentsProvider.class)); + Collection<Label> missingEnvironments = + ConstraintSemantics.getUnsupportedEnvironments( + provider.getRefinedEnvironments(), expectedEnvironments); + if (!missingEnvironments.isEmpty()) { + badTargets.add(topLevelTarget); + if (failBuildIfTargetIsBad) { + exceptionInducingTargets.putAll(topLevelTarget, missingEnvironments); + } + } + } + + if (!exceptionInducingTargets.isEmpty()) { + throw new ViewCreationFailedException(getBadTargetsUserMessage(exceptionInducingTargets)); + } + return ImmutableSet.copyOf(badTargets.build()); + } + + /** + * Helper method for {@link #checkTargetEnvironmentRestrictions} that populates inferred + * expected environments. + */ + private static List<Label> autoConfigureTargetEnvironments(BuildConfiguration config, + @Nullable Label environmentGroupLabel, PackageManager packageManager, + ExtendedEventHandler eventHandler) + throws InterruptedException, NoSuchTargetException, NoSuchPackageException, + ConstraintSemantics.EnvironmentLookupException { + if (environmentGroupLabel == null) { + return ImmutableList.of(); + } + + EnvironmentGroup environmentGroup = (EnvironmentGroup) + packageManager.getTarget(eventHandler, environmentGroupLabel); + + ImmutableList.Builder<Label> targetEnvironments = new ImmutableList.Builder<>(); + for (Label environmentLabel : environmentGroup.getEnvironments()) { + if (environmentLabel.getName().equals(config.getCpu())) { + targetEnvironments.add(environmentLabel); + } + } + + return targetEnvironments.build(); + } + + /** + * Prepares a user-friendly error message for a list of targets missing support for required + * environments. + */ + private static String getBadTargetsUserMessage(Multimap<ConfiguredTarget, Label> badTargets) { + StringBuilder msg = new StringBuilder(); + msg.append("This is a restricted-environment build."); + for (Map.Entry<ConfiguredTarget, Collection<Label>> entry : badTargets.asMap().entrySet()) { + msg.append(String.format("\n - %s does not support required environment%s %s.", + entry.getKey().getLabel(), + entry.getValue().size() == 1 ? "" : "s", + Joiner.on(", ").join(entry.getValue()))); + } + return msg.toString(); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/BuildResult.java b/src/main/java/com/google/devtools/build/lib/buildtool/BuildResult.java index 8bbc62c107..741ef98a94 100644 --- a/src/main/java/com/google/devtools/build/lib/buildtool/BuildResult.java +++ b/src/main/java/com/google/devtools/build/lib/buildtool/BuildResult.java @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.buildtool; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection; @@ -42,6 +43,7 @@ public final class BuildResult { private Collection<ConfiguredTarget> actualTargets; private Collection<ConfiguredTarget> testTargets; private Collection<ConfiguredTarget> successfulTargets; + private Collection<ConfiguredTarget> skippedTargets; public BuildResult(long startTimeMillis) { this.startTimeMillis = startTimeMillis; @@ -207,6 +209,22 @@ public final class BuildResult { return successfulTargets; } + /** + * See {@link #getSkippedTargets()}. + */ + void setSkippedTargets(Collection<ConfiguredTarget> skippedTargets) { + this.skippedTargets = skippedTargets; + } + + /** + * Returns the set of targets which were skipped (Blaze didn't attempt to execute them) + * because they're not compatible with the build's target platform. + */ + @VisibleForTesting + public Collection<ConfiguredTarget> getSkippedTargets() { + return skippedTargets; + } + /** For debugging. */ @Override public String toString() { diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java b/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java index 2d036eeef2..b43863d083 100644 --- a/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java +++ b/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java @@ -56,6 +56,7 @@ class BuildResultPrinter { BuildRequest request, BuildResult result, Collection<ConfiguredTarget> configuredTargets, + Collection<ConfiguredTarget> configuredTargetsToSkip, Collection<AspectValue> aspects) { // NOTE: be careful what you print! We don't want to create a consistency // problem where the summary message and the exit code disagree. The logic @@ -72,6 +73,9 @@ class BuildResultPrinter { (successfulTargets.contains(target) ? succeeded : failed).add(target); } + // TODO(bazel-team): convert these to a new "SKIPPED" status when ready: b/62191890. + failed.addAll(configuredTargetsToSkip); + // Suppress summary if --show_result value is exceeded: if (succeeded.size() + failed.size() + aspectsToPrint.size() > request.getBuildOptions().maxResultTargets) { diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java b/src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java index f9bab78bd4..a65c0ae6e0 100644 --- a/src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java +++ b/src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java @@ -14,11 +14,8 @@ package com.google.devtools.build.lib.buildtool; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Joiner; import com.google.common.base.Stopwatch; import com.google.common.base.Throwables; -import com.google.common.base.Verify; -import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.actions.BuildFailedException; import com.google.devtools.build.lib.actions.TestExecException; import com.google.devtools.build.lib.analysis.AnalysisPhaseCompleteEvent; @@ -29,39 +26,28 @@ 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.MakeEnvironmentEvent; -import com.google.devtools.build.lib.analysis.OutputFileConfiguredTarget; import com.google.devtools.build.lib.analysis.StaticallyLinkedMarkerProvider; -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.analysis.config.BuildConfigurationCollection; import com.google.devtools.build.lib.analysis.config.BuildOptions; import com.google.devtools.build.lib.analysis.config.DefaultsPackage; import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; -import com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics; -import com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics.EnvironmentLookupException; -import com.google.devtools.build.lib.analysis.constraints.EnvironmentCollection; -import com.google.devtools.build.lib.analysis.constraints.SupportedEnvironmentsProvider; import com.google.devtools.build.lib.buildtool.BuildRequest.BuildRequestOptions; import com.google.devtools.build.lib.buildtool.buildevent.BuildCompleteEvent; import com.google.devtools.build.lib.buildtool.buildevent.BuildInterruptedEvent; import com.google.devtools.build.lib.buildtool.buildevent.BuildStartingEvent; 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.events.OutputFilter; import com.google.devtools.build.lib.events.Reporter; -import com.google.devtools.build.lib.packages.EnvironmentGroup; 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.LoadedPackageProvider; import com.google.devtools.build.lib.pkgcache.LoadingCallback; import com.google.devtools.build.lib.pkgcache.LoadingFailedException; import com.google.devtools.build.lib.pkgcache.LoadingPhaseRunner; @@ -76,12 +62,10 @@ import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.util.RegexFilter; import com.google.devtools.common.options.OptionsParsingException; import java.util.Collection; -import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.logging.Logger; import java.util.regex.Pattern; -import javax.annotation.Nullable; /** * Provides the bulk of the implementation of the 'blaze build' command. @@ -223,9 +207,6 @@ public final class BuildTool { result.setActualTargets(analysisResult.getTargetsToBuild()); result.setTestTargets(analysisResult.getTargetsToTest()); - LoadedPackageProvider bridge = - new LoadedPackageProvider(env.getPackageManager(), env.getReporter()); - checkTargetEnvironmentRestrictions(analysisResult.getTargetsToBuild(), bridge); reportTargets(analysisResult); // Execution phase. @@ -291,104 +272,6 @@ public final class BuildTool { } } - /** - * Checks that if this is an environment-restricted build, all top-level targets support the - * expected environments. - * - * @param topLevelTargets the build's top-level targets - * @throws ViewCreationFailedException if constraint enforcement is on, the build declares - * environment-restricted top level configurations, and any top-level target doesn't support - * the expected environments - */ - private static void checkTargetEnvironmentRestrictions( - Iterable<ConfiguredTarget> topLevelTargets, LoadedPackageProvider packageManager) - throws ViewCreationFailedException, InterruptedException { - for (ConfiguredTarget topLevelTarget : topLevelTargets) { - BuildConfiguration config = topLevelTarget.getConfiguration(); - if (config == null) { - // TODO(bazel-team): support file targets (they should apply package-default constraints). - continue; - } else if (!config.enforceConstraints()) { - continue; - } - - List<Label> targetEnvironments = config.getTargetEnvironments(); - if (targetEnvironments.isEmpty()) { - try { - targetEnvironments = - autoConfigureTargetEnvironments( - packageManager, config, config.getAutoCpuEnvironmentGroup()); - } catch (NoSuchPackageException - | NoSuchTargetException - | ConstraintSemantics.EnvironmentLookupException e) { - throw new ViewCreationFailedException("invalid target environment", e); - } - } - - if (targetEnvironments.isEmpty()) { - continue; - } - - // Parse and collect this configuration's environments. - EnvironmentCollection.Builder builder = new EnvironmentCollection.Builder(); - for (Label envLabel : targetEnvironments) { - try { - Target env = packageManager.getLoadedTarget(envLabel); - builder.put(ConstraintSemantics.getEnvironmentGroup(env), envLabel); - } catch (NoSuchPackageException | NoSuchTargetException - | ConstraintSemantics.EnvironmentLookupException e) { - throw new ViewCreationFailedException("invalid target environment", e); - } - } - EnvironmentCollection expectedEnvironments = builder.build(); - - // Now check the target against those environments. - TransitiveInfoCollection asProvider; - if (topLevelTarget instanceof OutputFileConfiguredTarget) { - asProvider = ((OutputFileConfiguredTarget) topLevelTarget).getGeneratingRule(); - } else { - asProvider = topLevelTarget; - } - SupportedEnvironmentsProvider provider = - Verify.verifyNotNull(asProvider.getProvider(SupportedEnvironmentsProvider.class)); - Collection<Label> missingEnvironments = - ConstraintSemantics.getUnsupportedEnvironments( - provider.getRefinedEnvironments(), expectedEnvironments); - if (!missingEnvironments.isEmpty()) { - throw new ViewCreationFailedException( - String.format( - "This is a restricted-environment build. %s does not support" - + " required environment%s %s", - topLevelTarget.getLabel(), - missingEnvironments.size() == 1 ? "" : "s", - Joiner.on(", ").join(missingEnvironments))); - } - } - } - - private static List<Label> autoConfigureTargetEnvironments( - LoadedPackageProvider packageManager, - BuildConfiguration config, - @Nullable Label environmentGroupLabel) - throws InterruptedException, NoSuchTargetException, NoSuchPackageException, - EnvironmentLookupException { - if (environmentGroupLabel == null) { - return ImmutableList.of(); - } - - EnvironmentGroup environmentGroup = - (EnvironmentGroup) packageManager.getLoadedTarget(environmentGroupLabel); - - ImmutableList.Builder<Label> targetEnvironments = new ImmutableList.Builder<>(); - for (Label environmentLabel : environmentGroup.getEnvironments()) { - if (environmentLabel.getName().equals(config.getCpu())) { - targetEnvironments.add(environmentLabel); - } - } - - return targetEnvironments.build(); - } - private void reportExceptionError(Exception e) { if (e.getMessage() != null) { getReporter().handle(Event.error(e.getMessage())); diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java index ef87660e9e..953ae1647b 100644 --- a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java +++ b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java @@ -430,6 +430,7 @@ public class ExecutionTool { analysisResult.getParallelTests(), analysisResult.getExclusiveTests(), analysisResult.getTargetsToBuild(), + analysisResult.getTargetsToSkip(), analysisResult.getAspects(), executor, builtTargets, @@ -467,9 +468,10 @@ public class ExecutionTool { try (AutoProfiler p = AutoProfiler.profiled("Show results", ProfilerTask.INFO)) { buildResult.setSuccessfulTargets( determineSuccessfulTargets(configuredTargets, builtTargets, timer)); + buildResult.setSkippedTargets(analysisResult.getTargetsToSkip()); BuildResultPrinter buildResultPrinter = new BuildResultPrinter(env); - buildResultPrinter.showBuildResult( - request, buildResult, configuredTargets, analysisResult.getAspects()); + buildResultPrinter.showBuildResult(request, buildResult, configuredTargets, + analysisResult.getTargetsToSkip(), analysisResult.getAspects()); } try (AutoProfiler p = AutoProfiler.profiled("Show artifacts", ProfilerTask.INFO)) { diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/SkyframeBuilder.java b/src/main/java/com/google/devtools/build/lib/buildtool/SkyframeBuilder.java index c8cde04074..ab8bcee37c 100644 --- a/src/main/java/com/google/devtools/build/lib/buildtool/SkyframeBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/buildtool/SkyframeBuilder.java @@ -18,6 +18,7 @@ import com.google.common.base.Optional; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Range; +import com.google.common.collect.Sets; import com.google.devtools.build.lib.actions.ActionCacheChecker; import com.google.devtools.build.lib.actions.ActionExecutionException; import com.google.devtools.build.lib.actions.ActionExecutionStatusReporter; @@ -97,7 +98,8 @@ public class SkyframeBuilder implements Builder { Set<Artifact> artifacts, Set<ConfiguredTarget> parallelTests, Set<ConfiguredTarget> exclusiveTests, - Collection<ConfiguredTarget> targetsToBuild, + Set<ConfiguredTarget> targetsToBuild, + Set<ConfiguredTarget> targetsToSkip, Collection<AspectValue> aspects, Executor executor, Set<ConfiguredTarget> builtTargets, @@ -139,6 +141,10 @@ public class SkyframeBuilder implements Builder { executionProgressReceiver, statusReporter); watchdog.start(); + targetsToBuild = Sets.difference(targetsToBuild, targetsToSkip); + parallelTests = Sets.difference(parallelTests, targetsToSkip); + exclusiveTests = Sets.difference(exclusiveTests, targetsToSkip); + try { result = skyframeExecutor.buildArtifacts( diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/Builder.java b/src/main/java/com/google/devtools/build/lib/skyframe/Builder.java index d25341a4e7..1b88199614 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/Builder.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/Builder.java @@ -24,10 +24,8 @@ import com.google.devtools.build.lib.analysis.TopLevelArtifactContext; import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible; import com.google.devtools.build.lib.events.Reporter; import com.google.devtools.build.lib.util.AbruptExitException; - import java.util.Collection; import java.util.Set; - import javax.annotation.Nullable; /** @@ -56,6 +54,8 @@ public interface Builder { * artifacts. * @param exclusiveTests are executed one at a time, only after all other tasks have completed * @param targetsToBuild Set of targets which will be built + * @param targetsToSkip Set of targets which should be skipped (they still show up in build + * results, but with a "SKIPPED" status and without the cost of any actual build work) * @param aspects Set of aspects that will be built * @param executor an opaque application-specific value that will be * passed down to the execute() method of any Action executed during @@ -65,10 +65,10 @@ public interface Builder { * valid even if a future action throws ActionExecutionException * @param lastExecutionTimeRange If not null, the start/finish time of the last build that * run the execution phase. - * @param topLevelArtifactContext contains the the options which determine the artifacts to build + * @param topLevelArtifactContext contains the options which determine the artifacts to build * for the top-level targets. * @throws BuildFailedException if there were problems establishing the action execution - * environment, if the the metadata of any file during the build could not be obtained, + * environment, if the metadata of any file during the build could not be obtained, * if any input files are missing, or if an action fails during execution * @throws InterruptedException if there was an asynchronous stop request * @throws TestExecException if any test fails @@ -79,7 +79,8 @@ public interface Builder { Set<Artifact> artifacts, Set<ConfiguredTarget> parallelTests, Set<ConfiguredTarget> exclusiveTests, - Collection<ConfiguredTarget> targetsToBuild, + Set<ConfiguredTarget> targetsToBuild, + Set<ConfiguredTarget> targetsToSkip, Collection<AspectValue> aspects, Executor executor, Set<ConfiguredTarget> builtTargets, |