aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com
diff options
context:
space:
mode:
authorGravatar twerth <twerth@google.com>2018-07-18 05:34:13 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-07-18 05:35:53 -0700
commita1a57a519d49fcbda35f3df0e68e04ba09db3362 (patch)
treefa5b002a09bed482b892bf02fba63df0e4578a20 /src/main/java/com
parent47819a99f2bb10429315ad181811f4359103d6d5 (diff)
Add aquery as proper command to Bazel.
RELNOTES: Add aquery command to get analysis time information about the action graph. PiperOrigin-RevId: 205064145
Diffstat (limited to 'src/main/java/com')
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildtool/AqueryBuildTool.java57
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/ActionGraphProtoOutputFormatterCallback.java73
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/ActionGraphQueryEnvironment.java291
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/AqueryThreadsafeCallback.java45
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/ConfiguredTargetQueryEnvironment.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/PostAnalysisQueryEnvironment.java23
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/output/AqueryOptions.java30
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/BuiltinCommandModule.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/AqueryCommand.java121
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/aquery.txt8
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/ActionGraphDump.java5
11 files changed, 656 insertions, 9 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/AqueryBuildTool.java b/src/main/java/com/google/devtools/build/lib/buildtool/AqueryBuildTool.java
new file mode 100644
index 0000000000..ef6721b43f
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/AqueryBuildTool.java
@@ -0,0 +1,57 @@
+// 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.config.BuildConfiguration;
+import com.google.devtools.build.lib.query2.ActionGraphQueryEnvironment;
+import com.google.devtools.build.lib.query2.PostAnalysisQueryEnvironment;
+import com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunction;
+import com.google.devtools.build.lib.query2.engine.QueryExpression;
+import com.google.devtools.build.lib.query2.output.AqueryOptions;
+import com.google.devtools.build.lib.runtime.CommandEnvironment;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetValue;
+import com.google.devtools.build.skyframe.WalkableGraph;
+
+/** A version of {@link BuildTool} that handles all aquery work. */
+public class AqueryBuildTool extends PostAnalysisQueryBuildTool<ConfiguredTargetValue> {
+
+ public AqueryBuildTool(CommandEnvironment env, QueryExpression queryExpression) {
+ super(env, queryExpression);
+ }
+
+ @Override
+ protected PostAnalysisQueryEnvironment<ConfiguredTargetValue> getQueryEnvironment(
+ BuildRequest request,
+ BuildConfiguration hostConfiguration,
+ BuildConfiguration targetConfig,
+ WalkableGraph walkableGraph) {
+ ImmutableList<QueryFunction> extraFunctions =
+ new ImmutableList.Builder<QueryFunction>()
+ .addAll(ActionGraphQueryEnvironment.AQUERY_FUNCTIONS)
+ .addAll(env.getRuntime().getQueryFunctions())
+ .build();
+ AqueryOptions aqueryOptions = request.getOptions(AqueryOptions.class);
+ return new ActionGraphQueryEnvironment(
+ request.getKeepGoing(),
+ env.getReporter(),
+ extraFunctions,
+ targetConfig,
+ hostConfiguration,
+ env.getRelativeWorkingDirectory().getPathString(),
+ env.getPackageManager().getPackagePath(),
+ () -> walkableGraph,
+ aqueryOptions);
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/query2/ActionGraphProtoOutputFormatterCallback.java b/src/main/java/com/google/devtools/build/lib/query2/ActionGraphProtoOutputFormatterCallback.java
new file mode 100644
index 0000000000..d18ee1852d
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/query2/ActionGraphProtoOutputFormatterCallback.java
@@ -0,0 +1,73 @@
+// 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.query2;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.devtools.build.lib.actions.CommandLineExpansionException;
+import com.google.devtools.build.lib.analysis.AnalysisProtos;
+import com.google.devtools.build.lib.analysis.AnalysisProtos.ActionGraphContainer;
+import com.google.devtools.build.lib.events.Reporter;
+import com.google.devtools.build.lib.query2.engine.QueryEnvironment.TargetAccessor;
+import com.google.devtools.build.lib.query2.output.AqueryOptions;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetValue;
+import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
+import com.google.devtools.build.lib.skyframe.actiongraph.ActionGraphDump;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/** Default output callback for aquery, prints proto output. */
+public class ActionGraphProtoOutputFormatterCallback extends AqueryThreadsafeCallback {
+
+ final ActionGraphDump actionGraphDump;
+
+ ActionGraphProtoOutputFormatterCallback(
+ Reporter reporter,
+ AqueryOptions options,
+ OutputStream out,
+ SkyframeExecutor skyframeExecutor,
+ TargetAccessor<ConfiguredTargetValue> accessor) {
+ super(reporter, options, out, skyframeExecutor, accessor);
+ // TODO(twerth): Allow users to include action command lines.
+ actionGraphDump = new ActionGraphDump(/* includeActionCmdLine */ false);
+ }
+
+ @Override
+ public String getName() {
+ return "proto";
+ }
+
+ @Override
+ public void processOutput(Iterable<ConfiguredTargetValue> partialResult) throws IOException {
+ try {
+ for (ConfiguredTargetValue configuredTargetValue : partialResult) {
+ actionGraphDump.dumpConfiguredTarget(configuredTargetValue);
+ }
+ } catch (CommandLineExpansionException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ @Override
+ public void close(boolean failFast) throws IOException {
+ if (!failFast && printStream != null) {
+ ActionGraphContainer actionGraphContainer = actionGraphDump.build();
+ actionGraphContainer.writeTo(printStream);
+ }
+ }
+
+ @VisibleForTesting
+ public AnalysisProtos.ActionGraphContainer getProtoResult() {
+ return actionGraphDump.build();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/query2/ActionGraphQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/ActionGraphQueryEnvironment.java
new file mode 100644
index 0000000000..e3dd353a0b
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/query2/ActionGraphQueryEnvironment.java
@@ -0,0 +1,291 @@
+// 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.query2;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.TargetParsingException;
+import com.google.devtools.build.lib.cmdline.TargetPattern;
+import com.google.devtools.build.lib.events.ExtendedEventHandler;
+import com.google.devtools.build.lib.events.Reporter;
+import com.google.devtools.build.lib.packages.RuleTransitionFactory;
+import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.pkgcache.PackageManager;
+import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
+import com.google.devtools.build.lib.query2.engine.Callback;
+import com.google.devtools.build.lib.query2.engine.KeyExtractor;
+import com.google.devtools.build.lib.query2.engine.QueryEnvironment;
+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.QueryUtil.ThreadSafeMutableKeyExtractorBackedSetImpl;
+import com.google.devtools.build.lib.query2.output.AqueryOptions;
+import com.google.devtools.build.lib.rules.AliasConfiguredTarget;
+import com.google.devtools.build.lib.skyframe.BuildConfigurationValue;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetValue;
+import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
+import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.WalkableGraph;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Supplier;
+import javax.annotation.Nullable;
+
+/**
+ * {@link QueryEnvironment} that is specialized for running action graph queries over the configured
+ * target graph.
+ */
+public class ActionGraphQueryEnvironment
+ extends PostAnalysisQueryEnvironment<ConfiguredTargetValue> {
+
+ public static final ImmutableList<QueryFunction> AQUERY_FUNCTIONS = ImmutableList.of();
+ public static final ImmutableList<QueryFunction> FUNCTIONS = populateFunctions();
+ AqueryOptions aqueryOptions;
+ private final KeyExtractor<ConfiguredTargetValue, ConfiguredTargetKey>
+ configuredTargetKeyExtractor;
+
+ public ActionGraphQueryEnvironment(
+ boolean keepGoing,
+ ExtendedEventHandler eventHandler,
+ Iterable<QueryFunction> extraFunctions,
+ BuildConfiguration defaultTargetConfiguration,
+ BuildConfiguration hostConfiguration,
+ String parserPrefix,
+ PathPackageLocator pkgPath,
+ Supplier<WalkableGraph> walkableGraphSupplier,
+ Set<Setting> settings) {
+ super(
+ keepGoing,
+ eventHandler,
+ extraFunctions,
+ defaultTargetConfiguration,
+ hostConfiguration,
+ parserPrefix,
+ pkgPath,
+ walkableGraphSupplier,
+ settings,
+ new ConfiguredTargetValueAccessor(walkableGraphSupplier.get()));
+ this.configuredTargetKeyExtractor =
+ configuredTargetValue -> {
+ try {
+ ConfiguredTarget element = configuredTargetValue.getConfiguredTarget();
+ return ConfiguredTargetKey.of(
+ element,
+ element.getConfigurationKey() == null
+ ? null
+ : ((BuildConfigurationValue) graph.getValue(element.getConfigurationKey()))
+ .getConfiguration());
+ } catch (InterruptedException e) {
+ throw new IllegalStateException("Interruption unexpected in configured query");
+ }
+ };
+ }
+
+ public ActionGraphQueryEnvironment(
+ boolean keepGoing,
+ ExtendedEventHandler eventHandler,
+ Iterable<QueryFunction> extraFunctions,
+ BuildConfiguration defaultTargetConfiguration,
+ BuildConfiguration hostConfiguration,
+ String parserPrefix,
+ PathPackageLocator pkgPath,
+ Supplier<WalkableGraph> walkableGraphSupplier,
+ AqueryOptions aqueryOptions) {
+ this(
+ keepGoing,
+ eventHandler,
+ extraFunctions,
+ defaultTargetConfiguration,
+ hostConfiguration,
+ parserPrefix,
+ pkgPath,
+ walkableGraphSupplier,
+ aqueryOptions.toSettings());
+ this.aqueryOptions = aqueryOptions;
+ }
+
+ private static ImmutableList<QueryFunction> populateFunctions() {
+ return ImmutableList.copyOf(QueryEnvironment.DEFAULT_QUERY_FUNCTIONS);
+ }
+
+ @Override
+ public ImmutableList<NamedThreadSafeOutputFormatterCallback<ConfiguredTargetValue>>
+ getDefaultOutputFormatters(
+ TargetAccessor<ConfiguredTargetValue> accessor,
+ Reporter reporter,
+ SkyframeExecutor skyframeExecutor,
+ BuildConfiguration hostConfiguration,
+ @Nullable RuleTransitionFactory trimmingTransitionFactory,
+ PackageManager packageManager) {
+ OutputStream out = reporter.getOutErr().getOutputStream();
+ return ImmutableList.of(
+ new ActionGraphProtoOutputFormatterCallback(
+ reporter, aqueryOptions, out, skyframeExecutor, accessor));
+ }
+
+ @Override
+ public String getOutputFormat() {
+ return aqueryOptions.outputFormat;
+ }
+
+ @Override
+ protected KeyExtractor<ConfiguredTargetValue, ConfiguredTargetKey>
+ getConfiguredTargetKeyExtractor() {
+ return configuredTargetKeyExtractor;
+ }
+
+ @Override
+ public Label getCorrectLabel(ConfiguredTargetValue configuredTargetValue) {
+ ConfiguredTarget target = configuredTargetValue.getConfiguredTarget();
+ if (target instanceof AliasConfiguredTarget) {
+ return ((AliasConfiguredTarget) target).getOriginalLabel();
+ }
+ return target.getLabel();
+ }
+
+ @Nullable
+ @Override
+ protected ConfiguredTargetValue getHostConfiguredTarget(Label label) throws InterruptedException {
+ return this.getConfiguredTargetValue(ConfiguredTargetValue.key(label, hostConfiguration));
+ }
+
+ @Nullable
+ @Override
+ protected ConfiguredTargetValue getTargetConfiguredTarget(Label label)
+ throws InterruptedException {
+ return this.getConfiguredTargetValue(
+ ConfiguredTargetValue.key(label, defaultTargetConfiguration));
+ }
+
+ @Nullable
+ @Override
+ protected ConfiguredTargetValue getNullConfiguredTarget(Label label) throws InterruptedException {
+ return this.getConfiguredTargetValue(
+ ConfiguredTargetValue.key(label, /* configuration= */ null));
+ }
+
+ @Nullable
+ @Override
+ protected ConfiguredTargetValue getValueFromKey(SkyKey key) throws InterruptedException {
+ return getConfiguredTargetValue(key);
+ }
+
+ @Nullable
+ @Override
+ protected RuleConfiguredTarget getRuleConfiguredTarget(
+ ConfiguredTargetValue configuredTargetValue) {
+ ConfiguredTarget configuredTarget = configuredTargetValue.getConfiguredTarget();
+ if (configuredTarget instanceof RuleConfiguredTarget) {
+ return (RuleConfiguredTarget) configuredTarget;
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ protected BuildConfiguration getConfiguration(ConfiguredTargetValue configuredTargetValue) {
+ ConfiguredTarget target = configuredTargetValue.getConfiguredTarget();
+ try {
+ return target.getConfigurationKey() == null
+ ? null
+ : ((BuildConfigurationValue) graph.getValue(target.getConfigurationKey()))
+ .getConfiguration();
+ } catch (InterruptedException e) {
+ throw new IllegalStateException("Unexpected interruption during aquery");
+ }
+ }
+
+ @Override
+ protected ConfiguredTargetKey getSkyKey(ConfiguredTargetValue configuredTargetValue) {
+ ConfiguredTarget target = configuredTargetValue.getConfiguredTarget();
+ return ConfiguredTargetKey.of(target, getConfiguration(configuredTargetValue));
+ }
+
+ @Override
+ public QueryTaskFuture<Void> getTargetsMatchingPattern(
+ QueryExpression owner, String pattern, Callback<ConfiguredTargetValue> callback) {
+ TargetPattern patternToEval;
+ try {
+ patternToEval = getPattern(pattern);
+ } catch (TargetParsingException tpe) {
+ try {
+ reportBuildFileError(owner, tpe.getMessage());
+ } catch (QueryException qe) {
+ return immediateFailedFuture(qe);
+ }
+ return immediateSuccessfulFuture(null);
+ }
+ AsyncFunction<TargetParsingException, Void> reportBuildFileErrorAsyncFunction =
+ exn -> {
+ reportBuildFileError(owner, exn.getMessage());
+ return Futures.immediateFuture(null);
+ };
+ return QueryTaskFutureImpl.ofDelegate(
+ Futures.catchingAsync(
+ patternToEval.evalAdaptedForAsync(
+ resolver,
+ ImmutableSet.of(),
+ ImmutableSet.of(),
+ (Callback<Target>)
+ partialResult -> {
+ List<ConfiguredTargetValue> transformedResult = new ArrayList<>();
+ for (Target target : partialResult) {
+ ConfiguredTargetValue configuredTargetValue =
+ getConfiguredTargetValue(target.getLabel());
+ if (configuredTargetValue != null) {
+ transformedResult.add(configuredTargetValue);
+ }
+ }
+ callback.process(transformedResult);
+ },
+ QueryException.class),
+ TargetParsingException.class,
+ reportBuildFileErrorAsyncFunction,
+ MoreExecutors.directExecutor()));
+ }
+
+ private ConfiguredTargetValue getConfiguredTargetValue(Label label) throws InterruptedException {
+ // Try with target configuration.
+ ConfiguredTargetValue configuredTargetValue = getTargetConfiguredTarget(label);
+ if (configuredTargetValue != null) {
+ return configuredTargetValue;
+ }
+ // Try with host configuration (even when --nohost_deps is set in the case that top-level
+ // targets are configured in the host configuration so we are doing a host-configuration-only
+ // query).
+ configuredTargetValue = getHostConfiguredTarget(label);
+ if (configuredTargetValue != null) {
+ return configuredTargetValue;
+ }
+ // Last chance: source file.
+ return getNullConfiguredTarget(label);
+ }
+
+ @Override
+ public ThreadSafeMutableSet<ConfiguredTargetValue> createThreadSafeMutableSet() {
+ return new ThreadSafeMutableKeyExtractorBackedSetImpl<>(
+ configuredTargetKeyExtractor,
+ ConfiguredTargetValue.class,
+ SkyQueryEnvironment.DEFAULT_THREAD_COUNT);
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/query2/AqueryThreadsafeCallback.java b/src/main/java/com/google/devtools/build/lib/query2/AqueryThreadsafeCallback.java
new file mode 100644
index 0000000000..efbecd524b
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/query2/AqueryThreadsafeCallback.java
@@ -0,0 +1,45 @@
+// 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.query2;
+
+import com.google.devtools.build.lib.events.Reporter;
+import com.google.devtools.build.lib.query2.engine.QueryEnvironment.TargetAccessor;
+import com.google.devtools.build.lib.query2.output.AqueryOptions;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetValue;
+import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+/** Base class for aquery output callbacks. */
+public abstract class AqueryThreadsafeCallback
+ extends NamedThreadSafeOutputFormatterCallback<ConfiguredTargetValue> {
+ protected final Reporter reporter;
+ protected final AqueryOptions options;
+ protected final PrintStream printStream;
+ protected final SkyframeExecutor skyframeExecutor;
+ protected final ConfiguredTargetValueAccessor accessor;
+
+ AqueryThreadsafeCallback(
+ Reporter reporter,
+ AqueryOptions options,
+ OutputStream out,
+ SkyframeExecutor skyframeExecutor,
+ TargetAccessor<ConfiguredTargetValue> accessor) {
+ this.reporter = reporter;
+ this.options = options;
+ this.printStream = out == null ? null : new PrintStream(out);
+ this.skyframeExecutor = skyframeExecutor;
+ this.accessor = (ConfiguredTargetValueAccessor) accessor;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/query2/ConfiguredTargetQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/ConfiguredTargetQueryEnvironment.java
index f48c384d9c..2ab78be533 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/ConfiguredTargetQueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/ConfiguredTargetQueryEnvironment.java
@@ -20,6 +20,7 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.TargetParsingException;
import com.google.devtools.build.lib.cmdline.TargetPattern;
@@ -328,6 +329,15 @@ public class ConfiguredTargetQueryEnvironment
@Nullable
@Override
+ protected RuleConfiguredTarget getRuleConfiguredTarget(ConfiguredTarget configuredTarget) {
+ if (configuredTarget instanceof RuleConfiguredTarget) {
+ return (RuleConfiguredTarget) configuredTarget;
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
protected BuildConfiguration getConfiguration(ConfiguredTarget target) {
try {
return target.getConfigurationKey() == null
diff --git a/src/main/java/com/google/devtools/build/lib/query2/PostAnalysisQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/PostAnalysisQueryEnvironment.java
index df61da858a..fb17eac07d 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/PostAnalysisQueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/PostAnalysisQueryEnvironment.java
@@ -341,19 +341,24 @@ public abstract class PostAnalysisQueryEnvironment<T> extends AbstractBlazeQuery
.collect(Collectors.toList());
}
}
- if (settings.contains(Setting.NO_IMPLICIT_DEPS) && target instanceof RuleConfiguredTarget) {
- Set<ConfiguredTargetKey> implicitDeps = ((RuleConfiguredTarget) target).getImplicitDeps();
- deps =
- deps.stream()
- .filter(
- dep ->
- !implicitDeps.contains(
- ConfiguredTargetKey.of(getCorrectLabel(dep), getConfiguration(dep))))
- .collect(Collectors.toList());
+ if (settings.contains(Setting.NO_IMPLICIT_DEPS)) {
+ RuleConfiguredTarget ruleConfiguredTarget = getRuleConfiguredTarget(target);
+ if (ruleConfiguredTarget != null) {
+ Set<ConfiguredTargetKey> implicitDeps = ruleConfiguredTarget.getImplicitDeps();
+ deps =
+ deps.stream()
+ .filter(
+ dep ->
+ !implicitDeps.contains(
+ ConfiguredTargetKey.of(getCorrectLabel(dep), getConfiguration(dep))))
+ .collect(Collectors.toList());
+ }
}
return deps;
}
+ protected abstract RuleConfiguredTarget getRuleConfiguredTarget(T target);
+
protected Map<SkyKey, Collection<T>> targetifyValues(
Map<SkyKey, ? extends Iterable<SkyKey>> input) throws InterruptedException {
Map<SkyKey, Collection<T>> result = new HashMap<>();
diff --git a/src/main/java/com/google/devtools/build/lib/query2/output/AqueryOptions.java b/src/main/java/com/google/devtools/build/lib/query2/output/AqueryOptions.java
new file mode 100644
index 0000000000..157b3b4f8e
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/query2/output/AqueryOptions.java
@@ -0,0 +1,30 @@
+// 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.query2.output;
+
+import com.google.devtools.build.lib.query2.CommonQueryOptions;
+import com.google.devtools.common.options.Option;
+import com.google.devtools.common.options.OptionDocumentationCategory;
+import com.google.devtools.common.options.OptionEffectTag;
+
+/** Options class for aquery specific query options. */
+public class AqueryOptions extends CommonQueryOptions {
+ @Option(
+ name = "output",
+ defaultValue = "proto",
+ documentationCategory = OptionDocumentationCategory.QUERY,
+ effectTags = {OptionEffectTag.TERMINAL_OUTPUT},
+ help = "The format in which the aquery results should be printed.")
+ public String outputFormat;
+}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BuiltinCommandModule.java b/src/main/java/com/google/devtools/build/lib/runtime/BuiltinCommandModule.java
index e94f2f5be2..63896d3ccf 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BuiltinCommandModule.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BuiltinCommandModule.java
@@ -13,6 +13,7 @@
// limitations under the License.
package com.google.devtools.build.lib.runtime;
+import com.google.devtools.build.lib.runtime.commands.AqueryCommand;
import com.google.devtools.build.lib.runtime.commands.BuildCommand;
import com.google.devtools.build.lib.runtime.commands.CanonicalizeCommand;
import com.google.devtools.build.lib.runtime.commands.CleanCommand;
@@ -58,6 +59,7 @@ public class BuiltinCommandModule extends BlazeModule {
new ShutdownCommand(),
new TestCommand(),
new VersionCommand(),
+ new AqueryCommand(),
new CqueryCommand());
// Only enable the "license" command when this binary has an embedded LICENSE file.
if (LicenseCommand.isSupported()) {
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/AqueryCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/AqueryCommand.java
new file mode 100644
index 0000000000..ec8ca19f47
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/AqueryCommand.java
@@ -0,0 +1,121 @@
+// 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.runtime.commands;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.buildtool.AqueryBuildTool;
+import com.google.devtools.build.lib.buildtool.BuildRequest;
+import com.google.devtools.build.lib.events.Event;
+import com.google.devtools.build.lib.query2.ActionGraphQueryEnvironment;
+import com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunction;
+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.QueryParser;
+import com.google.devtools.build.lib.query2.output.AqueryOptions;
+import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
+import com.google.devtools.build.lib.runtime.BlazeRuntime;
+import com.google.devtools.build.lib.runtime.Command;
+import com.google.devtools.build.lib.runtime.CommandEnvironment;
+import com.google.devtools.build.lib.util.ExitCode;
+import com.google.devtools.common.options.OptionPriority.PriorityCategory;
+import com.google.devtools.common.options.OptionsParser;
+import com.google.devtools.common.options.OptionsParsingException;
+import com.google.devtools.common.options.OptionsProvider;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/** Handles the 'aquery' command on the Blaze command line. */
+@Command(
+ name = "aquery",
+ builds = true,
+ inherits = {BuildCommand.class},
+ options = {AqueryOptions.class},
+ usesConfigurationOptions = true,
+ shortDescription = "Analyzes the given targets and queries the action graph.",
+ allowResidue = true,
+ completion = "label",
+ help = "resource:aquery.txt")
+public final class AqueryCommand implements BlazeCommand {
+
+ @Override
+ public void editOptions(OptionsParser optionsParser) {
+ try {
+ optionsParser.parse(
+ PriorityCategory.COMPUTED_DEFAULT,
+ "Option required by aquery",
+ ImmutableList.of("--nobuild"));
+ } catch (OptionsParsingException e) {
+ throw new IllegalStateException("Aquery's known options failed to parse", e);
+ }
+ }
+
+ @Override
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
+ // TODO(twerth): Reduce overlap with CqueryCommand.
+ env.getReporter()
+ .handle(
+ Event.warn(
+ "Note that the aquery command is still experimental "
+ + "and its API will change in the future."));
+ if (options.getResidue().isEmpty()) {
+ env.getReporter()
+ .handle(
+ Event.error(
+ "Missing query expression. Use the 'help aquery' command for syntax and help."));
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
+ }
+ String query = Joiner.on(' ').join(options.getResidue());
+ HashMap<String, QueryFunction> functions = new HashMap<>();
+ for (QueryFunction queryFunction : ActionGraphQueryEnvironment.FUNCTIONS) {
+ functions.put(queryFunction.getName(), queryFunction);
+ }
+ for (QueryFunction queryFunction : env.getRuntime().getQueryFunctions()) {
+ functions.put(queryFunction.getName(), queryFunction);
+ }
+ QueryExpression expr;
+ try {
+ expr = QueryParser.parse(query, functions);
+ } catch (QueryException e) {
+ env.getReporter()
+ .handle(Event.error("Error while parsing '" + query + "': " + e.getMessage()));
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
+ }
+
+ List<String> topLevelTargets = options.getOptions(AqueryOptions.class).universeScope;
+ Set<String> targetPatternSet = new LinkedHashSet<>();
+ if (topLevelTargets.isEmpty()) {
+ expr.collectTargetPatterns(targetPatternSet);
+ topLevelTargets = new ArrayList<>(targetPatternSet);
+ }
+ BlazeRuntime runtime = env.getRuntime();
+
+ BuildRequest request =
+ BuildRequest.create(
+ getClass().getAnnotation(Command.class).name(),
+ options,
+ runtime.getStartupOptionsProvider(),
+ topLevelTargets,
+ env.getReporter().getOutErr(),
+ env.getCommandId(),
+ env.getCommandStartTime());
+ ExitCode exitCode =
+ new AqueryBuildTool(env, expr).processRequest(request, null).getExitCondition();
+ return BlazeCommandResult.exitCode(exitCode);
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/aquery.txt b/src/main/java/com/google/devtools/build/lib/runtime/commands/aquery.txt
new file mode 100644
index 0000000000..d8585f4a33
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/aquery.txt
@@ -0,0 +1,8 @@
+Usage: %{product} %{command} <options> <targets>
+
+Queries the specified targets, taking options into account and returns analysis
+time information about the action graph.
+The aquery command works on the post analysis phase configured target graph. It
+understands and takes into account configurations and configuration transitions.
+
+%{options}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/ActionGraphDump.java b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/ActionGraphDump.java
index acd5b3bd1b..5ade7a91ea 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/ActionGraphDump.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/ActionGraphDump.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.skyframe.actiongraph;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@@ -59,6 +60,10 @@ public class ActionGraphDump {
private final KnownRuleConfiguredTargets knownRuleConfiguredTargets;
private final boolean includeActionCmdLine;
+ public ActionGraphDump(boolean includeActionCmdLine) {
+ this(/* actionGraphTargets= */ ImmutableList.of("..."), includeActionCmdLine);
+ }
+
public ActionGraphDump(List<String> actionGraphTargets, boolean includeActionCmdLine) {
this.actionGraphTargets = ImmutableSet.copyOf(actionGraphTargets);
this.includeActionCmdLine = includeActionCmdLine;