aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/buildtool
diff options
context:
space:
mode:
authorGravatar twerth <twerth@google.com>2018-06-11 03:09:29 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-06-11 03:10:39 -0700
commit1a6c706d7b92d2529986c814cc1c9eac2dab9a1c (patch)
tree957c7ec1365070801171ec3449b8e4ff62e98292 /src/main/java/com/google/devtools/build/lib/buildtool
parent4022bac855a790b3a42fcb44c06f62dbbe078c5a (diff)
Introduce generic post analysis build tool.
This is the first step on the way to a proper action graph query command. RELNOTES: None PiperOrigin-RevId: 200026440
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/buildtool')
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java15
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildtool/CqueryBuildTool.java139
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildtool/PostAnalysisQueryBuildTool.java165
3 files changed, 185 insertions, 134 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 407f2f63a1..755ea82151 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
@@ -39,7 +39,7 @@ import com.google.devtools.build.lib.analysis.config.InvalidConfigurationExcepti
import com.google.devtools.build.lib.buildeventstream.AbortedEvent;
import com.google.devtools.build.lib.buildeventstream.BuildEventId;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.Aborted.AbortReason;
-import com.google.devtools.build.lib.buildtool.CqueryBuildTool.ConfiguredTargetQueryCommandLineException;
+import com.google.devtools.build.lib.buildtool.PostAnalysisQueryBuildTool.PostAnalysisQueryCommandLineException;
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;
@@ -131,14 +131,10 @@ public class BuildTool {
* @param result the build result that is the mutable result of this build
* @param validator target validator
*/
- public void buildTargets(
- BuildRequest request,
- BuildResult result,
- TargetValidator validator)
+ public void buildTargets(BuildRequest request, BuildResult result, TargetValidator validator)
throws BuildFailedException, InterruptedException, ViewCreationFailedException,
TargetParsingException, LoadingFailedException, AbruptExitException,
- InvalidConfigurationException, TestExecException,
- ConfiguredTargetQueryCommandLineException {
+ InvalidConfigurationException, TestExecException, PostAnalysisQueryCommandLineException {
validateOptions(request);
BuildOptions buildOptions = runtime.createBuildOptions(request);
// Sync the package manager before sending the BuildStartingEvent in runLoadingPhase()
@@ -311,8 +307,7 @@ public class BuildTool {
AnalysisResult analysisResult,
BuildConfigurationCollection configurations)
throws InterruptedException, ViewCreationFailedException,
- ConfiguredTargetQueryCommandLineException {
- }
+ PostAnalysisQueryCommandLineException {}
private void reportExceptionError(Exception e) {
if (e.getMessage() != null) {
@@ -376,7 +371,7 @@ public class BuildTool {
} catch (TargetParsingException | LoadingFailedException | ViewCreationFailedException e) {
exitCode = ExitCode.PARSING_FAILURE;
reportExceptionError(e);
- } catch (ConfiguredTargetQueryCommandLineException e) {
+ } catch (PostAnalysisQueryCommandLineException e) {
exitCode = ExitCode.COMMAND_LINE_ERROR;
reportExceptionError(e);
} catch (TestExecException e) {
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/CqueryBuildTool.java b/src/main/java/com/google/devtools/build/lib/buildtool/CqueryBuildTool.java
index 46ed57cd4f..2bdd2b7750 100644
--- a/src/main/java/com/google/devtools/build/lib/buildtool/CqueryBuildTool.java
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/CqueryBuildTool.java
@@ -14,151 +14,42 @@
package com.google.devtools.build.lib.buildtool;
import com.google.common.collect.ImmutableList;
-import com.google.devtools.build.lib.analysis.BuildView.AnalysisResult;
-import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
-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.events.Event;
import com.google.devtools.build.lib.query2.ConfiguredTargetQueryEnvironment;
-import com.google.devtools.build.lib.query2.CqueryThreadsafeCallback;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunction;
-import com.google.devtools.build.lib.query2.engine.QueryEvalResult;
-import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.query2.engine.QueryExpression;
-import com.google.devtools.build.lib.query2.engine.TargetLiteral;
import com.google.devtools.build.lib.query2.output.CqueryOptions;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
-import com.google.devtools.build.lib.skyframe.SkyframeExecutorWrappingWalkableGraph;
import com.google.devtools.build.skyframe.WalkableGraph;
-import java.io.IOException;
-import java.util.List;
-import java.util.stream.Collectors;
/** A version of {@link BuildTool} that handles all cquery work. */
-public class CqueryBuildTool extends BuildTool {
-
- private final QueryExpression queryExpression;
+public class CqueryBuildTool extends PostAnalysisQueryBuildTool {
public CqueryBuildTool(CommandEnvironment env, QueryExpression queryExpression) {
- super(env);
- this.queryExpression = queryExpression;
+ super(env, queryExpression);
}
@Override
- protected void postProcessAnalysisResult(
- BuildRequest request,
- AnalysisResult analysisResult,
- BuildConfigurationCollection configurations)
- throws InterruptedException, ViewCreationFailedException,
- ConfiguredTargetQueryCommandLineException {
- // TODO: b/71905538 - 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#handleConfiguredTargetChange should be sufficient).
- if (queryExpression != null) {
- if (!env.getSkyframeExecutor().tracksStateForIncrementality()) {
- throw new ConfiguredTargetQueryCommandLineException(
- "Configured query is not allowed if incrementality state is not being kept");
- }
- try {
- doConfiguredTargetQuery(
- request,
- configurations.getHostConfiguration(),
- analysisResult.getTopLevelTargetsWithConfigs(),
- queryExpression);
- } catch (QueryException | IOException e) {
- if (!request.getKeepGoing()) {
- throw new ViewCreationFailedException("Error doing configured target query", e);
- }
- env.getReporter().error(null, "Error doing configured target query", e);
- }
- }
- }
-
- private void doConfiguredTargetQuery(
+ protected ConfiguredTargetQueryEnvironment getQueryEnvironment(
BuildRequest request,
BuildConfiguration hostConfiguration,
- List<TargetAndConfiguration> topLevelTargetsWithConfigs,
- QueryExpression queryExpression)
- throws InterruptedException, QueryException, IOException {
-
- // Currently, CTQE assumes that all top level targets take on the same default config and we
- // don't have the ability to map multiple configs to multiple top level targets.
- // So for now, we only allow multiple targets when they all carry the same config.
- // TODO: b/71508373 - fully support multiple top level targets
- List<TargetAndConfiguration> nonNullTargets =
- topLevelTargetsWithConfigs
- .stream()
- .filter(targetAndConfig -> targetAndConfig.getConfiguration() != null)
- .collect(Collectors.toList());
- BuildConfiguration targetConfig = null;
- if (!nonNullTargets.isEmpty()) {
- targetConfig = nonNullTargets.get(0).getConfiguration();
- for (TargetAndConfiguration targAndConfig : topLevelTargetsWithConfigs) {
- if (targAndConfig.getConfiguration() != null
- && !targAndConfig.getConfiguration().equals(targetConfig)) {
- throw new QueryException(
- new TargetLiteral(queryExpression.toString()),
- String.format(
- "Top-level targets %s and %s have different configurations (top-level "
- + "targets with different configurations is not supported)",
- nonNullTargets.get(0).getLabel(), targAndConfig.getLabel()));
- }
- }
- }
- WalkableGraph walkableGraph =
- SkyframeExecutorWrappingWalkableGraph.of(env.getSkyframeExecutor());
+ BuildConfiguration targetConfig,
+ WalkableGraph walkableGraph) {
ImmutableList<QueryFunction> extraFunctions =
new ImmutableList.Builder<QueryFunction>()
.addAll(ConfiguredTargetQueryEnvironment.CQUERY_FUNCTIONS)
.addAll(env.getRuntime().getQueryFunctions())
.build();
CqueryOptions cqueryOptions = request.getOptions(CqueryOptions.class);
- ConfiguredTargetQueryEnvironment configuredTargetQueryEnvironment =
- new ConfiguredTargetQueryEnvironment(
- request.getKeepGoing(),
- env.getReporter(),
- extraFunctions,
- targetConfig,
- hostConfiguration,
- env.newTargetPatternEvaluator().getOffset(),
- env.getPackageManager().getPackagePath(),
- () -> walkableGraph,
- cqueryOptions.toSettings());
- Iterable<CqueryThreadsafeCallback> callbacks =
- configuredTargetQueryEnvironment.getDefaultOutputFormatters(
- configuredTargetQueryEnvironment.getAccessor(),
- cqueryOptions,
- env.getReporter(),
- env.getSkyframeExecutor(),
- hostConfiguration,
- runtime.getRuleClassProvider().getTrimmingTransitionFactory(),
- cqueryOptions.aspectDeps.createResolver(env.getPackageManager(), env.getReporter()));
- CqueryThreadsafeCallback callback =
- CqueryThreadsafeCallback.getCallback(cqueryOptions.outputFormat, callbacks);
- if (callback == null) {
- env.getReporter()
- .handle(
- Event.error(
- String.format(
- "Invalid output format '%s'. Valid values are: %s",
- cqueryOptions.outputFormat,
- CqueryThreadsafeCallback.callbackNames(callbacks))));
- return;
- }
- QueryEvalResult result =
- configuredTargetQueryEnvironment.evaluateQuery(queryExpression, callback);
- if (result.isEmpty()) {
- env.getReporter().handle(Event.info("Empty query results"));
- }
- }
-
- /** Cquery specific command line exception. */
- protected static class ConfiguredTargetQueryCommandLineException extends Exception {
- ConfiguredTargetQueryCommandLineException(String message) {
- super(message);
- }
+ return new ConfiguredTargetQueryEnvironment(
+ request.getKeepGoing(),
+ env.getReporter(),
+ extraFunctions,
+ targetConfig,
+ hostConfiguration,
+ env.newTargetPatternEvaluator().getOffset(),
+ env.getPackageManager().getPackagePath(),
+ () -> walkableGraph,
+ cqueryOptions);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/PostAnalysisQueryBuildTool.java b/src/main/java/com/google/devtools/build/lib/buildtool/PostAnalysisQueryBuildTool.java
new file mode 100644
index 0000000000..df5205eb70
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/PostAnalysisQueryBuildTool.java
@@ -0,0 +1,165 @@
+// Copyright 2018 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.devtools.build.lib.analysis.BuildView.AnalysisResult;
+import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
+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.events.Event;
+import com.google.devtools.build.lib.query2.ConfiguredTargetQueryEnvironment;
+import com.google.devtools.build.lib.query2.CqueryThreadsafeCallback;
+import com.google.devtools.build.lib.query2.engine.QueryEvalResult;
+import com.google.devtools.build.lib.query2.engine.QueryException;
+import com.google.devtools.build.lib.query2.engine.QueryExpression;
+import com.google.devtools.build.lib.query2.engine.TargetLiteral;
+import com.google.devtools.build.lib.runtime.CommandEnvironment;
+import com.google.devtools.build.lib.skyframe.SkyframeExecutorWrappingWalkableGraph;
+import com.google.devtools.build.skyframe.WalkableGraph;
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Version of {@link BuildTool} that handles all work for queries based on results from the analysis
+ * phase.
+ */
+public abstract class PostAnalysisQueryBuildTool extends BuildTool {
+
+ private final QueryExpression queryExpression;
+
+ public PostAnalysisQueryBuildTool(CommandEnvironment env, QueryExpression queryExpression) {
+ super(env);
+ this.queryExpression = queryExpression;
+ }
+
+ @Override
+ protected void postProcessAnalysisResult(
+ BuildRequest request,
+ AnalysisResult analysisResult,
+ BuildConfigurationCollection configurations)
+ throws InterruptedException, ViewCreationFailedException,
+ PostAnalysisQueryCommandLineException {
+ // TODO: b/71905538 - 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#handleConfiguredTargetChange should be sufficient).
+ if (queryExpression != null) {
+ if (!env.getSkyframeExecutor().tracksStateForIncrementality()) {
+ throw new PostAnalysisQueryCommandLineException(
+ "Queries based on analysis results are not allowed "
+ + "if incrementality state is not being kept");
+ }
+ try {
+ doPostAnalysisQuery(
+ request,
+ configurations.getHostConfiguration(),
+ analysisResult.getTopLevelTargetsWithConfigs(),
+ queryExpression);
+ } catch (QueryException | IOException e) {
+ if (!request.getKeepGoing()) {
+ throw new ViewCreationFailedException("Error doing post analysis query", e);
+ }
+ env.getReporter().error(null, "Error doing post analysis query", e);
+ }
+ }
+ }
+
+ // TODO(twerth): Make this more generic when introducting a PostAnalysisQueryEnvironment.
+ protected abstract ConfiguredTargetQueryEnvironment getQueryEnvironment(
+ BuildRequest request,
+ BuildConfiguration hostConfiguration,
+ BuildConfiguration targetConfig,
+ WalkableGraph walkableGraph);
+
+ private BuildConfiguration getBuildConfiguration(
+ List<TargetAndConfiguration> topLevelTargetsWithConfigs, QueryExpression queryExpression)
+ throws QueryException {
+ // Currently, CTQE assumes that all top level targets take on the same default config and we
+ // don't have the ability to map multiple configs to multiple top level targets.
+ // So for now, we only allow multiple targets when they all carry the same config.
+ // TODO: b/71508373 - fully support multiple top level targets
+ List<TargetAndConfiguration> nonNullTargets =
+ topLevelTargetsWithConfigs
+ .stream()
+ .filter(targetAndConfig -> targetAndConfig.getConfiguration() != null)
+ .collect(Collectors.toList());
+ BuildConfiguration targetConfig = null;
+ if (!nonNullTargets.isEmpty()) {
+ targetConfig = nonNullTargets.get(0).getConfiguration();
+ for (TargetAndConfiguration targAndConfig : topLevelTargetsWithConfigs) {
+ if (targAndConfig.getConfiguration() != null
+ && !targAndConfig.getConfiguration().equals(targetConfig)) {
+ throw new QueryException(
+ new TargetLiteral(queryExpression.toString()),
+ String.format(
+ "Top-level targets %s and %s have different configurations (top-level "
+ + "targets with different configurations is not supported)",
+ nonNullTargets.get(0).getLabel(), targAndConfig.getLabel()));
+ }
+ }
+ }
+ return targetConfig;
+ }
+
+ private void doPostAnalysisQuery(
+ BuildRequest request,
+ BuildConfiguration hostConfiguration,
+ List<TargetAndConfiguration> topLevelTargetsWithConfigs,
+ QueryExpression queryExpression)
+ throws InterruptedException, QueryException, IOException {
+ BuildConfiguration targetConfig =
+ getBuildConfiguration(topLevelTargetsWithConfigs, queryExpression);
+
+ WalkableGraph walkableGraph =
+ SkyframeExecutorWrappingWalkableGraph.of(env.getSkyframeExecutor());
+
+ ConfiguredTargetQueryEnvironment configuredTargetQueryEnvironment =
+ getQueryEnvironment(request, hostConfiguration, targetConfig, walkableGraph);
+ Iterable<CqueryThreadsafeCallback> callbacks =
+ configuredTargetQueryEnvironment.getDefaultOutputFormatters(
+ configuredTargetQueryEnvironment.getAccessor(),
+ env.getReporter(),
+ env.getSkyframeExecutor(),
+ hostConfiguration,
+ runtime.getRuleClassProvider().getTrimmingTransitionFactory(),
+ env.getPackageManager());
+ String outputFormat = configuredTargetQueryEnvironment.getOutputFormat();
+ CqueryThreadsafeCallback callback =
+ CqueryThreadsafeCallback.getCallback(outputFormat, callbacks);
+ if (callback == null) {
+ env.getReporter()
+ .handle(
+ Event.error(
+ String.format(
+ "Invalid output format '%s'. Valid values are: %s",
+ outputFormat, CqueryThreadsafeCallback.callbackNames(callbacks))));
+ return;
+ }
+ QueryEvalResult result =
+ configuredTargetQueryEnvironment.evaluateQuery(queryExpression, callback);
+ if (result.isEmpty()) {
+ env.getReporter().handle(Event.info("Empty query results"));
+ }
+ }
+
+ /** Post analysis query specific command line exception. */
+ protected static class PostAnalysisQueryCommandLineException extends Exception {
+ PostAnalysisQueryCommandLineException(String message) {
+ super(message);
+ }
+ }
+}