diff options
author | 2017-08-18 22:52:37 +0200 | |
---|---|---|
committer | 2017-08-21 14:16:06 +0200 | |
commit | dc8b2e9a40770dde7638898bf3e3573eb51a79f8 (patch) | |
tree | 4ec53fe63861f5de8275953552aaabf3fd0b00a3 /src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java | |
parent | 8529746358ff5d88dc7ddf584a85ba0aa1a269a8 (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.java | 59 |
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); |