blob: 77cefb525861ea4d63c638a390f0fa143e8b8d08 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package com.google.devtools.build.lib.analysis;
16
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000017import static com.google.common.collect.Iterables.concat;
18
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010019import com.google.common.annotations.VisibleForTesting;
20import com.google.common.base.Function;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010021import com.google.common.base.Predicate;
Greg Estren7883bf12016-11-18 20:03:43 +000022import com.google.common.collect.ArrayListMultimap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010023import com.google.common.collect.ImmutableList;
24import com.google.common.collect.ImmutableMap;
Greg Estren0db9b112016-12-05 21:55:54 +000025import com.google.common.collect.ImmutableMultimap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010026import com.google.common.collect.ImmutableSet;
27import com.google.common.collect.Iterables;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010028import com.google.common.collect.Lists;
Greg Estren7883bf12016-11-18 20:03:43 +000029import com.google.common.collect.Multimap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010030import com.google.common.collect.Sets;
31import com.google.common.eventbus.EventBus;
Rumou Duan33bab462016-04-25 17:55:12 +000032import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010033import com.google.devtools.build.lib.actions.ActionGraph;
34import com.google.devtools.build.lib.actions.Artifact;
35import com.google.devtools.build.lib.actions.ArtifactFactory;
Eric Fellheimer9c1e12f2015-08-06 20:23:55 +000036import com.google.devtools.build.lib.actions.ArtifactOwner;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010037import com.google.devtools.build.lib.actions.Root;
Dmitry Lomovd83af9e2017-02-23 15:44:23 +000038import com.google.devtools.build.lib.analysis.DependencyResolver.InconsistentAspectOrderException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010039import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
40import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection;
Greg Estren373e3e22016-08-09 22:36:51 +000041import com.google.devtools.build.lib.analysis.config.BuildOptions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010042import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
Greg Estren373e3e22016-08-09 22:36:51 +000043import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000044import com.google.devtools.build.lib.cmdline.Label;
Kristina Chodorow73fa2032015-08-28 17:57:46 +000045import com.google.devtools.build.lib.cmdline.PackageIdentifier;
Lukacs Berki6916be22015-02-19 13:36:06 +000046import com.google.devtools.build.lib.collect.nestedset.NestedSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010047import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
48import com.google.devtools.build.lib.collect.nestedset.Order;
49import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010050import com.google.devtools.build.lib.events.Event;
51import com.google.devtools.build.lib.events.EventHandler;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010052import com.google.devtools.build.lib.events.StoredEventHandler;
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000053import com.google.devtools.build.lib.packages.AspectClass;
Dmitry Lomov15756522016-12-16 16:52:37 +000054import com.google.devtools.build.lib.packages.AspectDescriptor;
Dmitry Lomovca9bfa42016-11-15 13:22:36 +000055import com.google.devtools.build.lib.packages.AspectParameters;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010056import com.google.devtools.build.lib.packages.Attribute;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000057import com.google.devtools.build.lib.packages.BuildType;
Dmitry Lomov8ff06452015-10-21 19:16:30 +000058import com.google.devtools.build.lib.packages.NativeAspectClass;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010059import com.google.devtools.build.lib.packages.NoSuchThingException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010060import com.google.devtools.build.lib.packages.PackageSpecification;
61import com.google.devtools.build.lib.packages.RawAttributeMapper;
62import com.google.devtools.build.lib.packages.Rule;
63import com.google.devtools.build.lib.packages.Target;
64import com.google.devtools.build.lib.packages.TargetUtils;
Ulf Adamsd8099362015-11-02 14:56:46 +000065import com.google.devtools.build.lib.pkgcache.LoadingResult;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010066import com.google.devtools.build.lib.rules.test.CoverageReportActionFactory;
Googlercdc90e92015-02-11 00:18:07 +000067import com.google.devtools.build.lib.rules.test.CoverageReportActionFactory.CoverageReportActionsWrapper;
Ulf Adamsfc154ae2015-08-31 12:32:14 +000068import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider;
Eric Fellheimer9c1e12f2015-08-06 20:23:55 +000069import com.google.devtools.build.lib.skyframe.ActionLookupValue;
Dmitry Lomove2033b12015-08-19 16:57:49 +000070import com.google.devtools.build.lib.skyframe.AspectValue;
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000071import com.google.devtools.build.lib.skyframe.AspectValue.AspectKey;
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +000072import com.google.devtools.build.lib.skyframe.AspectValue.AspectValueKey;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010073import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
Greg Estren7971e672016-06-01 23:22:48 +000074import com.google.devtools.build.lib.skyframe.ConfiguredTargetValue;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010075import com.google.devtools.build.lib.skyframe.CoverageReportValue;
Dmitry Lomove2033b12015-08-19 16:57:49 +000076import com.google.devtools.build.lib.skyframe.SkyframeAnalysisResult;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010077import com.google.devtools.build.lib.skyframe.SkyframeBuildView;
78import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
79import com.google.devtools.build.lib.syntax.EvalException;
Dmitry Lomov51aafc12016-11-18 14:02:54 +000080import com.google.devtools.build.lib.syntax.SkylarkImport;
81import com.google.devtools.build.lib.syntax.SkylarkImports;
82import com.google.devtools.build.lib.syntax.SkylarkImports.SkylarkImportSyntaxException;
Greg Estrend5353252016-08-11 22:13:31 +000083import com.google.devtools.build.lib.util.OrderedSetMultimap;
Mark Schaller6df81792015-12-10 18:47:47 +000084import com.google.devtools.build.lib.util.Preconditions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010085import com.google.devtools.build.lib.util.RegexFilter;
86import com.google.devtools.build.lib.vfs.Path;
Dmitry Lomov0b832ce2015-10-20 10:03:14 +000087import com.google.devtools.build.lib.vfs.PathFragment;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010088import com.google.devtools.build.skyframe.SkyKey;
Eric Fellheimer9c1e12f2015-08-06 20:23:55 +000089import com.google.devtools.build.skyframe.WalkableGraph;
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +000090import com.google.devtools.common.options.Converter;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010091import com.google.devtools.common.options.Option;
92import com.google.devtools.common.options.OptionsBase;
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +000093import com.google.devtools.common.options.OptionsParsingException;
Dmitry Lomove2033b12015-08-19 16:57:49 +000094import java.util.ArrayList;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010095import java.util.Collection;
96import java.util.HashMap;
97import java.util.HashSet;
Lukacs Berki53e03912016-05-19 16:26:09 +000098import java.util.LinkedHashMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010099import java.util.LinkedHashSet;
100import java.util.List;
101import java.util.Map;
102import java.util.Set;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100103import java.util.logging.Logger;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100104import javax.annotation.Nullable;
105
106/**
107 * <p>The BuildView presents a semantically-consistent and transitively-closed
108 * dependency graph for some set of packages.
109 *
110 * <h2>Package design</h2>
111 *
112 * <p>This package contains the Blaze dependency analysis framework (aka
113 * "analysis phase"). The goal of this code is to perform semantic analysis of
114 * all of the build targets required for a given build, to report
115 * errors/warnings for any problems in the input, and to construct an "action
116 * graph" (see {@code lib.actions} package) correctly representing the work to
117 * be done during the execution phase of the build.
118 *
119 * <p><b>Configurations</b> the inputs to a build come from two sources: the
120 * intrinsic inputs, specified in the BUILD file, are called <em>targets</em>.
121 * The environmental inputs, coming from the build tool, the command-line, or
122 * configuration files, are called the <em>configuration</em>. Only when a
123 * target and a configuration are combined is there sufficient information to
124 * perform a build. </p>
125 *
126 * <p>Targets are implemented by the {@link Target} hierarchy in the {@code
127 * lib.packages} code. Configurations are implemented by {@link
128 * BuildConfiguration}. The pair of these together is represented by an
129 * instance of class {@link ConfiguredTarget}; this is the root of a hierarchy
130 * with different implementations for each kind of target: source file, derived
131 * file, rules, etc.
132 *
133 * <p>The framework code in this package (as opposed to its subpackages) is
134 * responsible for constructing the {@code ConfiguredTarget} graph for a given
135 * target and configuration, taking care of such issues as:
136 * <ul>
137 * <li>caching common subgraphs.
138 * <li>detecting and reporting cycles.
139 * <li>correct propagation of errors through the graph.
140 * <li>reporting universal errors, such as dependencies from production code
141 * to tests, or to experimental branches.
142 * <li>capturing and replaying errors.
143 * <li>maintaining the graph from one build to the next to
144 * avoid unnecessary recomputation.
145 * <li>checking software licenses.
146 * </ul>
147 *
148 * <p>See also {@link ConfiguredTarget} which documents some important
149 * invariants.
150 */
151public class BuildView {
152
153 /**
154 * Options that affect the <i>mechanism</i> of analysis. These are distinct from {@link
155 * com.google.devtools.build.lib.analysis.config.BuildOptions}, which affect the <i>value</i>
156 * of a BuildConfiguration.
157 */
158 public static class Options extends OptionsBase {
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000159 @Option(
160 name = "loading_phase_threads",
161 defaultValue = "-1",
162 category = "what",
163 converter = LoadingPhaseThreadCountConverter.class,
164 help = "Number of parallel threads to use for the loading/analysis phase."
165 )
166 public int loadingPhaseThreads;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100167
168 @Option(name = "keep_going",
169 abbrev = 'k',
170 defaultValue = "false",
171 category = "strategy",
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000172 help = "Continue as much as possible after an error. While the"
173 + " target that failed, and those that depend on it, cannot be"
174 + " analyzed (or built), the other prerequisites of these"
175 + " targets can be analyzed (or built) all the same.")
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100176 public boolean keepGoing;
177
178 @Option(name = "analysis_warnings_as_errors",
Janak Ramakrishnanae8e9222015-04-28 17:37:13 +0000179 deprecationWarning = "analysis_warnings_as_errors is now a no-op and will be removed in"
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000180 + " an upcoming Blaze release",
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100181 defaultValue = "false",
182 category = "strategy",
183 help = "Treat visible analysis warnings as errors.")
184 public boolean analysisWarningsAsErrors;
185
186 @Option(name = "discard_analysis_cache",
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000187 defaultValue = "false",
188 category = "strategy",
189 help = "Discard the analysis cache immediately after the analysis phase completes."
190 + " Reduces memory usage by ~10%, but makes further incremental builds slower.")
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100191 public boolean discardAnalysisCache;
192
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100193 @Option(name = "experimental_extra_action_filter",
194 defaultValue = "",
195 category = "experimental",
196 converter = RegexFilter.RegexFilterConverter.class,
197 help = "Filters set of targets to schedule extra_actions for.")
198 public RegexFilter extraActionFilter;
199
200 @Option(name = "experimental_extra_action_top_level_only",
201 defaultValue = "false",
202 category = "experimental",
203 help = "Only schedules extra_actions for top level targets.")
204 public boolean extraActionTopLevelOnly;
205
Carmi Grushko9a796de2016-11-13 12:22:30 +0000206 @Option(
207 name = "experimental_extra_action_top_level_only_with_aspects",
208 defaultValue = "true",
209 category = "experimental",
210 help =
211 "If true and --experimental_extra_action_top_level_only=true, will include actions "
212 + "from aspects injected by top-level rules. "
213 + "This is an escape hatch in case commit df9e5e16c370391098c4432779ad4d1c9dd693ca "
214 + "breaks something."
215 )
216 public boolean extraActionTopLevelOnlyWithAspects;
217
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100218 @Option(name = "version_window_for_dirty_node_gc",
219 defaultValue = "0",
220 category = "undocumented",
221 help = "Nodes that have been dirty for more than this many versions will be deleted"
222 + " from the graph upon the next update. Values must be non-negative long integers,"
223 + " or -1 indicating the maximum possible window.")
224 public long versionWindowForDirtyNodeGc;
Ulf Adamsab64e592016-09-05 09:40:13 +0000225
226 @Deprecated
227 @Option(
228 name = "experimental_interleave_loading_and_analysis",
229 defaultValue = "true",
230 category = "experimental",
231 help = "No-op."
232 )
233 public boolean interleaveLoadingAndAnalysis;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100234 }
235
236 private static Logger LOG = Logger.getLogger(BuildView.class.getName());
237
238 private final BlazeDirectories directories;
239
240 private final SkyframeExecutor skyframeExecutor;
241 private final SkyframeBuildView skyframeBuildView;
242
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100243 private final ConfiguredRuleClassProvider ruleClassProvider;
244
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100245 /**
246 * A factory class to create the coverage report action. May be null.
247 */
248 @Nullable private final CoverageReportActionFactory coverageReportActionFactory;
249
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100250 @VisibleForTesting
251 public Set<SkyKey> getSkyframeEvaluatedTargetKeysForTesting() {
252 return skyframeBuildView.getEvaluatedTargetKeys();
253 }
254
255 /** The number of targets freshly evaluated in the last analysis run. */
256 public int getTargetsVisited() {
257 return skyframeBuildView.getEvaluatedTargetKeys().size();
258 }
259
Ulf Adams59dbf682015-09-17 11:36:43 +0000260 public BuildView(BlazeDirectories directories,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100261 ConfiguredRuleClassProvider ruleClassProvider,
262 SkyframeExecutor skyframeExecutor,
Ulf Adams5a96d532015-09-26 09:00:57 +0000263 CoverageReportActionFactory coverageReportActionFactory) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100264 this.directories = directories;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100265 this.coverageReportActionFactory = coverageReportActionFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100266 this.ruleClassProvider = ruleClassProvider;
267 this.skyframeExecutor = Preconditions.checkNotNull(skyframeExecutor);
Ulf Adams89eefd72015-09-23 08:00:43 +0000268 this.skyframeBuildView = skyframeExecutor.getSkyframeBuildView();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100269 }
270
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100271 /**
272 * Returns whether the given configured target has errors.
273 */
274 @VisibleForTesting
275 public boolean hasErrors(ConfiguredTarget configuredTarget) {
276 return configuredTarget == null;
277 }
278
279 /**
280 * Sets the configurations. Not thread-safe. DO NOT CALL except from tests!
281 */
282 @VisibleForTesting
Ulf Adams79f05212015-02-27 16:40:00 +0000283 public void setConfigurationsForTesting(BuildConfigurationCollection configurations) {
Ulf Adams003fe962015-09-26 09:51:39 +0000284 skyframeBuildView.setConfigurations(configurations);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100285 }
286
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100287 public ArtifactFactory getArtifactFactory() {
Ulf Adams89eefd72015-09-23 08:00:43 +0000288 return skyframeBuildView.getArtifactFactory();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100289 }
290
291 @VisibleForTesting
292 WorkspaceStatusAction getLastWorkspaceBuildInfoActionForTesting() {
293 return skyframeExecutor.getLastWorkspaceStatusActionForTesting();
294 }
295
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100296 @Override
297 public int hashCode() {
298 throw new UnsupportedOperationException(); // avoid nondeterminism
299 }
300
301 /**
302 * Return value for {@link BuildView#update} and {@code BuildTool.prepareToBuild}.
303 */
304 public static final class AnalysisResult {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100305 private final ImmutableList<ConfiguredTarget> targetsToBuild;
306 @Nullable private final ImmutableList<ConfiguredTarget> targetsToTest;
307 @Nullable private final String error;
308 private final ActionGraph actionGraph;
309 private final ImmutableSet<Artifact> artifactsToBuild;
310 private final ImmutableSet<ConfiguredTarget> parallelTests;
311 private final ImmutableSet<ConfiguredTarget> exclusiveTests;
312 @Nullable private final TopLevelArtifactContext topLevelContext;
Dmitry Lomove2033b12015-08-19 16:57:49 +0000313 private final ImmutableList<AspectValue> aspects;
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000314 private final ImmutableMap<PackageIdentifier, Path> packageRoots;
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000315 private final String workspaceName;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100316
317 private AnalysisResult(
Dmitry Lomove2033b12015-08-19 16:57:49 +0000318 Collection<ConfiguredTarget> targetsToBuild,
319 Collection<AspectValue> aspects,
320 Collection<ConfiguredTarget> targetsToTest,
321 @Nullable String error,
322 ActionGraph actionGraph,
323 Collection<Artifact> artifactsToBuild,
324 Collection<ConfiguredTarget> parallelTests,
325 Collection<ConfiguredTarget> exclusiveTests,
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000326 TopLevelArtifactContext topLevelContext,
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000327 ImmutableMap<PackageIdentifier, Path> packageRoots,
328 String workspaceName) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100329 this.targetsToBuild = ImmutableList.copyOf(targetsToBuild);
Dmitry Lomove2033b12015-08-19 16:57:49 +0000330 this.aspects = ImmutableList.copyOf(aspects);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100331 this.targetsToTest = targetsToTest == null ? null : ImmutableList.copyOf(targetsToTest);
332 this.error = error;
333 this.actionGraph = actionGraph;
334 this.artifactsToBuild = ImmutableSet.copyOf(artifactsToBuild);
335 this.parallelTests = ImmutableSet.copyOf(parallelTests);
336 this.exclusiveTests = ImmutableSet.copyOf(exclusiveTests);
337 this.topLevelContext = topLevelContext;
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000338 this.packageRoots = packageRoots;
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000339 this.workspaceName = workspaceName;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100340 }
341
342 /**
343 * Returns configured targets to build.
344 */
345 public Collection<ConfiguredTarget> getTargetsToBuild() {
346 return targetsToBuild;
347 }
348
349 /**
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000350 * The map from package names to the package root where each package was found; this is used to
351 * set up the symlink tree.
352 */
353 public ImmutableMap<PackageIdentifier, Path> getPackageRoots() {
354 return packageRoots;
355 }
356
357 /**
Dmitry Lomove2033b12015-08-19 16:57:49 +0000358 * Returns aspects of configured targets to build.
359 *
360 * <p>If this list is empty, build the targets returned by {@code getTargetsToBuild()}.
361 * Otherwise, only build these aspects of the targets returned by {@code getTargetsToBuild()}.
362 */
363 public Collection<AspectValue> getAspects() {
364 return aspects;
365 }
366
367 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100368 * Returns the configured targets to run as tests, or {@code null} if testing was not
369 * requested (e.g. "build" command rather than "test" command).
370 */
371 @Nullable
372 public Collection<ConfiguredTarget> getTargetsToTest() {
373 return targetsToTest;
374 }
375
376 public ImmutableSet<Artifact> getAdditionalArtifactsToBuild() {
377 return artifactsToBuild;
378 }
379
380 public ImmutableSet<ConfiguredTarget> getExclusiveTests() {
381 return exclusiveTests;
382 }
383
384 public ImmutableSet<ConfiguredTarget> getParallelTests() {
385 return parallelTests;
386 }
387
388 /**
389 * Returns an error description (if any).
390 */
391 @Nullable public String getError() {
392 return error;
393 }
394
Ulf Adams988bb212015-08-25 12:51:48 +0000395 public boolean hasError() {
396 return error != null;
397 }
398
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100399 /**
400 * Returns the action graph.
401 */
402 public ActionGraph getActionGraph() {
403 return actionGraph;
404 }
405
406 public TopLevelArtifactContext getTopLevelContext() {
407 return topLevelContext;
408 }
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000409
410 public String getWorkspaceName() {
411 return workspaceName;
412 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100413 }
414
415
416 /**
417 * Returns the collection of configured targets corresponding to any of the provided targets.
418 */
419 @VisibleForTesting
420 static Iterable<? extends ConfiguredTarget> filterTestsByTargets(
421 Collection<? extends ConfiguredTarget> targets,
422 final Set<? extends Target> allowedTargets) {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000423 return Iterables.filter(
424 targets,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100425 new Predicate<ConfiguredTarget>() {
426 @Override
Dmitry Lomove2033b12015-08-19 16:57:49 +0000427 public boolean apply(ConfiguredTarget rule) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100428 return allowedTargets.contains(rule.getTarget());
429 }
430 });
431 }
432
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100433 @ThreadCompatible
Dmitry Lomove2033b12015-08-19 16:57:49 +0000434 public AnalysisResult update(
435 LoadingResult loadingResult,
436 BuildConfigurationCollection configurations,
437 List<String> aspects,
438 Options viewOptions,
439 TopLevelArtifactContext topLevelOptions,
440 EventHandler eventHandler,
Ulf Adams8c4ae672016-03-30 11:20:41 +0000441 EventBus eventBus)
Dmitry Lomove2033b12015-08-19 16:57:49 +0000442 throws ViewCreationFailedException, InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100443 LOG.info("Starting analysis");
444 pollInterruptedStatus();
445
446 skyframeBuildView.resetEvaluatedConfiguredTargetKeysSet();
447
448 Collection<Target> targets = loadingResult.getTargets();
449 eventBus.post(new AnalysisPhaseStartedEvent(targets));
450
Ulf Adams003fe962015-09-26 09:51:39 +0000451 skyframeBuildView.setConfigurations(configurations);
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000452
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100453 // Determine the configurations.
Greg Estren7971e672016-06-01 23:22:48 +0000454 List<TargetAndConfiguration> topLevelTargetsWithConfigs =
455 nodesForTopLevelTargets(configurations, targets, eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100456
Greg Estren7971e672016-06-01 23:22:48 +0000457 List<ConfiguredTargetKey> topLevelCtKeys = Lists.transform(topLevelTargetsWithConfigs,
458 new Function<TargetAndConfiguration, ConfiguredTargetKey>() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100459 @Override
460 public ConfiguredTargetKey apply(TargetAndConfiguration node) {
461 return new ConfiguredTargetKey(node.getLabel(), node.getConfiguration());
462 }
463 });
464
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000465 List<AspectValueKey> aspectKeys = new ArrayList<>();
Dmitry Lomove2033b12015-08-19 16:57:49 +0000466 for (String aspect : aspects) {
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000467 // Syntax: label%aspect
468 int delimiterPosition = aspect.indexOf('%');
469 if (delimiterPosition >= 0) {
John Fielda97e17f2015-11-13 02:19:52 +0000470 // TODO(jfield): For consistency with Skylark loads, the aspect should be specified
471 // as an absolute path. Also, we probably need to do at least basic validation of
472 // path well-formedness here.
Dmitry Lomov51aafc12016-11-18 14:02:54 +0000473 String bzlFileLoadLikeString = aspect.substring(0, delimiterPosition);
474 if (!bzlFileLoadLikeString.startsWith("//") && !bzlFileLoadLikeString.startsWith("@")) {
475 // "Legacy" behavior of '--aspects' parameter.
476 bzlFileLoadLikeString = new PathFragment("/" + bzlFileLoadLikeString).toString();
477 if (bzlFileLoadLikeString.endsWith(".bzl")) {
478 bzlFileLoadLikeString = bzlFileLoadLikeString.substring(0,
479 bzlFileLoadLikeString.length() - ".bzl".length());
480 }
481 }
482 SkylarkImport skylarkImport;
483 try {
484 skylarkImport = SkylarkImports.create(bzlFileLoadLikeString);
485 } catch (SkylarkImportSyntaxException e) {
486 throw new ViewCreationFailedException(
487 String.format("Invalid aspect '%s': %s", aspect, e.getMessage()), e);
488 }
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000489
490 String skylarkFunctionName = aspect.substring(delimiterPosition + 1);
Dmitry Lomov01f85c02016-06-29 06:37:50 +0000491 for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) {
492 if (!(targetSpec.getTarget() instanceof Rule)) {
493 continue;
494 }
Dmitry Lomove2033b12015-08-19 16:57:49 +0000495 aspectKeys.add(
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000496 AspectValue.createSkylarkAspectKey(
497 targetSpec.getLabel(),
Michael Staib04f6f242016-03-01 15:40:29 +0000498 // For invoking top-level aspects, use the top-level configuration for both the
499 // aspect and the base target while the top-level configuration is untrimmed.
500 targetSpec.getConfiguration(),
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000501 targetSpec.getConfiguration(),
Dmitry Lomov51aafc12016-11-18 14:02:54 +0000502 skylarkImport,
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000503 skylarkFunctionName));
Dmitry Lomove2033b12015-08-19 16:57:49 +0000504 }
505 } else {
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000506 final NativeAspectClass aspectFactoryClass =
507 ruleClassProvider.getNativeAspectClassMap().get(aspect);
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000508 if (aspectFactoryClass != null) {
Dmitry Lomov01f85c02016-06-29 06:37:50 +0000509 for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) {
510 if (!(targetSpec.getTarget() instanceof Rule)) {
511 continue;
512 }
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000513 // For invoking top-level aspects, use the top-level configuration for both the
514 // aspect and the base target while the top-level configuration is untrimmed.
515 BuildConfiguration configuration = targetSpec.getConfiguration();
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000516 aspectKeys.add(
517 AspectValue.createAspectKey(
Dmitry Lomov8ff06452015-10-21 19:16:30 +0000518 targetSpec.getLabel(),
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000519 configuration,
520 new AspectDescriptor(aspectFactoryClass, AspectParameters.EMPTY),
521 configuration
522 ));
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000523 }
524 } else {
525 throw new ViewCreationFailedException("Aspect '" + aspect + "' is unknown");
526 }
Dmitry Lomove2033b12015-08-19 16:57:49 +0000527 }
528 }
529
Kristina Chodorow8cb36d62016-08-26 16:14:37 +0000530 skyframeExecutor.injectWorkspaceStatusData(loadingResult.getWorkspaceName());
Dmitry Lomove2033b12015-08-19 16:57:49 +0000531 SkyframeAnalysisResult skyframeAnalysisResult;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100532 try {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000533 skyframeAnalysisResult =
534 skyframeBuildView.configureTargets(
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000535 eventHandler,
536 topLevelCtKeys,
537 aspectKeys,
538 eventBus,
539 viewOptions.keepGoing,
540 viewOptions.loadingPhaseThreads);
Kristina Chodorow94e27422016-08-25 14:17:30 +0000541 setArtifactRoots(skyframeAnalysisResult.getPackageRoots());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100542 } finally {
543 skyframeBuildView.clearInvalidatedConfiguredTargets();
544 }
545
Greg Estren7971e672016-06-01 23:22:48 +0000546 int numTargetsToAnalyze = topLevelTargetsWithConfigs.size();
Dmitry Lomove2033b12015-08-19 16:57:49 +0000547 int numSuccessful = skyframeAnalysisResult.getConfiguredTargets().size();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100548 if (0 < numSuccessful && numSuccessful < numTargetsToAnalyze) {
549 String msg = String.format("Analysis succeeded for only %d of %d top-level targets",
550 numSuccessful, numTargetsToAnalyze);
551 eventHandler.handle(Event.info(msg));
552 LOG.info(msg);
553 }
554
Dmitry Lomove2033b12015-08-19 16:57:49 +0000555 AnalysisResult result =
556 createResult(
Ulf Adams5b9009b2015-09-24 09:52:53 +0000557 eventHandler,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000558 loadingResult,
559 topLevelOptions,
560 viewOptions,
Ulf Adams53abece2016-02-03 08:30:07 +0000561 skyframeAnalysisResult);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100562 LOG.info("Finished analysis");
563 return result;
564 }
565
Dmitry Lomove2033b12015-08-19 16:57:49 +0000566 private AnalysisResult createResult(
Ulf Adams5b9009b2015-09-24 09:52:53 +0000567 EventHandler eventHandler,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000568 LoadingResult loadingResult,
569 TopLevelArtifactContext topLevelOptions,
570 BuildView.Options viewOptions,
Ulf Adams53abece2016-02-03 08:30:07 +0000571 SkyframeAnalysisResult skyframeAnalysisResult)
572 throws InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100573 Collection<Target> testsToRun = loadingResult.getTestsToRun();
Ulf Adams53abece2016-02-03 08:30:07 +0000574 Collection<ConfiguredTarget> configuredTargets = skyframeAnalysisResult.getConfiguredTargets();
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000575 Collection<AspectValue> aspects = skyframeAnalysisResult.getAspects();
576
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100577 Collection<ConfiguredTarget> allTargetsToTest = null;
578 if (testsToRun != null) {
579 // Determine the subset of configured targets that are meant to be run as tests.
Dmitry Lomov8b1a0942015-11-19 15:14:15 +0000580 // Do not remove <ConfiguredTarget>: workaround for Java 7 type inference.
581 allTargetsToTest =
582 Lists.<ConfiguredTarget>newArrayList(
583 filterTestsByTargets(configuredTargets, Sets.newHashSet(testsToRun)));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100584 }
585
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100586 Set<Artifact> artifactsToBuild = new HashSet<>();
587 Set<ConfiguredTarget> parallelTests = new HashSet<>();
588 Set<ConfiguredTarget> exclusiveTests = new HashSet<>();
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000589
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100590 // build-info and build-changelist.
Ulf Adams5b9009b2015-09-24 09:52:53 +0000591 Collection<Artifact> buildInfoArtifacts =
592 skyframeExecutor.getWorkspaceStatusArtifacts(eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100593 Preconditions.checkState(buildInfoArtifacts.size() == 2, buildInfoArtifacts);
594 artifactsToBuild.addAll(buildInfoArtifacts);
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000595
596 // Extra actions
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000597 addExtraActionsIfRequested(viewOptions, configuredTargets, aspects, artifactsToBuild);
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000598
599 // Coverage
600 NestedSet<Artifact> baselineCoverageArtifacts = getBaselineCoverageArtifacts(configuredTargets);
601 Iterables.addAll(artifactsToBuild, baselineCoverageArtifacts);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100602 if (coverageReportActionFactory != null) {
Googlercdc90e92015-02-11 00:18:07 +0000603 CoverageReportActionsWrapper actionsWrapper;
604 actionsWrapper = coverageReportActionFactory.createCoverageReportActionsWrapper(
Ulf Adams5834e2b2016-04-18 12:03:51 +0000605 eventHandler,
606 directories,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100607 allTargetsToTest,
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000608 baselineCoverageArtifacts,
Ulf Adams89eefd72015-09-23 08:00:43 +0000609 getArtifactFactory(),
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100610 CoverageReportValue.ARTIFACT_OWNER);
Googlercdc90e92015-02-11 00:18:07 +0000611 if (actionsWrapper != null) {
Rumou Duan33bab462016-04-25 17:55:12 +0000612 ImmutableList<ActionAnalysisMetadata> actions = actionsWrapper.getActions();
Googlercdc90e92015-02-11 00:18:07 +0000613 skyframeExecutor.injectCoverageReportData(actions);
614 artifactsToBuild.addAll(actionsWrapper.getCoverageOutputs());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100615 }
616 }
617
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000618 // Tests. This must come last, so that the exclusive tests are scheduled after everything else.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100619 scheduleTestsIfRequested(parallelTests, exclusiveTests, topLevelOptions, allTargetsToTest);
620
Janak Ramakrishnan6f9d7d12016-08-09 08:45:34 +0000621 String error = createErrorMessage(loadingResult, skyframeAnalysisResult);
Eric Fellheimer9c1e12f2015-08-06 20:23:55 +0000622
Ulf Adams53abece2016-02-03 08:30:07 +0000623 final WalkableGraph graph = skyframeAnalysisResult.getWalkableGraph();
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000624 final ActionGraph actionGraph =
625 new ActionGraph() {
626 @Nullable
627 @Override
628 public ActionAnalysisMetadata getGeneratingAction(Artifact artifact) {
629 ArtifactOwner artifactOwner = artifact.getArtifactOwner();
630 if (artifactOwner instanceof ActionLookupValue.ActionLookupKey) {
631 SkyKey key = ActionLookupValue.key((ActionLookupValue.ActionLookupKey) artifactOwner);
632 ActionLookupValue val;
633 try {
634 val = (ActionLookupValue) graph.getValue(key);
635 } catch (InterruptedException e) {
636 throw new IllegalStateException(
637 "Interruption not expected from this graph: " + key, e);
638 }
639 return val == null ? null : val.getGeneratingAction(artifact);
640 }
641 return null;
642 }
643 };
Dmitry Lomove2033b12015-08-19 16:57:49 +0000644 return new AnalysisResult(
645 configuredTargets,
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000646 aspects,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000647 allTargetsToTest,
648 error,
649 actionGraph,
650 artifactsToBuild,
651 parallelTests,
652 exclusiveTests,
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000653 topLevelOptions,
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000654 skyframeAnalysisResult.getPackageRoots(),
655 loadingResult.getWorkspaceName());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100656 }
657
Janak Ramakrishnan6f9d7d12016-08-09 08:45:34 +0000658 @Nullable
659 public static String createErrorMessage(
660 LoadingResult loadingResult, @Nullable SkyframeAnalysisResult skyframeAnalysisResult) {
661 return loadingResult.hasTargetPatternError()
662 ? "command succeeded, but there were errors parsing the target pattern"
663 : loadingResult.hasLoadingError()
664 || (skyframeAnalysisResult != null && skyframeAnalysisResult.hasLoadingError())
665 ? "command succeeded, but there were loading phase errors"
666 : (skyframeAnalysisResult != null && skyframeAnalysisResult.hasAnalysisError())
667 ? "command succeeded, but not all targets were analyzed"
668 : null;
669 }
670
Lukacs Berki6916be22015-02-19 13:36:06 +0000671 private static NestedSet<Artifact> getBaselineCoverageArtifacts(
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100672 Collection<ConfiguredTarget> configuredTargets) {
Lukacs Berki6916be22015-02-19 13:36:06 +0000673 NestedSetBuilder<Artifact> baselineCoverageArtifacts = NestedSetBuilder.stableOrder();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100674 for (ConfiguredTarget target : configuredTargets) {
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000675 InstrumentedFilesProvider provider = target.getProvider(InstrumentedFilesProvider.class);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100676 if (provider != null) {
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000677 baselineCoverageArtifacts.addTransitive(provider.getBaselineCoverageArtifacts());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100678 }
679 }
Lukacs Berki6916be22015-02-19 13:36:06 +0000680 return baselineCoverageArtifacts.build();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100681 }
682
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000683 private void addExtraActionsIfRequested(Options viewOptions,
684 Collection<ConfiguredTarget> configuredTargets,
685 Collection<AspectValue> aspects,
686 Set<Artifact> artifactsToBuild) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000687 Iterable<Artifact> extraActionArtifacts =
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000688 concat(
689 addExtraActionsFromTargets(viewOptions, configuredTargets),
690 addExtraActionsFromAspects(viewOptions, aspects));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100691
692 RegexFilter filter = viewOptions.extraActionFilter;
Carmi Grushkobabd4852016-11-18 17:58:09 +0000693 for (Artifact artifact : extraActionArtifacts) {
694 boolean filterMatches =
695 filter == null || filter.isIncluded(artifact.getOwnerLabel().toString());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100696 if (filterMatches) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000697 artifactsToBuild.add(artifact);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100698 }
699 }
700 }
701
Carmi Grushkobabd4852016-11-18 17:58:09 +0000702 private NestedSet<Artifact> addExtraActionsFromTargets(
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000703 BuildView.Options viewOptions, Collection<ConfiguredTarget> configuredTargets) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000704 NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000705 for (ConfiguredTarget target : configuredTargets) {
706 ExtraActionArtifactsProvider provider =
707 target.getProvider(ExtraActionArtifactsProvider.class);
708 if (provider != null) {
709 if (viewOptions.extraActionTopLevelOnly) {
Carmi Grushko9a796de2016-11-13 12:22:30 +0000710 if (!viewOptions.extraActionTopLevelOnlyWithAspects) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000711 builder.addTransitive(provider.getExtraActionArtifacts());
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000712 } else {
Carmi Grushko9a796de2016-11-13 12:22:30 +0000713 // Collect all aspect-classes that topLevel might inject.
714 Set<AspectClass> aspectClasses = new HashSet<>();
715 for (Attribute attr : target.getTarget().getAssociatedRule().getAttributes()) {
716 aspectClasses.addAll(attr.getAspectClasses());
717 }
718
Carmi Grushkobabd4852016-11-18 17:58:09 +0000719 builder.addTransitive(provider.getExtraActionArtifacts());
720 if (!aspectClasses.isEmpty()) {
721 builder.addAll(filterTransitiveExtraActions(provider, aspectClasses));
Carmi Grushko9a796de2016-11-13 12:22:30 +0000722 }
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000723 }
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000724 } else {
725 builder.addTransitive(provider.getTransitiveExtraActionArtifacts());
726 }
727 }
728 }
729 return builder.build();
730 }
731
732 /**
733 * Returns a list of actions from 'provider' that were registered by an aspect from
734 * 'aspectClasses'. All actions in 'provider' are considered - both direct and transitive.
735 */
736 private ImmutableList<Artifact> filterTransitiveExtraActions(
737 ExtraActionArtifactsProvider provider, Set<AspectClass> aspectClasses) {
738 ImmutableList.Builder<Artifact> artifacts = ImmutableList.builder();
739 // Add to 'artifacts' all extra-actions which were registered by aspects which 'topLevel'
740 // might have injected.
Carmi Grushkobabd4852016-11-18 17:58:09 +0000741 for (Artifact artifact : provider.getTransitiveExtraActionArtifacts()) {
742 ArtifactOwner owner = artifact.getArtifactOwner();
743 if (owner instanceof AspectKey) {
744 if (aspectClasses.contains(((AspectKey) owner).getAspectClass())) {
745 artifacts.add(artifact);
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000746 }
747 }
748 }
749 return artifacts.build();
750 }
751
Carmi Grushkobabd4852016-11-18 17:58:09 +0000752 private NestedSet<Artifact> addExtraActionsFromAspects(
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000753 BuildView.Options viewOptions, Collection<AspectValue> aspects) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000754 NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000755 for (AspectValue aspect : aspects) {
756 ExtraActionArtifactsProvider provider =
757 aspect.getConfiguredAspect().getProvider(ExtraActionArtifactsProvider.class);
758 if (provider != null) {
759 if (viewOptions.extraActionTopLevelOnly) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000760 builder.addTransitive(provider.getExtraActionArtifacts());
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000761 } else {
762 builder.addTransitive(provider.getTransitiveExtraActionArtifacts());
763 }
764 }
765 }
766 return builder.build();
767 }
768
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100769 private static void scheduleTestsIfRequested(Collection<ConfiguredTarget> targetsToTest,
770 Collection<ConfiguredTarget> targetsToTestExclusive, TopLevelArtifactContext topLevelOptions,
771 Collection<ConfiguredTarget> allTestTargets) {
Lukacs Berki3f4d4e92015-02-24 10:28:26 +0000772 Set<String> outputGroups = topLevelOptions.outputGroups();
Lukacs Berki1e79b962015-03-03 10:59:21 +0000773 if (!outputGroups.contains(OutputGroupProvider.FILES_TO_COMPILE)
774 && !outputGroups.contains(OutputGroupProvider.COMPILATION_PREREQUISITES)
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100775 && allTestTargets != null) {
776 scheduleTests(targetsToTest, targetsToTestExclusive, allTestTargets,
777 topLevelOptions.runTestsExclusively());
778 }
779 }
780
781
782 /**
783 * Returns set of artifacts representing test results, writing into targetsToTest and
784 * targetsToTestExclusive.
785 */
786 private static void scheduleTests(Collection<ConfiguredTarget> targetsToTest,
787 Collection<ConfiguredTarget> targetsToTestExclusive,
788 Collection<ConfiguredTarget> allTestTargets,
789 boolean isExclusive) {
790 for (ConfiguredTarget target : allTestTargets) {
791 if (target.getTarget() instanceof Rule) {
792 boolean exclusive =
793 isExclusive || TargetUtils.isExclusiveTestRule((Rule) target.getTarget());
794 Collection<ConfiguredTarget> testCollection = exclusive
795 ? targetsToTestExclusive
796 : targetsToTest;
797 testCollection.add(target);
798 }
799 }
800 }
801
Greg Estren7971e672016-06-01 23:22:48 +0000802 /**
803 * Given a set of top-level targets and a configuration collection, returns the appropriate
804 * <Target, Configuration> pair for each target.
805 *
806 * <p>Preserves the original input ordering.
807 */
808 private List<TargetAndConfiguration> nodesForTopLevelTargets(
809 BuildConfigurationCollection configurations, Collection<Target> targets,
810 EventHandler eventHandler) throws InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100811 // We use a hash set here to remove duplicate nodes; this can happen for input files and package
812 // groups.
813 LinkedHashSet<TargetAndConfiguration> nodes = new LinkedHashSet<>(targets.size());
814 for (BuildConfiguration config : configurations.getTargetConfigurations()) {
815 for (Target target : targets) {
816 nodes.add(new TargetAndConfiguration(target,
817 BuildConfigurationCollection.configureTopLevelTarget(config, target)));
818 }
819 }
Greg Estren7971e672016-06-01 23:22:48 +0000820 return configurations.useDynamicConfigurations()
Greg Estren1d8ba902016-09-21 21:18:19 +0000821 ? getDynamicConfigurations(nodes, eventHandler)
Greg Estren7971e672016-06-01 23:22:48 +0000822 : ImmutableList.copyOf(nodes);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100823 }
824
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100825 /**
Greg Estren1d8ba902016-09-21 21:18:19 +0000826 * <p>If {@link BuildConfiguration.Options#trimConfigurations()} is true, transforms a collection
827 * of <Target, Configuration> pairs by trimming each target's
Greg Estren7971e672016-06-01 23:22:48 +0000828 * configuration to only the fragments the target and its transitive dependencies need.
829 *
Greg Estren1d8ba902016-09-21 21:18:19 +0000830 * <p>Else returns configurations that unconditionally include all fragments.
831 *
Greg Estren7971e672016-06-01 23:22:48 +0000832 * <p>Preserves the original input order. Uses original (untrimmed) configurations for targets
833 * that can't be evaluated (e.g. due to loading phase errors).
834 *
835 * <p>This is suitable for feeding {@link ConfiguredTargetValue} keys: as general principle
836 * {@link ConfiguredTarget}s should have exactly as much information in their configurations as
837 * they need to evaluate and no more (e.g. there's no need for Android settings in a C++
838 * configured target).
839 */
840 // TODO(bazel-team): error out early for targets that fail - untrimmed configurations should
841 // never make it through analysis (and especially not seed ConfiguredTargetValues)
Greg Estren1d8ba902016-09-21 21:18:19 +0000842 private List<TargetAndConfiguration> getDynamicConfigurations(
843 Iterable<TargetAndConfiguration> inputs, EventHandler eventHandler)
844 throws InterruptedException {
Greg Estren7883bf12016-11-18 20:03:43 +0000845 Map<Label, Target> labelsToTargets = new LinkedHashMap<>();
846 // We'll get the configs from SkyframeExecutor#getConfigurations, which gets configurations
847 // for deps including transitions. So to satisfy its API we repackage each target as a
848 // Dependency with a NONE transition.
849 Multimap<BuildConfiguration, Dependency> asDeps =
850 ArrayListMultimap.<BuildConfiguration, Dependency>create();
Greg Estren7971e672016-06-01 23:22:48 +0000851
852 for (TargetAndConfiguration targetAndConfig : inputs) {
Greg Estren7883bf12016-11-18 20:03:43 +0000853 labelsToTargets.put(targetAndConfig.getLabel(), targetAndConfig.getTarget());
Cal Peyser2fe062b2017-02-21 23:47:43 +0000854
855 Attribute.Transition ruleclassTransition = null;
856 if (targetAndConfig.getTarget().getAssociatedRule() != null) {
857 ruleclassTransition = targetAndConfig
858 .getTarget()
859 .getAssociatedRule()
860 .getRuleClassObject()
861 .getTransition();
862 }
Greg Estren7883bf12016-11-18 20:03:43 +0000863 if (targetAndConfig.getConfiguration() != null) {
864 asDeps.put(targetAndConfig.getConfiguration(),
865 Dependency.withTransitionAndAspects(
866 targetAndConfig.getLabel(),
Cal Peyser2fe062b2017-02-21 23:47:43 +0000867 ruleclassTransition == null
868 ? Attribute.ConfigurationTransition.NONE
869 : ruleclassTransition,
Greg Estren7883bf12016-11-18 20:03:43 +0000870 // TODO(bazel-team): support top-level aspects
Dmitry Lomove851fe22017-02-14 23:11:23 +0000871 AspectCollection.EMPTY));
Greg Estren7971e672016-06-01 23:22:48 +0000872 }
873 }
874
Greg Estren7883bf12016-11-18 20:03:43 +0000875 // Maps <target, originalConfig> pairs to <target, dynamicConfig> pairs for targets that
876 // could be successfully Skyframe-evaluated.
877 Map<TargetAndConfiguration, TargetAndConfiguration> successfullyEvaluatedTargets =
878 new LinkedHashMap<>();
Greg Estren7971e672016-06-01 23:22:48 +0000879 if (!asDeps.isEmpty()) {
Greg Estren7883bf12016-11-18 20:03:43 +0000880 for (BuildConfiguration fromConfig : asDeps.keySet()) {
Greg Estren0db9b112016-12-05 21:55:54 +0000881 Multimap<Dependency, BuildConfiguration> trimmedTargets =
Greg Estren7883bf12016-11-18 20:03:43 +0000882 skyframeExecutor.getConfigurations(eventHandler, fromConfig.getOptions(),
883 asDeps.get(fromConfig));
Greg Estren0db9b112016-12-05 21:55:54 +0000884 for (Map.Entry<Dependency, BuildConfiguration> trimmedTarget : trimmedTargets.entries()) {
Greg Estren7883bf12016-11-18 20:03:43 +0000885 Target target = labelsToTargets.get(trimmedTarget.getKey().getLabel());
886 successfullyEvaluatedTargets.put(
887 new TargetAndConfiguration(target, fromConfig),
888 new TargetAndConfiguration(target, trimmedTarget.getValue()));
889 }
Greg Estren7971e672016-06-01 23:22:48 +0000890 }
891 }
892
893 ImmutableList.Builder<TargetAndConfiguration> result =
894 ImmutableList.<TargetAndConfiguration>builder();
895 for (TargetAndConfiguration originalInput : inputs) {
Greg Estren7883bf12016-11-18 20:03:43 +0000896 if (successfullyEvaluatedTargets.containsKey(originalInput)) {
Greg Estren7971e672016-06-01 23:22:48 +0000897 // The configuration was successfully trimmed.
Greg Estren7883bf12016-11-18 20:03:43 +0000898 result.add(successfullyEvaluatedTargets.get(originalInput));
Greg Estren7971e672016-06-01 23:22:48 +0000899 } else {
900 // Either the configuration couldn't be determined (e.g. loading phase error) or it's null.
901 result.add(originalInput);
902 }
903 }
904 return result.build();
905 }
906
Greg Estren01a78e72016-06-17 16:16:16 +0000907 /**
Greg Estren1d8ba902016-09-21 21:18:19 +0000908 * Gets a dynamic configuration for the given target.
909 *
910 * <p>If {@link BuildConfiguration.Options#trimConfigurations()} is true, the configuration only
911 * includes the fragments needed by the fragment and its transitive closure. Else unconditionally
912 * includes all fragments.
Greg Estren01a78e72016-06-17 16:16:16 +0000913 */
914 @VisibleForTesting
Greg Estren1d8ba902016-09-21 21:18:19 +0000915 public BuildConfiguration getDynamicConfigurationForTesting(Target target,
916 BuildConfiguration config, EventHandler eventHandler) throws InterruptedException {
917 return Iterables.getOnlyElement(getDynamicConfigurations(
Greg Estren01a78e72016-06-17 16:16:16 +0000918 ImmutableList.<TargetAndConfiguration>of(new TargetAndConfiguration(target, config)),
919 eventHandler)).getConfiguration();
920 }
Greg Estren7971e672016-06-01 23:22:48 +0000921
922 /**
Ulf Adamsa385d3e2015-09-28 13:21:45 +0000923 * Sets the possible artifact roots in the artifact factory. This allows the factory to resolve
924 * paths with unknown roots to artifacts.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100925 */
926 @VisibleForTesting // for BuildViewTestCase
Kristina Chodorow94e27422016-08-25 14:17:30 +0000927 public void setArtifactRoots(ImmutableMap<PackageIdentifier, Path> packageRoots) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100928 Map<Path, Root> rootMap = new HashMap<>();
929 Map<PackageIdentifier, Root> realPackageRoots = new HashMap<>();
930 for (Map.Entry<PackageIdentifier, Path> entry : packageRoots.entrySet()) {
931 Root root = rootMap.get(entry.getValue());
932 if (root == null) {
Kristina Chodorow3fd3f1b2016-09-08 14:27:10 +0000933 root = Root.asSourceRoot(entry.getValue(), entry.getKey().getRepository().isMain());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100934 rootMap.put(entry.getValue(), root);
935 }
936 realPackageRoots.put(entry.getKey(), root);
937 }
938 // Source Artifact roots:
Ulf Adams89eefd72015-09-23 08:00:43 +0000939 getArtifactFactory().setPackageRoots(realPackageRoots);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100940 }
941
942 /**
Ulf Adams9c505cb2015-09-28 13:38:14 +0000943 * Tests and clears the current thread's pending "interrupted" status, and
944 * throws InterruptedException iff it was set.
945 */
946 protected final void pollInterruptedStatus() throws InterruptedException {
947 if (Thread.interrupted()) {
948 throw new InterruptedException();
949 }
950 }
951
952 /**
953 * Drops the analysis cache. If building with Skyframe, targets in {@code topLevelTargets} may
954 * remain in the cache for use during the execution phase.
955 *
956 * @see BuildView.Options#discardAnalysisCache
957 */
958 public void clearAnalysisCache(Collection<ConfiguredTarget> topLevelTargets) {
959 skyframeBuildView.clearAnalysisCache(topLevelTargets);
960 }
961
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000962 // For testing
963 @VisibleForTesting
964 public Iterable<ConfiguredTarget> getDirectPrerequisitesForTesting(
965 EventHandler eventHandler, ConfiguredTarget ct, BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +0000966 throws EvalException, InvalidConfigurationException,
967 InterruptedException, InconsistentAspectOrderException {
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000968 return skyframeExecutor.getConfiguredTargets(
969 eventHandler, ct.getConfiguration(),
970 ImmutableSet.copyOf(
971 getDirectPrerequisiteDependenciesForTesting(eventHandler, ct, configurations).values()),
972 false);
973 }
974
975 @VisibleForTesting
Greg Estrend5353252016-08-11 22:13:31 +0000976 public OrderedSetMultimap<Attribute, Dependency> getDirectPrerequisiteDependenciesForTesting(
Greg Estren373e3e22016-08-09 22:36:51 +0000977 final EventHandler eventHandler, final ConfiguredTarget ct,
978 BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +0000979 throws EvalException, InvalidConfigurationException, InterruptedException,
980 InconsistentAspectOrderException {
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000981 if (!(ct.getTarget() instanceof Rule)) {
Greg Estrend5353252016-08-11 22:13:31 +0000982 return OrderedSetMultimap.create();
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000983 }
984
985 class SilentDependencyResolver extends DependencyResolver {
986 @Override
987 protected void invalidVisibilityReferenceHook(TargetAndConfiguration node, Label label) {
Ulf Adams84901732016-01-28 15:05:16 +0000988 throw new RuntimeException("bad visibility on " + label + " during testing unexpected");
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000989 }
990
991 @Override
992 protected void invalidPackageGroupReferenceHook(TargetAndConfiguration node, Label label) {
Ulf Adams84901732016-01-28 15:05:16 +0000993 throw new RuntimeException("bad package group on " + label + " during testing unexpected");
994 }
995
996 @Override
997 protected void missingEdgeHook(Target from, Label to, NoSuchThingException e) {
998 throw new RuntimeException(
999 "missing dependency from " + from.getLabel() + " to " + to + ": " + e.getMessage(),
1000 e);
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001001 }
1002
1003 @Override
Janak Ramakrishnan03e4f9c2016-08-16 18:59:56 +00001004 protected Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses)
1005 throws InterruptedException {
Ulf Adams2ac20962016-02-01 13:04:54 +00001006 try {
Janak Ramakrishnan03e4f9c2016-08-16 18:59:56 +00001007 return skyframeExecutor.getPackageManager().getTarget(eventHandler, label);
Ulf Adams2ac20962016-02-01 13:04:54 +00001008 } catch (NoSuchThingException e) {
1009 throw new IllegalStateException(e);
1010 }
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001011 }
Greg Estren373e3e22016-08-09 22:36:51 +00001012
1013 @Override
1014 protected List<BuildConfiguration> getConfigurations(
1015 Set<Class<? extends BuildConfiguration.Fragment>> fragments,
1016 Iterable<BuildOptions> buildOptions) {
1017 Preconditions.checkArgument(ct.getConfiguration().fragmentClasses().equals(fragments));
1018 Dependency asDep = Dependency.withTransitionAndAspects(ct.getLabel(),
Dmitry Lomove851fe22017-02-14 23:11:23 +00001019 Attribute.ConfigurationTransition.NONE, AspectCollection.EMPTY);
Greg Estren373e3e22016-08-09 22:36:51 +00001020 ImmutableList.Builder<BuildConfiguration> builder = ImmutableList.builder();
1021 for (BuildOptions options : buildOptions) {
1022 builder.add(Iterables.getOnlyElement(
1023 skyframeExecutor
1024 .getConfigurations(eventHandler, options, ImmutableList.<Dependency>of(asDep))
1025 .values()
1026 ));
1027 }
1028 return builder.build();
1029 }
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001030 }
1031
1032 DependencyResolver dependencyResolver = new SilentDependencyResolver();
1033 TargetAndConfiguration ctgNode =
1034 new TargetAndConfiguration(ct.getTarget(), ct.getConfiguration());
1035 return dependencyResolver.dependentNodeMap(
1036 ctgNode, configurations.getHostConfiguration(), /*aspect=*/ null,
Ulf Adams9c505cb2015-09-28 13:38:14 +00001037 getConfigurableAttributeKeysForTesting(eventHandler, ctgNode));
1038 }
1039
1040 /**
1041 * Returns ConfigMatchingProvider instances corresponding to the configurable attribute keys
1042 * present in this rule's attributes.
1043 */
Lukacs Berki7894c182016-05-10 12:07:01 +00001044 private ImmutableMap<Label, ConfigMatchingProvider> getConfigurableAttributeKeysForTesting(
Ulf Adams9c505cb2015-09-28 13:38:14 +00001045 EventHandler eventHandler, TargetAndConfiguration ctg) {
1046 if (!(ctg.getTarget() instanceof Rule)) {
Lukacs Berki7894c182016-05-10 12:07:01 +00001047 return ImmutableMap.of();
Ulf Adams9c505cb2015-09-28 13:38:14 +00001048 }
1049 Rule rule = (Rule) ctg.getTarget();
Lukacs Berki53e03912016-05-19 16:26:09 +00001050 Map<Label, ConfigMatchingProvider> keys = new LinkedHashMap<>();
Ulf Adams9c505cb2015-09-28 13:38:14 +00001051 RawAttributeMapper mapper = RawAttributeMapper.of(rule);
1052 for (Attribute attribute : rule.getAttributes()) {
1053 for (Label label : mapper.getConfigurabilityKeys(attribute.getName(), attribute.getType())) {
1054 if (BuildType.Selector.isReservedLabel(label)) {
1055 continue;
1056 }
1057 ConfiguredTarget ct = getConfiguredTargetForTesting(
1058 eventHandler, label, ctg.getConfiguration());
Lukacs Berki7894c182016-05-10 12:07:01 +00001059 keys.put(label, Preconditions.checkNotNull(ct.getProvider(ConfigMatchingProvider.class)));
Ulf Adams9c505cb2015-09-28 13:38:14 +00001060 }
1061 }
Lukacs Berki53e03912016-05-19 16:26:09 +00001062 return ImmutableMap.copyOf(keys);
Ulf Adams9c505cb2015-09-28 13:38:14 +00001063 }
1064
Greg Estrend5353252016-08-11 22:13:31 +00001065 private OrderedSetMultimap<Attribute, ConfiguredTarget> getPrerequisiteMapForTesting(
Ulf Adams24e813a2015-09-28 14:34:08 +00001066 final EventHandler eventHandler, ConfiguredTarget target,
Greg Estren373e3e22016-08-09 22:36:51 +00001067 BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +00001068 throws EvalException, InvalidConfigurationException,
1069 InterruptedException, InconsistentAspectOrderException {
Greg Estrend5353252016-08-11 22:13:31 +00001070 OrderedSetMultimap<Attribute, Dependency> depNodeNames =
1071 getDirectPrerequisiteDependenciesForTesting(eventHandler, target, configurations);
Ulf Adams9c505cb2015-09-28 13:38:14 +00001072
Greg Estren0db9b112016-12-05 21:55:54 +00001073 ImmutableMultimap<Dependency, ConfiguredTarget> cts = skyframeExecutor.getConfiguredTargetMap(
Ulf Adams9c505cb2015-09-28 13:38:14 +00001074 eventHandler,
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001075 target.getConfiguration(), ImmutableSet.copyOf(depNodeNames.values()), false);
Ulf Adams9c505cb2015-09-28 13:38:14 +00001076
Greg Estrend5353252016-08-11 22:13:31 +00001077 OrderedSetMultimap<Attribute, ConfiguredTarget> result = OrderedSetMultimap.create();
Ulf Adams9c505cb2015-09-28 13:38:14 +00001078 for (Map.Entry<Attribute, Dependency> entry : depNodeNames.entries()) {
Greg Estren0db9b112016-12-05 21:55:54 +00001079 result.putAll(entry.getKey(), cts.get(entry.getValue()));
Ulf Adams9c505cb2015-09-28 13:38:14 +00001080 }
Greg Estrend5353252016-08-11 22:13:31 +00001081 return result;
Ulf Adams9c505cb2015-09-28 13:38:14 +00001082 }
1083
1084 /**
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001085 * Returns a configured target for the specified target and configuration. Returns {@code null}
1086 * if something goes wrong.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001087 */
1088 @VisibleForTesting
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001089 public ConfiguredTarget getConfiguredTargetForTesting(
1090 EventHandler eventHandler, Label label, BuildConfiguration config) {
1091 return skyframeExecutor.getConfiguredTargetForTesting(eventHandler, label, config);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001092 }
1093
1094 /**
1095 * Returns a RuleContext which is the same as the original RuleContext of the target parameter.
1096 */
1097 @VisibleForTesting
Florian Weikert4b67d4f2015-09-14 13:35:34 +00001098 public RuleContext getRuleContextForTesting(
Ulf Adamse7704672015-09-21 14:37:41 +00001099 ConfiguredTarget target, StoredEventHandler eventHandler,
Lukacs Berki76cb02e2017-02-17 14:06:11 +00001100 BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +00001101 throws EvalException, InvalidConfigurationException, InterruptedException,
1102 InconsistentAspectOrderException {
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001103 BuildConfiguration targetConfig = target.getConfiguration();
1104 CachingAnalysisEnvironment env =
Ulf Adams89eefd72015-09-23 08:00:43 +00001105 new CachingAnalysisEnvironment(getArtifactFactory(),
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001106 new ConfiguredTargetKey(target.getLabel(), targetConfig),
1107 /*isSystemEnv=*/false, targetConfig.extendedSanityChecks(), eventHandler,
Lukacs Berki76cb02e2017-02-17 14:06:11 +00001108 /*skyframeEnv=*/null, targetConfig.isActionsEnabled());
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001109 return getRuleContextForTesting(eventHandler, target, env, configurations);
Ulf Adams79f05212015-02-27 16:40:00 +00001110 }
1111
1112 /**
1113 * Creates and returns a rule context that is equivalent to the one that was used to create the
1114 * given configured target.
1115 */
1116 @VisibleForTesting
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001117 public RuleContext getRuleContextForTesting(EventHandler eventHandler, ConfiguredTarget target,
1118 AnalysisEnvironment env, BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +00001119 throws EvalException, InvalidConfigurationException, InterruptedException,
1120 InconsistentAspectOrderException {
Greg Estren9eb1cf02015-06-26 22:18:35 +00001121 BuildConfiguration targetConfig = target.getConfiguration();
Ulf Adams79f05212015-02-27 16:40:00 +00001122 return new RuleContext.Builder(
Mark Schaller0312f912016-07-22 18:45:02 +00001123 env,
1124 (Rule) target.getTarget(),
Dmitry Lomov15756522016-12-16 16:52:37 +00001125 ImmutableList.<AspectDescriptor>of(),
Mark Schaller0312f912016-07-22 18:45:02 +00001126 targetConfig,
1127 configurations.getHostConfiguration(),
1128 ruleClassProvider.getPrerequisiteValidator(),
1129 ((Rule) target.getTarget()).getRuleClassObject().getConfigurationFragmentPolicy())
1130 .setVisibility(
1131 NestedSetBuilder.<PackageSpecification>create(
1132 Order.STABLE_ORDER, PackageSpecification.everything()))
1133 .setPrerequisites(getPrerequisiteMapForTesting(eventHandler, target, configurations))
1134 .setConfigConditions(ImmutableMap.<Label, ConfigMatchingProvider>of())
1135 .setUniversalFragment(ruleClassProvider.getUniversalFragment())
1136 .build();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001137 }
1138
1139 /**
Googler9263b462015-05-13 19:22:24 +00001140 * For a configured target dependentTarget, returns the desired configured target
1141 * that is depended upon. Useful for obtaining the a target with aspects
1142 * required by the dependent.
1143 */
1144 @VisibleForTesting
1145 public ConfiguredTarget getPrerequisiteConfiguredTargetForTesting(
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001146 EventHandler eventHandler, ConfiguredTarget dependentTarget, Label desiredTarget,
Ulf Adamse7704672015-09-21 14:37:41 +00001147 BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +00001148 throws EvalException, InvalidConfigurationException, InterruptedException,
1149 InconsistentAspectOrderException {
Googler9263b462015-05-13 19:22:24 +00001150 Collection<ConfiguredTarget> configuredTargets =
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001151 getPrerequisiteMapForTesting(eventHandler, dependentTarget, configurations).values();
Googler9263b462015-05-13 19:22:24 +00001152 for (ConfiguredTarget ct : configuredTargets) {
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001153 if (ct.getLabel().equals(desiredTarget)) {
Googler9263b462015-05-13 19:22:24 +00001154 return ct;
1155 }
1156 }
1157 return null;
1158 }
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +00001159
1160 /**
1161 * A converter for loading phase thread count. Since the default is not a true constant, we create
1162 * a converter here to implement the default logic.
1163 */
1164 public static final class LoadingPhaseThreadCountConverter implements Converter<Integer> {
1165 @Override
1166 public Integer convert(String input) throws OptionsParsingException {
1167 if ("-1".equals(input)) {
1168 // Reduce thread count while running tests. Test cases are typically small, and large thread
1169 // pools vying for a relatively small number of CPU cores may induce non-optimal
1170 // performance.
1171 return System.getenv("TEST_TMPDIR") == null ? 200 : 5;
1172 }
1173
1174 try {
1175 int result = Integer.decode(input);
1176 if (result < 0) {
1177 throw new OptionsParsingException("'" + input + "' must be at least -1");
1178 }
1179 return result;
1180 } catch (NumberFormatException e) {
1181 throw new OptionsParsingException("'" + input + "' is not an int");
1182 }
1183 }
1184
1185 @Override
1186 public String getTypeDescription() {
1187 return "an integer";
1188 }
1189 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001190}