aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2015-10-12 15:44:09 +0000
committerGravatar John Field <jfield@google.com>2015-10-13 01:01:03 +0000
commit3ca7b788dfbd5f323e9b6c58df3bdce4ced95d81 (patch)
tree381604334b7223f471990ed3f67746b06c043034 /src/main/java/com/google/devtools/build/lib/buildtool/BuildResultPrinter.java
parentaa8b1520c6c90ab9f0a489f996937fc6a355ca3c (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.java243
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;
+ }
+}