aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java
diff options
context:
space:
mode:
authorGravatar janakr <janakr@google.com>2017-08-18 22:52:37 +0200
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2017-08-21 14:16:06 +0200
commitdc8b2e9a40770dde7638898bf3e3573eb51a79f8 (patch)
tree4ec53fe63861f5de8275953552aaabf3fd0b00a3 /src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java
parent8529746358ff5d88dc7ddf584a85ba0aa1a269a8 (diff)
Initial (partial) implementation of configured target query. Activated by passing the --post_build_query flag to a build command, with a query expression as the argument. Bazel then executes this query on the configured target graph as constructed by the build command.
Since the prepare graph -> query workflow is how SkyQueryEnvironment works, this is mostly just copying that. Main missing features/code cleanups: * Recursive target patterns (/...) are not supported. * There is no way to specify the configuration of the targets in your query. * Configuration output is totally opaque (just the hash, or null if no configuration). * More generally, no output options. * Some features (visibility, label attrs) not supported. * No edge filtering (host deps, implicit deps). * Aspects are totally ignored. * Graceful failure on errors, edge cases, incompatible flags (like the TAP flags that discard edges). * Code hygiene issues (calling test-only method to get to Skyframe graph, some code duplication across ConfiguredTargetQueryEnvironment and SkyQueryEnvironment). Most of the features I plan to leave to rules-side people, since I think they won't be too hard for a general Blaze developer to implement, and designing the right features and user interfaces for these things is better left to the rules side. PiperOrigin-RevId: 165747829
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java59
1 files changed, 58 insertions, 1 deletions
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 127b01d026..d04e23b097 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
@@ -56,13 +56,19 @@ import com.google.devtools.build.lib.pkgcache.LoadingPhaseRunner;
import com.google.devtools.build.lib.pkgcache.LoadingResult;
import com.google.devtools.build.lib.profiler.ProfilePhase;
import com.google.devtools.build.lib.profiler.Profiler;
+import com.google.devtools.build.lib.query2.ConfiguredTargetQueryEnvironment;
+import com.google.devtools.build.lib.query2.engine.QueryException;
+import com.google.devtools.build.lib.query2.engine.ThreadSafeOutputFormatterCallback;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
+import com.google.devtools.build.lib.skyframe.SkyframeExecutorWrappingWalkableGraph;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.util.RegexFilter;
+import com.google.devtools.build.skyframe.WalkableGraph;
import com.google.devtools.common.options.OptionsParsingException;
+import java.io.IOException;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -132,6 +138,7 @@ public final class BuildTool {
env.setupPackageCache(request, DefaultsPackage.getDefaultsPackageContent(buildOptions));
ExecutionTool executionTool = null;
+ BuildConfigurationCollection configurations;
boolean catastrophe = false;
try {
env.getEventBus().post(new BuildStartingEvent(env, request));
@@ -184,7 +191,7 @@ public final class BuildTool {
// TODO(gregce): BuildConfigurationCollection is important for static configs, less so for
// dynamic configs. Consider dropping it outright and passing on-the-fly target / host configs
// directly when needed (although this could be hard when Skyframe is unavailable).
- BuildConfigurationCollection configurations =
+ configurations =
env.getSkyframeExecutor()
.createConfigurations(
env.getReporter(),
@@ -218,6 +225,22 @@ public final class BuildTool {
"Target %s build was skipped.", target.getLabel())));
}
+ // TODO(janakr): this query will operate over the graph as constructed by analysis, but will
+ // also pick up any nodes that are in the graph from prior builds. This makes the results
+ // not reproducible at the level of a single command. Either tolerate, or wipe the analysis
+ // graph beforehand if this option is specified, or add another option to wipe if desired
+ // (SkyframeExecutor#dropConfiguredTargets should be sufficient).
+ if (request.getBuildOptions().queryExpression != null) {
+ try {
+ doConfiguredTargetQuery(request, configurations);
+ } catch (QueryException | IOException e) {
+ if (!request.getViewOptions().keepGoing) {
+ throw new ViewCreationFailedException("Error doing configured target query", e);
+ }
+ env.getReporter().error(null, "Error doing configured target query", e);
+ }
+ }
+
// Execution phase.
if (needsExecutionPhase(request.getBuildOptions())) {
executionTool.executeBuild(
@@ -368,6 +391,40 @@ public final class BuildTool {
return result;
}
+ private void doConfiguredTargetQuery(
+ BuildRequest request, BuildConfigurationCollection configurations)
+ throws InterruptedException, QueryException, IOException {
+ WalkableGraph walkableGraph =
+ SkyframeExecutorWrappingWalkableGraph.of(env.getSkyframeExecutor());
+ ConfiguredTargetQueryEnvironment configuredTargetQueryEnvironment =
+ new ConfiguredTargetQueryEnvironment(
+ request.getViewOptions().keepGoing,
+ env.getReporter(),
+ env.getRuntime().getQueryFunctions(),
+ configurations.getTargetConfigurations().get(0),
+ configurations.getHostConfiguration(),
+ env.newTargetPatternEvaluator().getOffset(),
+ env.getPackageManager().getPackagePath(),
+ () -> walkableGraph);
+ configuredTargetQueryEnvironment.evaluateQuery(
+ request.getBuildOptions().queryExpression,
+ new ThreadSafeOutputFormatterCallback<ConfiguredTarget>() {
+ @Override
+ public void processOutput(Iterable<ConfiguredTarget> partialResult)
+ throws IOException, InterruptedException {
+ for (ConfiguredTarget configuredTarget : partialResult) {
+ env.getReporter()
+ .getOutErr()
+ .printOutLn(
+ configuredTarget.getLabel()
+ + " ("
+ + configuredTarget.getConfiguration()
+ + ")");
+ }
+ }
+ });
+ }
+
private void maybeSetStopOnFirstFailure(BuildRequest request, BuildResult result) {
if (shouldStopOnFailure(request)) {
result.setStopOnFirstFailure(true);