aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main
diff options
context:
space:
mode:
authorGravatar juliexxia <juliexxia@google.com>2018-03-07 12:01:30 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-03-07 12:03:12 -0800
commite2cf7aa47e3b0504a85fd5e5fc8586f923777aaf (patch)
tree9c8a16b99504b805c20c40bb5d4a03a1e76825d4 /src/main
parent5d446a7b8f784e9fc41e82a1b1fa941fe52cea31 (diff)
Create a new version of BuildTool that holds all cquery logic.
PiperOrigin-RevId: 188212286
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java170
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildtool/CqueryBuildTool.java161
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/CqueryCommand.java5
3 files changed, 187 insertions, 149 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 c793faf1d6..6f25f38185 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
@@ -29,7 +29,6 @@ import com.google.devtools.build.lib.analysis.LicensesProvider;
import com.google.devtools.build.lib.analysis.LicensesProvider.TargetLicense;
import com.google.devtools.build.lib.analysis.MakeEnvironmentEvent;
import com.google.devtools.build.lib.analysis.StaticallyLinkedMarkerProvider;
-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;
@@ -39,6 +38,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.buildevent.BuildCompleteEvent;
import com.google.devtools.build.lib.buildtool.buildevent.BuildInterruptedEvent;
import com.google.devtools.build.lib.buildtool.buildevent.BuildStartingEvent;
@@ -64,30 +64,17 @@ 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.CommonQueryOptions;
-import com.google.devtools.build.lib.query2.ConfiguredTargetQueryEnvironment;
-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.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.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.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import java.util.regex.Pattern;
-import java.util.stream.Collectors;
/**
* Provides the bulk of the implementation of the 'blaze build' command.
@@ -99,12 +86,12 @@ import java.util.stream.Collectors;
*
* <p>Most of analysis is handled in {@link BuildView}, and execution in {@link ExecutionTool}.
*/
-public final class BuildTool {
+public class BuildTool {
- private static final Logger logger = Logger.getLogger(BuildTool.class.getName());
+ private static Logger logger = Logger.getLogger(BuildTool.class.getName());
- private final CommandEnvironment env;
- private final BlazeRuntime runtime;
+ protected CommandEnvironment env;
+ protected BlazeRuntime runtime;
/**
* Constructs a BuildTool.
@@ -116,21 +103,12 @@ public final class BuildTool {
this.runtime = env.getRuntime();
}
- public void buildTargets(BuildRequest request, BuildResult result, TargetValidator validator)
- throws BuildFailedException, InterruptedException, ViewCreationFailedException,
- TargetParsingException, LoadingFailedException, AbruptExitException,
- InvalidConfigurationException, TestExecException,
- ConfiguredTargetQueryCommandLineException {
- buildTargets(request, result, validator, null);
- }
-
/**
* The crux of the build system. Builds the targets specified in the request using the specified
* Executor.
*
* <p>Performs loading, analysis and execution for the specified set of targets, honoring the
- * configuration options in the BuildRequest. Also performs a query on results of analysis phase
- * if a query expression is specified. Returns normally iff successful, throws an exception
+ * configuration options in the BuildRequest. Returns normally iff successful, throws an exception
* otherwise.
*
* <p>Callers must ensure that {@link #stopRequest} is called after this method, even if it
@@ -146,14 +124,11 @@ public final class BuildTool {
* the request object are populated
* @param result the build result that is the mutable result of this build
* @param validator target validator
- * @param queryExpression if a query is to run after building targets, this will be the query
- * expression. If not, this will be null.
*/
public void buildTargets(
BuildRequest request,
BuildResult result,
- TargetValidator validator,
- QueryExpression queryExpression)
+ TargetValidator validator)
throws BuildFailedException, InterruptedException, ViewCreationFailedException,
TargetParsingException, LoadingFailedException, AbruptExitException,
InvalidConfigurationException, TestExecException,
@@ -251,31 +226,7 @@ public final class BuildTool {
AbortReason.SKIPPED,
String.format("Target %s build was skipped.", label), label));
}
-
- // 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#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);
- }
- }
-
+ postProcessAnalysisResult(request, analysisResult, configurations);
// Execution phase.
if (needsExecutionPhase(request.getBuildOptions())) {
executionTool.executeBuild(
@@ -343,23 +294,30 @@ public final class BuildTool {
}
}
+ /**
+ * This class is meant to be overridden by classes that want to perform the Analysis phase and
+ * then process the results in some interesting way. See {@link CqueryBuildTool} as an example.
+ */
+ protected void postProcessAnalysisResult(
+ BuildRequest request,
+ AnalysisResult analysisResult,
+ BuildConfigurationCollection configurations)
+ throws InterruptedException, ViewCreationFailedException,
+ ConfiguredTargetQueryCommandLineException {
+ }
+
private void reportExceptionError(Exception e) {
if (e.getMessage() != null) {
getReporter().handle(Event.error(e.getMessage()));
}
}
- public BuildResult processRequest(BuildRequest request, TargetValidator validator) {
- return processRequest(request, validator, null);
- }
-
/**
* The crux of the build system. Builds the targets specified in the request using the specified
* Executor.
*
* <p>Performs loading, analysis and execution for the specified set of targets, honoring the
- * configuration options in the BuildRequest. Also performs a query on results of analysis phase
- * if a query expression is specified. Returns normally iff successful, throws an exception
+ * configuration options in the BuildRequest. Returns normally iff successful, throws an exception
* otherwise.
*
* <p>The caller is responsible for setting up and syncing the package cache.
@@ -371,19 +329,17 @@ public final class BuildTool {
* options; during this method's execution, the actualTargets and successfulTargets fields
* of the request object are populated
* @param validator target validator
- * @param queryExpression if a query is to run after building targets, this will be the query
- * expression. If not, this will be null.
* @return the result as a {@link BuildResult} object
*/
public BuildResult processRequest(
- BuildRequest request, TargetValidator validator, QueryExpression queryExpression) {
+ BuildRequest request, TargetValidator validator) {
BuildResult result = new BuildResult(request.getStartTime());
env.getEventBus().register(result);
maybeSetStopOnFirstFailure(request, result);
Throwable catastrophe = null;
ExitCode exitCode = ExitCode.BLAZE_INTERNAL_ERROR;
try {
- buildTargets(request, result, validator, queryExpression);
+ buildTargets(request, result, validator);
exitCode = ExitCode.SUCCESS;
} catch (BuildFailedException e) {
if (e.isErrorAlreadyShown()) {
@@ -442,80 +398,6 @@ public final class BuildTool {
return result;
}
- private void doConfiguredTargetQuery(
- 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());
- ImmutableList<QueryFunction> extraFunctions =
- new ImmutableList.Builder<QueryFunction>()
- .addAll(ConfiguredTargetQueryEnvironment.CQUERY_FUNCTIONS)
- .addAll(env.getRuntime().getQueryFunctions())
- .build();
- ConfiguredTargetQueryEnvironment configuredTargetQueryEnvironment =
- new ConfiguredTargetQueryEnvironment(
- request.getKeepGoing(),
- env.getReporter(),
- extraFunctions,
- targetConfig,
- hostConfiguration,
- env.newTargetPatternEvaluator().getOffset(),
- env.getPackageManager().getPackagePath(),
- () -> walkableGraph,
- request.getOptions(CommonQueryOptions.class).toSettings());
- QueryEvalResult result =
- configuredTargetQueryEnvironment.evaluateQuery(
- queryExpression,
- new ThreadSafeOutputFormatterCallback<ConfiguredTarget>() {
- @Override
- public void processOutput(Iterable<ConfiguredTarget> partialResult)
- throws IOException, InterruptedException {
- for (ConfiguredTarget configuredTarget : partialResult) {
- BuildConfiguration config = configuredTarget.getConfiguration();
- StringBuilder output =
- new StringBuilder()
- .append(configuredTarget.getLabel())
- .append(" (")
- .append(config != null && config.isHostConfiguration() ? "HOST" : config)
- .append(")");
- env.getReporter().getOutErr().printOutLn(output.toString());
- }
- }
- });
- if (result.isEmpty()) {
- env.getReporter().handle(Event.info("Empty query results"));
- }
- }
-
private void maybeSetStopOnFirstFailure(BuildRequest request, BuildResult result) {
if (shouldStopOnFailure(request)) {
result.setStopOnFirstFailure(true);
@@ -745,10 +627,4 @@ public final class BuildTool {
private Reporter getReporter() {
return env.getReporter();
}
-
- private static class ConfiguredTargetQueryCommandLineException extends Exception {
- ConfiguredTargetQueryCommandLineException(String message) {
- super(message);
- }
- }
}
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
new file mode 100644
index 0000000000..f129278275
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/CqueryBuildTool.java
@@ -0,0 +1,161 @@
+// 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.common.collect.ImmutableList;
+import com.google.devtools.build.lib.analysis.BuildView.AnalysisResult;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+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.CommonQueryOptions;
+import com.google.devtools.build.lib.query2.ConfiguredTargetQueryEnvironment;
+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.engine.ThreadSafeOutputFormatterCallback;
+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 CqueryBuildTool(CommandEnvironment env, QueryExpression queryExpression) {
+ super(env);
+ this.queryExpression = 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(
+ 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());
+ ImmutableList<QueryFunction> extraFunctions =
+ new ImmutableList.Builder<QueryFunction>()
+ .addAll(ConfiguredTargetQueryEnvironment.CQUERY_FUNCTIONS)
+ .addAll(env.getRuntime().getQueryFunctions())
+ .build();
+ ConfiguredTargetQueryEnvironment configuredTargetQueryEnvironment =
+ new ConfiguredTargetQueryEnvironment(
+ request.getKeepGoing(),
+ env.getReporter(),
+ extraFunctions,
+ targetConfig,
+ hostConfiguration,
+ env.newTargetPatternEvaluator().getOffset(),
+ env.getPackageManager().getPackagePath(),
+ () -> walkableGraph,
+ request.getOptions(CommonQueryOptions.class).toSettings());
+ QueryEvalResult result =
+ configuredTargetQueryEnvironment.evaluateQuery(
+ queryExpression,
+ new ThreadSafeOutputFormatterCallback<ConfiguredTarget>() {
+ @Override
+ public void processOutput(Iterable<ConfiguredTarget> partialResult)
+ throws IOException, InterruptedException {
+ for (ConfiguredTarget configuredTarget : partialResult) {
+ BuildConfiguration config = configuredTarget.getConfiguration();
+ StringBuilder output =
+ new StringBuilder()
+ .append(configuredTarget.getLabel())
+ .append(" (")
+ .append(config != null && config.isHostConfiguration() ? "HOST" : config)
+ .append(")");
+ env.getReporter().getOutErr().printOutLn(output.toString());
+ }
+ }
+ });
+ 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);
+ }
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/CqueryCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/CqueryCommand.java
index 0ec5b8a4b0..6a80e0849e 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/CqueryCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/CqueryCommand.java
@@ -16,7 +16,7 @@ package com.google.devtools.build.lib.runtime.commands;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.buildtool.BuildRequest;
-import com.google.devtools.build.lib.buildtool.BuildTool;
+import com.google.devtools.build.lib.buildtool.CqueryBuildTool;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.query2.CommonQueryOptions;
import com.google.devtools.build.lib.query2.ConfiguredTargetQueryEnvironment;
@@ -108,7 +108,8 @@ public final class CqueryCommand implements BlazeCommand {
env.getReporter().getOutErr(),
env.getCommandId(),
env.getCommandStartTime());
- ExitCode exitCode = new BuildTool(env).processRequest(request, null, expr).getExitCondition();
+ ExitCode exitCode =
+ new CqueryBuildTool(env, expr).processRequest(request, null).getExitCondition();
return BlazeCommandResult.exitCode(exitCode);
}
}