diff options
author | 2015-10-12 15:44:09 +0000 | |
---|---|---|
committer | 2015-10-13 01:01:03 +0000 | |
commit | 3ca7b788dfbd5f323e9b6c58df3bdce4ced95d81 (patch) | |
tree | 381604334b7223f471990ed3f67746b06c043034 /src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java | |
parent | aa8b1520c6c90ab9f0a489f996937fc6a355ca3c (diff) |
Description redacted.
--
MOS_MIGRATED_REVID=105214382
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java | 243 |
1 files changed, 243 insertions, 0 deletions
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 new file mode 100644 index 0000000000..c12fed248d --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java @@ -0,0 +1,243 @@ +// Copyright 2014 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.buildtool; + +import com.google.common.collect.ImmutableList; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.FileProvider; +import com.google.devtools.build.lib.analysis.InputFileConfiguredTarget; +import com.google.devtools.build.lib.analysis.OutputFileConfiguredTarget; +import com.google.devtools.build.lib.analysis.OutputGroupProvider; +import com.google.devtools.build.lib.analysis.TopLevelArtifactContext; +import com.google.devtools.build.lib.analysis.TopLevelArtifactHelper; +import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; +import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.collect.CollectionUtils; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; +import com.google.devtools.build.lib.exec.ExecutionOptions; +import com.google.devtools.build.lib.packages.Rule; +import com.google.devtools.build.lib.runtime.BlazeRuntime; +import com.google.devtools.build.lib.runtime.CommandEnvironment; +import com.google.devtools.build.lib.skyframe.AspectValue; +import com.google.devtools.build.lib.util.io.OutErr; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * Handles --show_results and --experimental_show_artifacts. + */ +class BuildResultPrinter { + private final CommandEnvironment env; + private final BlazeRuntime runtime; + + BuildResultPrinter(CommandEnvironment env) { + this.env = env; + this.runtime = env.getRuntime(); + } + + /** + * Shows the result of the build. Information includes the list of up-to-date + * and failed targets and list of output artifacts for successful targets + * + * <p>This corresponds to the --show_results flag. + */ + public void showBuildResult( + BuildRequest request, + BuildResult result, + Collection<ConfiguredTarget> configuredTargets, + 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 + // here is already complex. + + Collection<ConfiguredTarget> targetsToPrint = filterTargetsToPrint(configuredTargets); + Collection<AspectValue> aspectsToPrint = filterAspectsToPrint(aspects); + + // Filter the targets we care about into two buckets: + Collection<ConfiguredTarget> succeeded = new ArrayList<>(); + Collection<ConfiguredTarget> failed = new ArrayList<>(); + for (ConfiguredTarget target : targetsToPrint) { + Collection<ConfiguredTarget> successfulTargets = result.getSuccessfulTargets(); + (successfulTargets.contains(target) ? succeeded : failed).add(target); + } + + // Suppress summary if --show_result value is exceeded: + if (succeeded.size() + failed.size() + aspectsToPrint.size() + > request.getBuildOptions().maxResultTargets) { + return; + } + + OutErr outErr = request.getOutErr(); + + TopLevelArtifactContext context = request.getTopLevelArtifactContext(); + for (ConfiguredTarget target : succeeded) { + Label label = target.getLabel(); + // For up-to-date targets report generated artifacts, but only + // if they have associated action and not middleman artifacts. + boolean headerFlag = true; + for (Artifact artifact : + TopLevelArtifactHelper.getAllArtifactsToBuild(target, context).getImportantArtifacts()) { + if (shouldPrint(artifact)) { + if (headerFlag) { + outErr.printErr("Target " + label + " up-to-date:\n"); + headerFlag = false; + } + outErr.printErrLn(formatArtifactForShowResults(artifact, request)); + } + } + if (headerFlag) { + outErr.printErr("Target " + label + " up-to-date (nothing to build)\n"); + } + } + + for (AspectValue aspect : aspectsToPrint) { + Label label = aspect.getLabel(); + String aspectName = aspect.getAspect().getName(); + boolean headerFlag = true; + NestedSet<Artifact> importantArtifacts = + TopLevelArtifactHelper.getAllArtifactsToBuild(aspect, context).getImportantArtifacts(); + for (Artifact importantArtifact : importantArtifacts) { + if (headerFlag) { + outErr.printErr("Aspect " + aspectName + " of " + label + " up-to-date:\n"); + headerFlag = false; + } + if (shouldPrint(importantArtifact)) { + outErr.printErrLn(formatArtifactForShowResults(importantArtifact, request)); + } + } + if (headerFlag) { + outErr.printErr( + "Aspect " + aspectName + " of " + label + " up-to-date (nothing to build)\n"); + } + } + + for (ConfiguredTarget target : failed) { + outErr.printErr("Target " + target.getLabel() + " failed to build\n"); + + // For failed compilation, it is still useful to examine temp artifacts, + // (ie, preprocessed and assembler files). + OutputGroupProvider topLevelProvider = + target.getProvider(OutputGroupProvider.class); + if (topLevelProvider != null) { + for (Artifact temp : topLevelProvider.getOutputGroup(OutputGroupProvider.TEMP_FILES)) { + if (temp.getPath().exists()) { + outErr.printErrLn(" See temp at " + + OutputDirectoryLinksUtils.getPrettyPath(temp.getPath(), + runtime.getWorkspaceName(), + runtime.getWorkspace(), + request.getSymlinkPrefix())); + } + } + } + } + if (!failed.isEmpty() && !request.getOptions(ExecutionOptions.class).verboseFailures) { + outErr.printErr("Use --verbose_failures to see the command lines of failed build steps.\n"); + } + } + + private boolean shouldPrint(Artifact artifact) { + return !artifact.isSourceArtifact() && !artifact.isMiddlemanArtifact(); + } + + private String formatArtifactForShowResults(Artifact artifact, BuildRequest request) { + return " " + OutputDirectoryLinksUtils.getPrettyPath(artifact.getPath(), + runtime.getWorkspaceName(), runtime.getWorkspace(), request.getSymlinkPrefix()); + } + + /** + * Prints a flat list of all artifacts built by the passed top-level targets. + * + * <p>This corresponds to the --experimental_show_artifacts flag. + */ + public void showArtifacts( + BuildRequest request, + Collection<ConfiguredTarget> configuredTargets, + Collection<AspectValue> aspects) { + + TopLevelArtifactContext context = request.getTopLevelArtifactContext(); + Collection<ConfiguredTarget> targetsToPrint = filterTargetsToPrint(configuredTargets); + Collection<AspectValue> aspectsToPrint = filterAspectsToPrint(aspects); + + NestedSetBuilder<Artifact> artifactsBuilder = NestedSetBuilder.stableOrder(); + for (ConfiguredTarget target : targetsToPrint) { + artifactsBuilder.addTransitive( + TopLevelArtifactHelper.getAllArtifactsToBuild(target, context).getImportantArtifacts()); + } + + for (AspectValue aspect : aspectsToPrint) { + artifactsBuilder.addTransitive( + TopLevelArtifactHelper.getAllArtifactsToBuild(aspect, context).getImportantArtifacts()); + } + + OutErr outErr = request.getOutErr(); + outErr.printErrLn("Build artifacts:"); + + NestedSet<Artifact> artifacts = artifactsBuilder.build(); + for (Artifact artifact : artifacts) { + if (!artifact.isSourceArtifact()) { + outErr.printErrLn(">>>" + artifact.getPath()); + } + } + } + + /** + * Returns a list of configured targets that should participate in printing. + * + * <p>Hidden rules and other inserted targets are ignored. + */ + private Collection<ConfiguredTarget> filterTargetsToPrint( + Collection<ConfiguredTarget> configuredTargets) { + ImmutableList.Builder<ConfiguredTarget> result = ImmutableList.builder(); + for (ConfiguredTarget target : configuredTargets) { + // TODO(bazel-team): this is quite ugly. Add a marker provider for this check. + if (target instanceof InputFileConfiguredTarget) { + // Suppress display of source files (because we do no work to build them). + continue; + } + if (target.getTarget() instanceof Rule) { + Rule rule = (Rule) target.getTarget(); + if (rule.getRuleClass().contains("$")) { + // Suppress display of hidden rules + continue; + } + } + if (target instanceof OutputFileConfiguredTarget) { + // Suppress display of generated files (because they appear underneath + // their generating rule), EXCEPT those ones which are not part of the + // filesToBuild of their generating rule (e.g. .par, _deploy.jar + // files), OR when a user explicitly requests an output file but not + // its rule. + TransitiveInfoCollection generatingRule = + env.getView().getGeneratingRule((OutputFileConfiguredTarget) target); + if (CollectionUtils.containsAll( + generatingRule.getProvider(FileProvider.class).getFilesToBuild(), + target.getProvider(FileProvider.class).getFilesToBuild()) + && configuredTargets.contains(generatingRule)) { + continue; + } + } + + result.add(target); + } + return result.build(); + } + + private Collection<AspectValue> filterAspectsToPrint(Collection<AspectValue> aspects) { + return aspects; + } +} |