blob: b9297a2b68d1b2146fc8a8a77b42bf30488efe98 [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;
25import com.google.common.collect.ImmutableSet;
26import com.google.common.collect.Iterables;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010027import com.google.common.collect.Lists;
Greg Estren7883bf12016-11-18 20:03:43 +000028import com.google.common.collect.Multimap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010029import com.google.common.collect.Sets;
30import com.google.common.eventbus.EventBus;
Rumou Duan33bab462016-04-25 17:55:12 +000031import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010032import com.google.devtools.build.lib.actions.ActionGraph;
33import com.google.devtools.build.lib.actions.Artifact;
34import com.google.devtools.build.lib.actions.ArtifactFactory;
Eric Fellheimer9c1e12f2015-08-06 20:23:55 +000035import com.google.devtools.build.lib.actions.ArtifactOwner;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010036import com.google.devtools.build.lib.actions.Root;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010037import com.google.devtools.build.lib.analysis.config.BinTools;
38import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
39import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection;
Greg Estren373e3e22016-08-09 22:36:51 +000040import com.google.devtools.build.lib.analysis.config.BuildOptions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010041import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
Greg Estren373e3e22016-08-09 22:36:51 +000042import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000043import com.google.devtools.build.lib.cmdline.Label;
Kristina Chodorow73fa2032015-08-28 17:57:46 +000044import com.google.devtools.build.lib.cmdline.PackageIdentifier;
Lukacs Berki6916be22015-02-19 13:36:06 +000045import com.google.devtools.build.lib.collect.nestedset.NestedSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010046import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
47import com.google.devtools.build.lib.collect.nestedset.Order;
48import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010049import com.google.devtools.build.lib.events.Event;
50import com.google.devtools.build.lib.events.EventHandler;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010051import com.google.devtools.build.lib.events.StoredEventHandler;
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000052import com.google.devtools.build.lib.packages.AspectClass;
Dmitry Lomovca9bfa42016-11-15 13:22:36 +000053import com.google.devtools.build.lib.packages.AspectParameters;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010054import com.google.devtools.build.lib.packages.Attribute;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000055import com.google.devtools.build.lib.packages.BuildType;
Dmitry Lomov8ff06452015-10-21 19:16:30 +000056import com.google.devtools.build.lib.packages.NativeAspectClass;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010057import com.google.devtools.build.lib.packages.NoSuchThingException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010058import com.google.devtools.build.lib.packages.PackageSpecification;
59import com.google.devtools.build.lib.packages.RawAttributeMapper;
60import com.google.devtools.build.lib.packages.Rule;
61import com.google.devtools.build.lib.packages.Target;
62import com.google.devtools.build.lib.packages.TargetUtils;
Ulf Adamsd8099362015-11-02 14:56:46 +000063import com.google.devtools.build.lib.pkgcache.LoadingResult;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010064import com.google.devtools.build.lib.rules.test.CoverageReportActionFactory;
Googlercdc90e92015-02-11 00:18:07 +000065import com.google.devtools.build.lib.rules.test.CoverageReportActionFactory.CoverageReportActionsWrapper;
Ulf Adamsfc154ae2015-08-31 12:32:14 +000066import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider;
Eric Fellheimer9c1e12f2015-08-06 20:23:55 +000067import com.google.devtools.build.lib.skyframe.ActionLookupValue;
Dmitry Lomove2033b12015-08-19 16:57:49 +000068import com.google.devtools.build.lib.skyframe.AspectValue;
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000069import com.google.devtools.build.lib.skyframe.AspectValue.AspectKey;
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +000070import com.google.devtools.build.lib.skyframe.AspectValue.AspectValueKey;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010071import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
Greg Estren7971e672016-06-01 23:22:48 +000072import com.google.devtools.build.lib.skyframe.ConfiguredTargetValue;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010073import com.google.devtools.build.lib.skyframe.CoverageReportValue;
Dmitry Lomove2033b12015-08-19 16:57:49 +000074import com.google.devtools.build.lib.skyframe.SkyframeAnalysisResult;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010075import com.google.devtools.build.lib.skyframe.SkyframeBuildView;
76import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
77import com.google.devtools.build.lib.syntax.EvalException;
Dmitry Lomov51aafc12016-11-18 14:02:54 +000078import com.google.devtools.build.lib.syntax.SkylarkImport;
79import com.google.devtools.build.lib.syntax.SkylarkImports;
80import com.google.devtools.build.lib.syntax.SkylarkImports.SkylarkImportSyntaxException;
Greg Estrend5353252016-08-11 22:13:31 +000081import com.google.devtools.build.lib.util.OrderedSetMultimap;
Mark Schaller6df81792015-12-10 18:47:47 +000082import com.google.devtools.build.lib.util.Preconditions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010083import com.google.devtools.build.lib.util.RegexFilter;
84import com.google.devtools.build.lib.vfs.Path;
Dmitry Lomov0b832ce2015-10-20 10:03:14 +000085import com.google.devtools.build.lib.vfs.PathFragment;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010086import com.google.devtools.build.skyframe.SkyKey;
Eric Fellheimer9c1e12f2015-08-06 20:23:55 +000087import com.google.devtools.build.skyframe.WalkableGraph;
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +000088import com.google.devtools.common.options.Converter;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010089import com.google.devtools.common.options.Option;
90import com.google.devtools.common.options.OptionsBase;
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +000091import com.google.devtools.common.options.OptionsParsingException;
Dmitry Lomove2033b12015-08-19 16:57:49 +000092import java.util.ArrayList;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010093import java.util.Collection;
94import java.util.HashMap;
95import java.util.HashSet;
Lukacs Berki53e03912016-05-19 16:26:09 +000096import java.util.LinkedHashMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010097import java.util.LinkedHashSet;
98import java.util.List;
99import java.util.Map;
100import java.util.Set;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100101import java.util.logging.Logger;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100102import javax.annotation.Nullable;
103
104/**
105 * <p>The BuildView presents a semantically-consistent and transitively-closed
106 * dependency graph for some set of packages.
107 *
108 * <h2>Package design</h2>
109 *
110 * <p>This package contains the Blaze dependency analysis framework (aka
111 * "analysis phase"). The goal of this code is to perform semantic analysis of
112 * all of the build targets required for a given build, to report
113 * errors/warnings for any problems in the input, and to construct an "action
114 * graph" (see {@code lib.actions} package) correctly representing the work to
115 * be done during the execution phase of the build.
116 *
117 * <p><b>Configurations</b> the inputs to a build come from two sources: the
118 * intrinsic inputs, specified in the BUILD file, are called <em>targets</em>.
119 * The environmental inputs, coming from the build tool, the command-line, or
120 * configuration files, are called the <em>configuration</em>. Only when a
121 * target and a configuration are combined is there sufficient information to
122 * perform a build. </p>
123 *
124 * <p>Targets are implemented by the {@link Target} hierarchy in the {@code
125 * lib.packages} code. Configurations are implemented by {@link
126 * BuildConfiguration}. The pair of these together is represented by an
127 * instance of class {@link ConfiguredTarget}; this is the root of a hierarchy
128 * with different implementations for each kind of target: source file, derived
129 * file, rules, etc.
130 *
131 * <p>The framework code in this package (as opposed to its subpackages) is
132 * responsible for constructing the {@code ConfiguredTarget} graph for a given
133 * target and configuration, taking care of such issues as:
134 * <ul>
135 * <li>caching common subgraphs.
136 * <li>detecting and reporting cycles.
137 * <li>correct propagation of errors through the graph.
138 * <li>reporting universal errors, such as dependencies from production code
139 * to tests, or to experimental branches.
140 * <li>capturing and replaying errors.
141 * <li>maintaining the graph from one build to the next to
142 * avoid unnecessary recomputation.
143 * <li>checking software licenses.
144 * </ul>
145 *
146 * <p>See also {@link ConfiguredTarget} which documents some important
147 * invariants.
148 */
149public class BuildView {
150
151 /**
152 * Options that affect the <i>mechanism</i> of analysis. These are distinct from {@link
153 * com.google.devtools.build.lib.analysis.config.BuildOptions}, which affect the <i>value</i>
154 * of a BuildConfiguration.
155 */
156 public static class Options extends OptionsBase {
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000157 @Option(
158 name = "loading_phase_threads",
159 defaultValue = "-1",
160 category = "what",
161 converter = LoadingPhaseThreadCountConverter.class,
162 help = "Number of parallel threads to use for the loading/analysis phase."
163 )
164 public int loadingPhaseThreads;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100165
166 @Option(name = "keep_going",
167 abbrev = 'k',
168 defaultValue = "false",
169 category = "strategy",
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000170 help = "Continue as much as possible after an error. While the"
171 + " target that failed, and those that depend on it, cannot be"
172 + " analyzed (or built), the other prerequisites of these"
173 + " targets can be analyzed (or built) all the same.")
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100174 public boolean keepGoing;
175
176 @Option(name = "analysis_warnings_as_errors",
Janak Ramakrishnanae8e9222015-04-28 17:37:13 +0000177 deprecationWarning = "analysis_warnings_as_errors is now a no-op and will be removed in"
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000178 + " an upcoming Blaze release",
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100179 defaultValue = "false",
180 category = "strategy",
181 help = "Treat visible analysis warnings as errors.")
182 public boolean analysisWarningsAsErrors;
183
184 @Option(name = "discard_analysis_cache",
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000185 defaultValue = "false",
186 category = "strategy",
187 help = "Discard the analysis cache immediately after the analysis phase completes."
188 + " Reduces memory usage by ~10%, but makes further incremental builds slower.")
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100189 public boolean discardAnalysisCache;
190
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100191 @Option(name = "experimental_extra_action_filter",
192 defaultValue = "",
193 category = "experimental",
194 converter = RegexFilter.RegexFilterConverter.class,
195 help = "Filters set of targets to schedule extra_actions for.")
196 public RegexFilter extraActionFilter;
197
198 @Option(name = "experimental_extra_action_top_level_only",
199 defaultValue = "false",
200 category = "experimental",
201 help = "Only schedules extra_actions for top level targets.")
202 public boolean extraActionTopLevelOnly;
203
Carmi Grushko9a796de2016-11-13 12:22:30 +0000204 @Option(
205 name = "experimental_extra_action_top_level_only_with_aspects",
206 defaultValue = "true",
207 category = "experimental",
208 help =
209 "If true and --experimental_extra_action_top_level_only=true, will include actions "
210 + "from aspects injected by top-level rules. "
211 + "This is an escape hatch in case commit df9e5e16c370391098c4432779ad4d1c9dd693ca "
212 + "breaks something."
213 )
214 public boolean extraActionTopLevelOnlyWithAspects;
215
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100216 @Option(name = "version_window_for_dirty_node_gc",
217 defaultValue = "0",
218 category = "undocumented",
219 help = "Nodes that have been dirty for more than this many versions will be deleted"
220 + " from the graph upon the next update. Values must be non-negative long integers,"
221 + " or -1 indicating the maximum possible window.")
222 public long versionWindowForDirtyNodeGc;
Ulf Adamsab64e592016-09-05 09:40:13 +0000223
224 @Deprecated
225 @Option(
226 name = "experimental_interleave_loading_and_analysis",
227 defaultValue = "true",
228 category = "experimental",
229 help = "No-op."
230 )
231 public boolean interleaveLoadingAndAnalysis;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100232 }
233
234 private static Logger LOG = Logger.getLogger(BuildView.class.getName());
235
236 private final BlazeDirectories directories;
237
238 private final SkyframeExecutor skyframeExecutor;
239 private final SkyframeBuildView skyframeBuildView;
240
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100241 private final ConfiguredRuleClassProvider ruleClassProvider;
242
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100243 /**
244 * A factory class to create the coverage report action. May be null.
245 */
246 @Nullable private final CoverageReportActionFactory coverageReportActionFactory;
247
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100248 @VisibleForTesting
249 public Set<SkyKey> getSkyframeEvaluatedTargetKeysForTesting() {
250 return skyframeBuildView.getEvaluatedTargetKeys();
251 }
252
253 /** The number of targets freshly evaluated in the last analysis run. */
254 public int getTargetsVisited() {
255 return skyframeBuildView.getEvaluatedTargetKeys().size();
256 }
257
Ulf Adams59dbf682015-09-17 11:36:43 +0000258 public BuildView(BlazeDirectories directories,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100259 ConfiguredRuleClassProvider ruleClassProvider,
260 SkyframeExecutor skyframeExecutor,
Ulf Adams5a96d532015-09-26 09:00:57 +0000261 CoverageReportActionFactory coverageReportActionFactory) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100262 this.directories = directories;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100263 this.coverageReportActionFactory = coverageReportActionFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100264 this.ruleClassProvider = ruleClassProvider;
265 this.skyframeExecutor = Preconditions.checkNotNull(skyframeExecutor);
Ulf Adams89eefd72015-09-23 08:00:43 +0000266 this.skyframeBuildView = skyframeExecutor.getSkyframeBuildView();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100267 }
268
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100269 /**
270 * Returns whether the given configured target has errors.
271 */
272 @VisibleForTesting
273 public boolean hasErrors(ConfiguredTarget configuredTarget) {
274 return configuredTarget == null;
275 }
276
277 /**
278 * Sets the configurations. Not thread-safe. DO NOT CALL except from tests!
279 */
280 @VisibleForTesting
Ulf Adams79f05212015-02-27 16:40:00 +0000281 public void setConfigurationsForTesting(BuildConfigurationCollection configurations) {
Ulf Adams003fe962015-09-26 09:51:39 +0000282 skyframeBuildView.setConfigurations(configurations);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100283 }
284
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100285 public ArtifactFactory getArtifactFactory() {
Ulf Adams89eefd72015-09-23 08:00:43 +0000286 return skyframeBuildView.getArtifactFactory();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100287 }
288
289 @VisibleForTesting
290 WorkspaceStatusAction getLastWorkspaceBuildInfoActionForTesting() {
291 return skyframeExecutor.getLastWorkspaceStatusActionForTesting();
292 }
293
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100294 @Override
295 public int hashCode() {
296 throw new UnsupportedOperationException(); // avoid nondeterminism
297 }
298
299 /**
300 * Return value for {@link BuildView#update} and {@code BuildTool.prepareToBuild}.
301 */
302 public static final class AnalysisResult {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100303 private final ImmutableList<ConfiguredTarget> targetsToBuild;
304 @Nullable private final ImmutableList<ConfiguredTarget> targetsToTest;
305 @Nullable private final String error;
306 private final ActionGraph actionGraph;
307 private final ImmutableSet<Artifact> artifactsToBuild;
308 private final ImmutableSet<ConfiguredTarget> parallelTests;
309 private final ImmutableSet<ConfiguredTarget> exclusiveTests;
310 @Nullable private final TopLevelArtifactContext topLevelContext;
Dmitry Lomove2033b12015-08-19 16:57:49 +0000311 private final ImmutableList<AspectValue> aspects;
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000312 private final ImmutableMap<PackageIdentifier, Path> packageRoots;
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000313 private final String workspaceName;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100314
315 private AnalysisResult(
Dmitry Lomove2033b12015-08-19 16:57:49 +0000316 Collection<ConfiguredTarget> targetsToBuild,
317 Collection<AspectValue> aspects,
318 Collection<ConfiguredTarget> targetsToTest,
319 @Nullable String error,
320 ActionGraph actionGraph,
321 Collection<Artifact> artifactsToBuild,
322 Collection<ConfiguredTarget> parallelTests,
323 Collection<ConfiguredTarget> exclusiveTests,
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000324 TopLevelArtifactContext topLevelContext,
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000325 ImmutableMap<PackageIdentifier, Path> packageRoots,
326 String workspaceName) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100327 this.targetsToBuild = ImmutableList.copyOf(targetsToBuild);
Dmitry Lomove2033b12015-08-19 16:57:49 +0000328 this.aspects = ImmutableList.copyOf(aspects);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100329 this.targetsToTest = targetsToTest == null ? null : ImmutableList.copyOf(targetsToTest);
330 this.error = error;
331 this.actionGraph = actionGraph;
332 this.artifactsToBuild = ImmutableSet.copyOf(artifactsToBuild);
333 this.parallelTests = ImmutableSet.copyOf(parallelTests);
334 this.exclusiveTests = ImmutableSet.copyOf(exclusiveTests);
335 this.topLevelContext = topLevelContext;
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000336 this.packageRoots = packageRoots;
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000337 this.workspaceName = workspaceName;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100338 }
339
340 /**
341 * Returns configured targets to build.
342 */
343 public Collection<ConfiguredTarget> getTargetsToBuild() {
344 return targetsToBuild;
345 }
346
347 /**
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000348 * The map from package names to the package root where each package was found; this is used to
349 * set up the symlink tree.
350 */
351 public ImmutableMap<PackageIdentifier, Path> getPackageRoots() {
352 return packageRoots;
353 }
354
355 /**
Dmitry Lomove2033b12015-08-19 16:57:49 +0000356 * Returns aspects of configured targets to build.
357 *
358 * <p>If this list is empty, build the targets returned by {@code getTargetsToBuild()}.
359 * Otherwise, only build these aspects of the targets returned by {@code getTargetsToBuild()}.
360 */
361 public Collection<AspectValue> getAspects() {
362 return aspects;
363 }
364
365 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100366 * Returns the configured targets to run as tests, or {@code null} if testing was not
367 * requested (e.g. "build" command rather than "test" command).
368 */
369 @Nullable
370 public Collection<ConfiguredTarget> getTargetsToTest() {
371 return targetsToTest;
372 }
373
374 public ImmutableSet<Artifact> getAdditionalArtifactsToBuild() {
375 return artifactsToBuild;
376 }
377
378 public ImmutableSet<ConfiguredTarget> getExclusiveTests() {
379 return exclusiveTests;
380 }
381
382 public ImmutableSet<ConfiguredTarget> getParallelTests() {
383 return parallelTests;
384 }
385
386 /**
387 * Returns an error description (if any).
388 */
389 @Nullable public String getError() {
390 return error;
391 }
392
Ulf Adams988bb212015-08-25 12:51:48 +0000393 public boolean hasError() {
394 return error != null;
395 }
396
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100397 /**
398 * Returns the action graph.
399 */
400 public ActionGraph getActionGraph() {
401 return actionGraph;
402 }
403
404 public TopLevelArtifactContext getTopLevelContext() {
405 return topLevelContext;
406 }
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000407
408 public String getWorkspaceName() {
409 return workspaceName;
410 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100411 }
412
413
414 /**
415 * Returns the collection of configured targets corresponding to any of the provided targets.
416 */
417 @VisibleForTesting
418 static Iterable<? extends ConfiguredTarget> filterTestsByTargets(
419 Collection<? extends ConfiguredTarget> targets,
420 final Set<? extends Target> allowedTargets) {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000421 return Iterables.filter(
422 targets,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100423 new Predicate<ConfiguredTarget>() {
424 @Override
Dmitry Lomove2033b12015-08-19 16:57:49 +0000425 public boolean apply(ConfiguredTarget rule) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100426 return allowedTargets.contains(rule.getTarget());
427 }
428 });
429 }
430
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100431 @ThreadCompatible
Dmitry Lomove2033b12015-08-19 16:57:49 +0000432 public AnalysisResult update(
433 LoadingResult loadingResult,
434 BuildConfigurationCollection configurations,
435 List<String> aspects,
436 Options viewOptions,
437 TopLevelArtifactContext topLevelOptions,
438 EventHandler eventHandler,
Ulf Adams8c4ae672016-03-30 11:20:41 +0000439 EventBus eventBus)
Dmitry Lomove2033b12015-08-19 16:57:49 +0000440 throws ViewCreationFailedException, InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100441 LOG.info("Starting analysis");
442 pollInterruptedStatus();
443
444 skyframeBuildView.resetEvaluatedConfiguredTargetKeysSet();
445
446 Collection<Target> targets = loadingResult.getTargets();
447 eventBus.post(new AnalysisPhaseStartedEvent(targets));
448
Ulf Adams003fe962015-09-26 09:51:39 +0000449 skyframeBuildView.setConfigurations(configurations);
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000450
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100451 // Determine the configurations.
Greg Estren7971e672016-06-01 23:22:48 +0000452 List<TargetAndConfiguration> topLevelTargetsWithConfigs =
453 nodesForTopLevelTargets(configurations, targets, eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100454
Greg Estren7971e672016-06-01 23:22:48 +0000455 List<ConfiguredTargetKey> topLevelCtKeys = Lists.transform(topLevelTargetsWithConfigs,
456 new Function<TargetAndConfiguration, ConfiguredTargetKey>() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100457 @Override
458 public ConfiguredTargetKey apply(TargetAndConfiguration node) {
459 return new ConfiguredTargetKey(node.getLabel(), node.getConfiguration());
460 }
461 });
462
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000463 List<AspectValueKey> aspectKeys = new ArrayList<>();
Dmitry Lomove2033b12015-08-19 16:57:49 +0000464 for (String aspect : aspects) {
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000465 // Syntax: label%aspect
466 int delimiterPosition = aspect.indexOf('%');
467 if (delimiterPosition >= 0) {
John Fielda97e17f2015-11-13 02:19:52 +0000468 // TODO(jfield): For consistency with Skylark loads, the aspect should be specified
469 // as an absolute path. Also, we probably need to do at least basic validation of
470 // path well-formedness here.
Dmitry Lomov51aafc12016-11-18 14:02:54 +0000471 String bzlFileLoadLikeString = aspect.substring(0, delimiterPosition);
472 if (!bzlFileLoadLikeString.startsWith("//") && !bzlFileLoadLikeString.startsWith("@")) {
473 // "Legacy" behavior of '--aspects' parameter.
474 bzlFileLoadLikeString = new PathFragment("/" + bzlFileLoadLikeString).toString();
475 if (bzlFileLoadLikeString.endsWith(".bzl")) {
476 bzlFileLoadLikeString = bzlFileLoadLikeString.substring(0,
477 bzlFileLoadLikeString.length() - ".bzl".length());
478 }
479 }
480 SkylarkImport skylarkImport;
481 try {
482 skylarkImport = SkylarkImports.create(bzlFileLoadLikeString);
483 } catch (SkylarkImportSyntaxException e) {
484 throw new ViewCreationFailedException(
485 String.format("Invalid aspect '%s': %s", aspect, e.getMessage()), e);
486 }
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000487
488 String skylarkFunctionName = aspect.substring(delimiterPosition + 1);
Dmitry Lomov01f85c02016-06-29 06:37:50 +0000489 for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) {
490 if (!(targetSpec.getTarget() instanceof Rule)) {
491 continue;
492 }
Dmitry Lomove2033b12015-08-19 16:57:49 +0000493 aspectKeys.add(
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000494 AspectValue.createSkylarkAspectKey(
495 targetSpec.getLabel(),
Michael Staib04f6f242016-03-01 15:40:29 +0000496 // For invoking top-level aspects, use the top-level configuration for both the
497 // aspect and the base target while the top-level configuration is untrimmed.
498 targetSpec.getConfiguration(),
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000499 targetSpec.getConfiguration(),
Dmitry Lomov51aafc12016-11-18 14:02:54 +0000500 skylarkImport,
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000501 skylarkFunctionName));
Dmitry Lomove2033b12015-08-19 16:57:49 +0000502 }
503 } else {
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000504 final NativeAspectClass aspectFactoryClass =
505 ruleClassProvider.getNativeAspectClassMap().get(aspect);
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000506 if (aspectFactoryClass != null) {
Dmitry Lomov01f85c02016-06-29 06:37:50 +0000507 for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) {
508 if (!(targetSpec.getTarget() instanceof Rule)) {
509 continue;
510 }
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000511 // For invoking top-level aspects, use the top-level configuration for both the
512 // aspect and the base target while the top-level configuration is untrimmed.
513 BuildConfiguration configuration = targetSpec.getConfiguration();
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000514 aspectKeys.add(
515 AspectValue.createAspectKey(
Dmitry Lomov8ff06452015-10-21 19:16:30 +0000516 targetSpec.getLabel(),
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000517 configuration,
518 new AspectDescriptor(aspectFactoryClass, AspectParameters.EMPTY),
519 configuration
520 ));
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000521 }
522 } else {
523 throw new ViewCreationFailedException("Aspect '" + aspect + "' is unknown");
524 }
Dmitry Lomove2033b12015-08-19 16:57:49 +0000525 }
526 }
527
Kristina Chodorow8cb36d62016-08-26 16:14:37 +0000528 skyframeExecutor.injectWorkspaceStatusData(loadingResult.getWorkspaceName());
Dmitry Lomove2033b12015-08-19 16:57:49 +0000529 SkyframeAnalysisResult skyframeAnalysisResult;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100530 try {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000531 skyframeAnalysisResult =
532 skyframeBuildView.configureTargets(
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000533 eventHandler,
534 topLevelCtKeys,
535 aspectKeys,
536 eventBus,
537 viewOptions.keepGoing,
538 viewOptions.loadingPhaseThreads);
Kristina Chodorow94e27422016-08-25 14:17:30 +0000539 setArtifactRoots(skyframeAnalysisResult.getPackageRoots());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100540 } finally {
541 skyframeBuildView.clearInvalidatedConfiguredTargets();
542 }
543
Greg Estren7971e672016-06-01 23:22:48 +0000544 int numTargetsToAnalyze = topLevelTargetsWithConfigs.size();
Dmitry Lomove2033b12015-08-19 16:57:49 +0000545 int numSuccessful = skyframeAnalysisResult.getConfiguredTargets().size();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100546 if (0 < numSuccessful && numSuccessful < numTargetsToAnalyze) {
547 String msg = String.format("Analysis succeeded for only %d of %d top-level targets",
548 numSuccessful, numTargetsToAnalyze);
549 eventHandler.handle(Event.info(msg));
550 LOG.info(msg);
551 }
552
Dmitry Lomove2033b12015-08-19 16:57:49 +0000553 AnalysisResult result =
554 createResult(
Ulf Adams5b9009b2015-09-24 09:52:53 +0000555 eventHandler,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000556 loadingResult,
557 topLevelOptions,
558 viewOptions,
Ulf Adams53abece2016-02-03 08:30:07 +0000559 skyframeAnalysisResult);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100560 LOG.info("Finished analysis");
561 return result;
562 }
563
Dmitry Lomove2033b12015-08-19 16:57:49 +0000564 private AnalysisResult createResult(
Ulf Adams5b9009b2015-09-24 09:52:53 +0000565 EventHandler eventHandler,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000566 LoadingResult loadingResult,
567 TopLevelArtifactContext topLevelOptions,
568 BuildView.Options viewOptions,
Ulf Adams53abece2016-02-03 08:30:07 +0000569 SkyframeAnalysisResult skyframeAnalysisResult)
570 throws InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100571 Collection<Target> testsToRun = loadingResult.getTestsToRun();
Ulf Adams53abece2016-02-03 08:30:07 +0000572 Collection<ConfiguredTarget> configuredTargets = skyframeAnalysisResult.getConfiguredTargets();
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000573 Collection<AspectValue> aspects = skyframeAnalysisResult.getAspects();
574
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100575 Collection<ConfiguredTarget> allTargetsToTest = null;
576 if (testsToRun != null) {
577 // Determine the subset of configured targets that are meant to be run as tests.
Dmitry Lomov8b1a0942015-11-19 15:14:15 +0000578 // Do not remove <ConfiguredTarget>: workaround for Java 7 type inference.
579 allTargetsToTest =
580 Lists.<ConfiguredTarget>newArrayList(
581 filterTestsByTargets(configuredTargets, Sets.newHashSet(testsToRun)));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100582 }
583
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100584 Set<Artifact> artifactsToBuild = new HashSet<>();
585 Set<ConfiguredTarget> parallelTests = new HashSet<>();
586 Set<ConfiguredTarget> exclusiveTests = new HashSet<>();
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000587
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100588 // build-info and build-changelist.
Ulf Adams5b9009b2015-09-24 09:52:53 +0000589 Collection<Artifact> buildInfoArtifacts =
590 skyframeExecutor.getWorkspaceStatusArtifacts(eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100591 Preconditions.checkState(buildInfoArtifacts.size() == 2, buildInfoArtifacts);
592 artifactsToBuild.addAll(buildInfoArtifacts);
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000593
594 // Extra actions
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000595 addExtraActionsIfRequested(viewOptions, configuredTargets, aspects, artifactsToBuild);
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000596
597 // Coverage
598 NestedSet<Artifact> baselineCoverageArtifacts = getBaselineCoverageArtifacts(configuredTargets);
599 Iterables.addAll(artifactsToBuild, baselineCoverageArtifacts);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100600 if (coverageReportActionFactory != null) {
Googlercdc90e92015-02-11 00:18:07 +0000601 CoverageReportActionsWrapper actionsWrapper;
602 actionsWrapper = coverageReportActionFactory.createCoverageReportActionsWrapper(
Ulf Adams5834e2b2016-04-18 12:03:51 +0000603 eventHandler,
604 directories,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100605 allTargetsToTest,
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000606 baselineCoverageArtifacts,
Ulf Adams89eefd72015-09-23 08:00:43 +0000607 getArtifactFactory(),
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100608 CoverageReportValue.ARTIFACT_OWNER);
Googlercdc90e92015-02-11 00:18:07 +0000609 if (actionsWrapper != null) {
Rumou Duan33bab462016-04-25 17:55:12 +0000610 ImmutableList<ActionAnalysisMetadata> actions = actionsWrapper.getActions();
Googlercdc90e92015-02-11 00:18:07 +0000611 skyframeExecutor.injectCoverageReportData(actions);
612 artifactsToBuild.addAll(actionsWrapper.getCoverageOutputs());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100613 }
614 }
615
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000616 // Tests. This must come last, so that the exclusive tests are scheduled after everything else.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100617 scheduleTestsIfRequested(parallelTests, exclusiveTests, topLevelOptions, allTargetsToTest);
618
Janak Ramakrishnan6f9d7d12016-08-09 08:45:34 +0000619 String error = createErrorMessage(loadingResult, skyframeAnalysisResult);
Eric Fellheimer9c1e12f2015-08-06 20:23:55 +0000620
Ulf Adams53abece2016-02-03 08:30:07 +0000621 final WalkableGraph graph = skyframeAnalysisResult.getWalkableGraph();
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000622 final ActionGraph actionGraph =
623 new ActionGraph() {
624 @Nullable
625 @Override
626 public ActionAnalysisMetadata getGeneratingAction(Artifact artifact) {
627 ArtifactOwner artifactOwner = artifact.getArtifactOwner();
628 if (artifactOwner instanceof ActionLookupValue.ActionLookupKey) {
629 SkyKey key = ActionLookupValue.key((ActionLookupValue.ActionLookupKey) artifactOwner);
630 ActionLookupValue val;
631 try {
632 val = (ActionLookupValue) graph.getValue(key);
633 } catch (InterruptedException e) {
634 throw new IllegalStateException(
635 "Interruption not expected from this graph: " + key, e);
636 }
637 return val == null ? null : val.getGeneratingAction(artifact);
638 }
639 return null;
640 }
641 };
Dmitry Lomove2033b12015-08-19 16:57:49 +0000642 return new AnalysisResult(
643 configuredTargets,
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000644 aspects,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000645 allTargetsToTest,
646 error,
647 actionGraph,
648 artifactsToBuild,
649 parallelTests,
650 exclusiveTests,
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000651 topLevelOptions,
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000652 skyframeAnalysisResult.getPackageRoots(),
653 loadingResult.getWorkspaceName());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100654 }
655
Janak Ramakrishnan6f9d7d12016-08-09 08:45:34 +0000656 @Nullable
657 public static String createErrorMessage(
658 LoadingResult loadingResult, @Nullable SkyframeAnalysisResult skyframeAnalysisResult) {
659 return loadingResult.hasTargetPatternError()
660 ? "command succeeded, but there were errors parsing the target pattern"
661 : loadingResult.hasLoadingError()
662 || (skyframeAnalysisResult != null && skyframeAnalysisResult.hasLoadingError())
663 ? "command succeeded, but there were loading phase errors"
664 : (skyframeAnalysisResult != null && skyframeAnalysisResult.hasAnalysisError())
665 ? "command succeeded, but not all targets were analyzed"
666 : null;
667 }
668
Lukacs Berki6916be22015-02-19 13:36:06 +0000669 private static NestedSet<Artifact> getBaselineCoverageArtifacts(
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100670 Collection<ConfiguredTarget> configuredTargets) {
Lukacs Berki6916be22015-02-19 13:36:06 +0000671 NestedSetBuilder<Artifact> baselineCoverageArtifacts = NestedSetBuilder.stableOrder();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100672 for (ConfiguredTarget target : configuredTargets) {
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000673 InstrumentedFilesProvider provider = target.getProvider(InstrumentedFilesProvider.class);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100674 if (provider != null) {
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000675 baselineCoverageArtifacts.addTransitive(provider.getBaselineCoverageArtifacts());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100676 }
677 }
Lukacs Berki6916be22015-02-19 13:36:06 +0000678 return baselineCoverageArtifacts.build();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100679 }
680
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000681 private void addExtraActionsIfRequested(Options viewOptions,
682 Collection<ConfiguredTarget> configuredTargets,
683 Collection<AspectValue> aspects,
684 Set<Artifact> artifactsToBuild) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000685 Iterable<Artifact> extraActionArtifacts =
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000686 concat(
687 addExtraActionsFromTargets(viewOptions, configuredTargets),
688 addExtraActionsFromAspects(viewOptions, aspects));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100689
690 RegexFilter filter = viewOptions.extraActionFilter;
Carmi Grushkobabd4852016-11-18 17:58:09 +0000691 for (Artifact artifact : extraActionArtifacts) {
692 boolean filterMatches =
693 filter == null || filter.isIncluded(artifact.getOwnerLabel().toString());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100694 if (filterMatches) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000695 artifactsToBuild.add(artifact);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100696 }
697 }
698 }
699
Carmi Grushkobabd4852016-11-18 17:58:09 +0000700 private NestedSet<Artifact> addExtraActionsFromTargets(
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000701 BuildView.Options viewOptions, Collection<ConfiguredTarget> configuredTargets) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000702 NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000703 for (ConfiguredTarget target : configuredTargets) {
704 ExtraActionArtifactsProvider provider =
705 target.getProvider(ExtraActionArtifactsProvider.class);
706 if (provider != null) {
707 if (viewOptions.extraActionTopLevelOnly) {
Carmi Grushko9a796de2016-11-13 12:22:30 +0000708 if (!viewOptions.extraActionTopLevelOnlyWithAspects) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000709 builder.addTransitive(provider.getExtraActionArtifacts());
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000710 } else {
Carmi Grushko9a796de2016-11-13 12:22:30 +0000711 // Collect all aspect-classes that topLevel might inject.
712 Set<AspectClass> aspectClasses = new HashSet<>();
713 for (Attribute attr : target.getTarget().getAssociatedRule().getAttributes()) {
714 aspectClasses.addAll(attr.getAspectClasses());
715 }
716
Carmi Grushkobabd4852016-11-18 17:58:09 +0000717 builder.addTransitive(provider.getExtraActionArtifacts());
718 if (!aspectClasses.isEmpty()) {
719 builder.addAll(filterTransitiveExtraActions(provider, aspectClasses));
Carmi Grushko9a796de2016-11-13 12:22:30 +0000720 }
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000721 }
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000722 } else {
723 builder.addTransitive(provider.getTransitiveExtraActionArtifacts());
724 }
725 }
726 }
727 return builder.build();
728 }
729
730 /**
731 * Returns a list of actions from 'provider' that were registered by an aspect from
732 * 'aspectClasses'. All actions in 'provider' are considered - both direct and transitive.
733 */
734 private ImmutableList<Artifact> filterTransitiveExtraActions(
735 ExtraActionArtifactsProvider provider, Set<AspectClass> aspectClasses) {
736 ImmutableList.Builder<Artifact> artifacts = ImmutableList.builder();
737 // Add to 'artifacts' all extra-actions which were registered by aspects which 'topLevel'
738 // might have injected.
Carmi Grushkobabd4852016-11-18 17:58:09 +0000739 for (Artifact artifact : provider.getTransitiveExtraActionArtifacts()) {
740 ArtifactOwner owner = artifact.getArtifactOwner();
741 if (owner instanceof AspectKey) {
742 if (aspectClasses.contains(((AspectKey) owner).getAspectClass())) {
743 artifacts.add(artifact);
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000744 }
745 }
746 }
747 return artifacts.build();
748 }
749
Carmi Grushkobabd4852016-11-18 17:58:09 +0000750 private NestedSet<Artifact> addExtraActionsFromAspects(
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000751 BuildView.Options viewOptions, Collection<AspectValue> aspects) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000752 NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000753 for (AspectValue aspect : aspects) {
754 ExtraActionArtifactsProvider provider =
755 aspect.getConfiguredAspect().getProvider(ExtraActionArtifactsProvider.class);
756 if (provider != null) {
757 if (viewOptions.extraActionTopLevelOnly) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000758 builder.addTransitive(provider.getExtraActionArtifacts());
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000759 } else {
760 builder.addTransitive(provider.getTransitiveExtraActionArtifacts());
761 }
762 }
763 }
764 return builder.build();
765 }
766
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100767 private static void scheduleTestsIfRequested(Collection<ConfiguredTarget> targetsToTest,
768 Collection<ConfiguredTarget> targetsToTestExclusive, TopLevelArtifactContext topLevelOptions,
769 Collection<ConfiguredTarget> allTestTargets) {
Lukacs Berki3f4d4e92015-02-24 10:28:26 +0000770 Set<String> outputGroups = topLevelOptions.outputGroups();
Lukacs Berki1e79b962015-03-03 10:59:21 +0000771 if (!outputGroups.contains(OutputGroupProvider.FILES_TO_COMPILE)
772 && !outputGroups.contains(OutputGroupProvider.COMPILATION_PREREQUISITES)
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100773 && allTestTargets != null) {
774 scheduleTests(targetsToTest, targetsToTestExclusive, allTestTargets,
775 topLevelOptions.runTestsExclusively());
776 }
777 }
778
779
780 /**
781 * Returns set of artifacts representing test results, writing into targetsToTest and
782 * targetsToTestExclusive.
783 */
784 private static void scheduleTests(Collection<ConfiguredTarget> targetsToTest,
785 Collection<ConfiguredTarget> targetsToTestExclusive,
786 Collection<ConfiguredTarget> allTestTargets,
787 boolean isExclusive) {
788 for (ConfiguredTarget target : allTestTargets) {
789 if (target.getTarget() instanceof Rule) {
790 boolean exclusive =
791 isExclusive || TargetUtils.isExclusiveTestRule((Rule) target.getTarget());
792 Collection<ConfiguredTarget> testCollection = exclusive
793 ? targetsToTestExclusive
794 : targetsToTest;
795 testCollection.add(target);
796 }
797 }
798 }
799
Greg Estren7971e672016-06-01 23:22:48 +0000800 /**
801 * Given a set of top-level targets and a configuration collection, returns the appropriate
802 * <Target, Configuration> pair for each target.
803 *
804 * <p>Preserves the original input ordering.
805 */
806 private List<TargetAndConfiguration> nodesForTopLevelTargets(
807 BuildConfigurationCollection configurations, Collection<Target> targets,
808 EventHandler eventHandler) throws InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100809 // We use a hash set here to remove duplicate nodes; this can happen for input files and package
810 // groups.
811 LinkedHashSet<TargetAndConfiguration> nodes = new LinkedHashSet<>(targets.size());
812 for (BuildConfiguration config : configurations.getTargetConfigurations()) {
813 for (Target target : targets) {
814 nodes.add(new TargetAndConfiguration(target,
815 BuildConfigurationCollection.configureTopLevelTarget(config, target)));
816 }
817 }
Greg Estren7971e672016-06-01 23:22:48 +0000818 return configurations.useDynamicConfigurations()
Greg Estren1d8ba902016-09-21 21:18:19 +0000819 ? getDynamicConfigurations(nodes, eventHandler)
Greg Estren7971e672016-06-01 23:22:48 +0000820 : ImmutableList.copyOf(nodes);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100821 }
822
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100823 /**
Greg Estren1d8ba902016-09-21 21:18:19 +0000824 * <p>If {@link BuildConfiguration.Options#trimConfigurations()} is true, transforms a collection
825 * of <Target, Configuration> pairs by trimming each target's
Greg Estren7971e672016-06-01 23:22:48 +0000826 * configuration to only the fragments the target and its transitive dependencies need.
827 *
Greg Estren1d8ba902016-09-21 21:18:19 +0000828 * <p>Else returns configurations that unconditionally include all fragments.
829 *
Greg Estren7971e672016-06-01 23:22:48 +0000830 * <p>Preserves the original input order. Uses original (untrimmed) configurations for targets
831 * that can't be evaluated (e.g. due to loading phase errors).
832 *
833 * <p>This is suitable for feeding {@link ConfiguredTargetValue} keys: as general principle
834 * {@link ConfiguredTarget}s should have exactly as much information in their configurations as
835 * they need to evaluate and no more (e.g. there's no need for Android settings in a C++
836 * configured target).
837 */
838 // TODO(bazel-team): error out early for targets that fail - untrimmed configurations should
839 // never make it through analysis (and especially not seed ConfiguredTargetValues)
Greg Estren1d8ba902016-09-21 21:18:19 +0000840 private List<TargetAndConfiguration> getDynamicConfigurations(
841 Iterable<TargetAndConfiguration> inputs, EventHandler eventHandler)
842 throws InterruptedException {
Greg Estren7883bf12016-11-18 20:03:43 +0000843 Map<Label, Target> labelsToTargets = new LinkedHashMap<>();
844 // We'll get the configs from SkyframeExecutor#getConfigurations, which gets configurations
845 // for deps including transitions. So to satisfy its API we repackage each target as a
846 // Dependency with a NONE transition.
847 Multimap<BuildConfiguration, Dependency> asDeps =
848 ArrayListMultimap.<BuildConfiguration, Dependency>create();
Greg Estren7971e672016-06-01 23:22:48 +0000849
850 for (TargetAndConfiguration targetAndConfig : inputs) {
Greg Estren7883bf12016-11-18 20:03:43 +0000851 labelsToTargets.put(targetAndConfig.getLabel(), targetAndConfig.getTarget());
852 if (targetAndConfig.getConfiguration() != null) {
853 asDeps.put(targetAndConfig.getConfiguration(),
854 Dependency.withTransitionAndAspects(
855 targetAndConfig.getLabel(),
856 Attribute.ConfigurationTransition.NONE,
857 // TODO(bazel-team): support top-level aspects
858 ImmutableSet.<AspectDescriptor>of()));
Greg Estren7971e672016-06-01 23:22:48 +0000859 }
860 }
861
Greg Estren7883bf12016-11-18 20:03:43 +0000862 // Maps <target, originalConfig> pairs to <target, dynamicConfig> pairs for targets that
863 // could be successfully Skyframe-evaluated.
864 Map<TargetAndConfiguration, TargetAndConfiguration> successfullyEvaluatedTargets =
865 new LinkedHashMap<>();
Greg Estren7971e672016-06-01 23:22:48 +0000866 if (!asDeps.isEmpty()) {
Greg Estren7883bf12016-11-18 20:03:43 +0000867 for (BuildConfiguration fromConfig : asDeps.keySet()) {
868 Map<Dependency, BuildConfiguration> trimmedTargets =
869 skyframeExecutor.getConfigurations(eventHandler, fromConfig.getOptions(),
870 asDeps.get(fromConfig));
871 for (Map.Entry<Dependency, BuildConfiguration> trimmedTarget : trimmedTargets.entrySet()) {
872 Target target = labelsToTargets.get(trimmedTarget.getKey().getLabel());
873 successfullyEvaluatedTargets.put(
874 new TargetAndConfiguration(target, fromConfig),
875 new TargetAndConfiguration(target, trimmedTarget.getValue()));
876 }
Greg Estren7971e672016-06-01 23:22:48 +0000877 }
878 }
879
880 ImmutableList.Builder<TargetAndConfiguration> result =
881 ImmutableList.<TargetAndConfiguration>builder();
882 for (TargetAndConfiguration originalInput : inputs) {
Greg Estren7883bf12016-11-18 20:03:43 +0000883 if (successfullyEvaluatedTargets.containsKey(originalInput)) {
Greg Estren7971e672016-06-01 23:22:48 +0000884 // The configuration was successfully trimmed.
Greg Estren7883bf12016-11-18 20:03:43 +0000885 result.add(successfullyEvaluatedTargets.get(originalInput));
Greg Estren7971e672016-06-01 23:22:48 +0000886 } else {
887 // Either the configuration couldn't be determined (e.g. loading phase error) or it's null.
888 result.add(originalInput);
889 }
890 }
891 return result.build();
892 }
893
Greg Estren01a78e72016-06-17 16:16:16 +0000894 /**
Greg Estren1d8ba902016-09-21 21:18:19 +0000895 * Gets a dynamic configuration for the given target.
896 *
897 * <p>If {@link BuildConfiguration.Options#trimConfigurations()} is true, the configuration only
898 * includes the fragments needed by the fragment and its transitive closure. Else unconditionally
899 * includes all fragments.
Greg Estren01a78e72016-06-17 16:16:16 +0000900 */
901 @VisibleForTesting
Greg Estren1d8ba902016-09-21 21:18:19 +0000902 public BuildConfiguration getDynamicConfigurationForTesting(Target target,
903 BuildConfiguration config, EventHandler eventHandler) throws InterruptedException {
904 return Iterables.getOnlyElement(getDynamicConfigurations(
Greg Estren01a78e72016-06-17 16:16:16 +0000905 ImmutableList.<TargetAndConfiguration>of(new TargetAndConfiguration(target, config)),
906 eventHandler)).getConfiguration();
907 }
Greg Estren7971e672016-06-01 23:22:48 +0000908
909 /**
Ulf Adamsa385d3e2015-09-28 13:21:45 +0000910 * Sets the possible artifact roots in the artifact factory. This allows the factory to resolve
911 * paths with unknown roots to artifacts.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100912 */
913 @VisibleForTesting // for BuildViewTestCase
Kristina Chodorow94e27422016-08-25 14:17:30 +0000914 public void setArtifactRoots(ImmutableMap<PackageIdentifier, Path> packageRoots) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100915 Map<Path, Root> rootMap = new HashMap<>();
916 Map<PackageIdentifier, Root> realPackageRoots = new HashMap<>();
917 for (Map.Entry<PackageIdentifier, Path> entry : packageRoots.entrySet()) {
918 Root root = rootMap.get(entry.getValue());
919 if (root == null) {
Kristina Chodorow3fd3f1b2016-09-08 14:27:10 +0000920 root = Root.asSourceRoot(entry.getValue(), entry.getKey().getRepository().isMain());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100921 rootMap.put(entry.getValue(), root);
922 }
923 realPackageRoots.put(entry.getKey(), root);
924 }
925 // Source Artifact roots:
Ulf Adams89eefd72015-09-23 08:00:43 +0000926 getArtifactFactory().setPackageRoots(realPackageRoots);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100927 }
928
929 /**
Ulf Adams9c505cb2015-09-28 13:38:14 +0000930 * Tests and clears the current thread's pending "interrupted" status, and
931 * throws InterruptedException iff it was set.
932 */
933 protected final void pollInterruptedStatus() throws InterruptedException {
934 if (Thread.interrupted()) {
935 throw new InterruptedException();
936 }
937 }
938
939 /**
940 * Drops the analysis cache. If building with Skyframe, targets in {@code topLevelTargets} may
941 * remain in the cache for use during the execution phase.
942 *
943 * @see BuildView.Options#discardAnalysisCache
944 */
945 public void clearAnalysisCache(Collection<ConfiguredTarget> topLevelTargets) {
946 skyframeBuildView.clearAnalysisCache(topLevelTargets);
947 }
948
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000949 // For testing
950 @VisibleForTesting
951 public Iterable<ConfiguredTarget> getDirectPrerequisitesForTesting(
952 EventHandler eventHandler, ConfiguredTarget ct, BuildConfigurationCollection configurations)
Greg Estren373e3e22016-08-09 22:36:51 +0000953 throws EvalException, InvalidConfigurationException, InterruptedException {
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000954 return skyframeExecutor.getConfiguredTargets(
955 eventHandler, ct.getConfiguration(),
956 ImmutableSet.copyOf(
957 getDirectPrerequisiteDependenciesForTesting(eventHandler, ct, configurations).values()),
958 false);
959 }
960
961 @VisibleForTesting
Greg Estrend5353252016-08-11 22:13:31 +0000962 public OrderedSetMultimap<Attribute, Dependency> getDirectPrerequisiteDependenciesForTesting(
Greg Estren373e3e22016-08-09 22:36:51 +0000963 final EventHandler eventHandler, final ConfiguredTarget ct,
964 BuildConfigurationCollection configurations)
965 throws EvalException, InvalidConfigurationException, InterruptedException {
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000966 if (!(ct.getTarget() instanceof Rule)) {
Greg Estrend5353252016-08-11 22:13:31 +0000967 return OrderedSetMultimap.create();
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000968 }
969
970 class SilentDependencyResolver extends DependencyResolver {
971 @Override
972 protected void invalidVisibilityReferenceHook(TargetAndConfiguration node, Label label) {
Ulf Adams84901732016-01-28 15:05:16 +0000973 throw new RuntimeException("bad visibility on " + label + " during testing unexpected");
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000974 }
975
976 @Override
977 protected void invalidPackageGroupReferenceHook(TargetAndConfiguration node, Label label) {
Ulf Adams84901732016-01-28 15:05:16 +0000978 throw new RuntimeException("bad package group on " + label + " during testing unexpected");
979 }
980
981 @Override
982 protected void missingEdgeHook(Target from, Label to, NoSuchThingException e) {
983 throw new RuntimeException(
984 "missing dependency from " + from.getLabel() + " to " + to + ": " + e.getMessage(),
985 e);
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000986 }
987
988 @Override
Janak Ramakrishnan03e4f9c2016-08-16 18:59:56 +0000989 protected Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses)
990 throws InterruptedException {
Ulf Adams2ac20962016-02-01 13:04:54 +0000991 try {
Janak Ramakrishnan03e4f9c2016-08-16 18:59:56 +0000992 return skyframeExecutor.getPackageManager().getTarget(eventHandler, label);
Ulf Adams2ac20962016-02-01 13:04:54 +0000993 } catch (NoSuchThingException e) {
994 throw new IllegalStateException(e);
995 }
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000996 }
Greg Estren373e3e22016-08-09 22:36:51 +0000997
998 @Override
999 protected List<BuildConfiguration> getConfigurations(
1000 Set<Class<? extends BuildConfiguration.Fragment>> fragments,
1001 Iterable<BuildOptions> buildOptions) {
1002 Preconditions.checkArgument(ct.getConfiguration().fragmentClasses().equals(fragments));
1003 Dependency asDep = Dependency.withTransitionAndAspects(ct.getLabel(),
1004 Attribute.ConfigurationTransition.NONE, ImmutableSet.<AspectDescriptor>of());
1005 ImmutableList.Builder<BuildConfiguration> builder = ImmutableList.builder();
1006 for (BuildOptions options : buildOptions) {
1007 builder.add(Iterables.getOnlyElement(
1008 skyframeExecutor
1009 .getConfigurations(eventHandler, options, ImmutableList.<Dependency>of(asDep))
1010 .values()
1011 ));
1012 }
1013 return builder.build();
1014 }
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001015 }
1016
1017 DependencyResolver dependencyResolver = new SilentDependencyResolver();
1018 TargetAndConfiguration ctgNode =
1019 new TargetAndConfiguration(ct.getTarget(), ct.getConfiguration());
1020 return dependencyResolver.dependentNodeMap(
1021 ctgNode, configurations.getHostConfiguration(), /*aspect=*/ null,
Ulf Adams9c505cb2015-09-28 13:38:14 +00001022 getConfigurableAttributeKeysForTesting(eventHandler, ctgNode));
1023 }
1024
1025 /**
1026 * Returns ConfigMatchingProvider instances corresponding to the configurable attribute keys
1027 * present in this rule's attributes.
1028 */
Lukacs Berki7894c182016-05-10 12:07:01 +00001029 private ImmutableMap<Label, ConfigMatchingProvider> getConfigurableAttributeKeysForTesting(
Ulf Adams9c505cb2015-09-28 13:38:14 +00001030 EventHandler eventHandler, TargetAndConfiguration ctg) {
1031 if (!(ctg.getTarget() instanceof Rule)) {
Lukacs Berki7894c182016-05-10 12:07:01 +00001032 return ImmutableMap.of();
Ulf Adams9c505cb2015-09-28 13:38:14 +00001033 }
1034 Rule rule = (Rule) ctg.getTarget();
Lukacs Berki53e03912016-05-19 16:26:09 +00001035 Map<Label, ConfigMatchingProvider> keys = new LinkedHashMap<>();
Ulf Adams9c505cb2015-09-28 13:38:14 +00001036 RawAttributeMapper mapper = RawAttributeMapper.of(rule);
1037 for (Attribute attribute : rule.getAttributes()) {
1038 for (Label label : mapper.getConfigurabilityKeys(attribute.getName(), attribute.getType())) {
1039 if (BuildType.Selector.isReservedLabel(label)) {
1040 continue;
1041 }
1042 ConfiguredTarget ct = getConfiguredTargetForTesting(
1043 eventHandler, label, ctg.getConfiguration());
Lukacs Berki7894c182016-05-10 12:07:01 +00001044 keys.put(label, Preconditions.checkNotNull(ct.getProvider(ConfigMatchingProvider.class)));
Ulf Adams9c505cb2015-09-28 13:38:14 +00001045 }
1046 }
Lukacs Berki53e03912016-05-19 16:26:09 +00001047 return ImmutableMap.copyOf(keys);
Ulf Adams9c505cb2015-09-28 13:38:14 +00001048 }
1049
Greg Estrend5353252016-08-11 22:13:31 +00001050 private OrderedSetMultimap<Attribute, ConfiguredTarget> getPrerequisiteMapForTesting(
Ulf Adams24e813a2015-09-28 14:34:08 +00001051 final EventHandler eventHandler, ConfiguredTarget target,
Greg Estren373e3e22016-08-09 22:36:51 +00001052 BuildConfigurationCollection configurations)
1053 throws EvalException, InvalidConfigurationException, InterruptedException {
Greg Estrend5353252016-08-11 22:13:31 +00001054 OrderedSetMultimap<Attribute, Dependency> depNodeNames =
1055 getDirectPrerequisiteDependenciesForTesting(eventHandler, target, configurations);
Ulf Adams9c505cb2015-09-28 13:38:14 +00001056
1057 ImmutableMap<Dependency, ConfiguredTarget> cts = skyframeExecutor.getConfiguredTargetMap(
1058 eventHandler,
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001059 target.getConfiguration(), ImmutableSet.copyOf(depNodeNames.values()), false);
Ulf Adams9c505cb2015-09-28 13:38:14 +00001060
Greg Estrend5353252016-08-11 22:13:31 +00001061 OrderedSetMultimap<Attribute, ConfiguredTarget> result = OrderedSetMultimap.create();
Ulf Adams9c505cb2015-09-28 13:38:14 +00001062 for (Map.Entry<Attribute, Dependency> entry : depNodeNames.entries()) {
Greg Estrend5353252016-08-11 22:13:31 +00001063 result.put(entry.getKey(), cts.get(entry.getValue()));
Ulf Adams9c505cb2015-09-28 13:38:14 +00001064 }
Greg Estrend5353252016-08-11 22:13:31 +00001065 return result;
Ulf Adams9c505cb2015-09-28 13:38:14 +00001066 }
1067
1068 /**
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001069 * Returns a configured target for the specified target and configuration. Returns {@code null}
1070 * if something goes wrong.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001071 */
1072 @VisibleForTesting
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001073 public ConfiguredTarget getConfiguredTargetForTesting(
1074 EventHandler eventHandler, Label label, BuildConfiguration config) {
1075 return skyframeExecutor.getConfiguredTargetForTesting(eventHandler, label, config);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001076 }
1077
1078 /**
1079 * Returns a RuleContext which is the same as the original RuleContext of the target parameter.
1080 */
1081 @VisibleForTesting
Florian Weikert4b67d4f2015-09-14 13:35:34 +00001082 public RuleContext getRuleContextForTesting(
Ulf Adamse7704672015-09-21 14:37:41 +00001083 ConfiguredTarget target, StoredEventHandler eventHandler,
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001084 BuildConfigurationCollection configurations, BinTools binTools)
Greg Estren373e3e22016-08-09 22:36:51 +00001085 throws EvalException, InvalidConfigurationException, InterruptedException {
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001086 BuildConfiguration targetConfig = target.getConfiguration();
1087 CachingAnalysisEnvironment env =
Ulf Adams89eefd72015-09-23 08:00:43 +00001088 new CachingAnalysisEnvironment(getArtifactFactory(),
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001089 new ConfiguredTargetKey(target.getLabel(), targetConfig),
1090 /*isSystemEnv=*/false, targetConfig.extendedSanityChecks(), eventHandler,
1091 /*skyframeEnv=*/null, targetConfig.isActionsEnabled(), binTools);
1092 return getRuleContextForTesting(eventHandler, target, env, configurations);
Ulf Adams79f05212015-02-27 16:40:00 +00001093 }
1094
1095 /**
1096 * Creates and returns a rule context that is equivalent to the one that was used to create the
1097 * given configured target.
1098 */
1099 @VisibleForTesting
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001100 public RuleContext getRuleContextForTesting(EventHandler eventHandler, ConfiguredTarget target,
1101 AnalysisEnvironment env, BuildConfigurationCollection configurations)
Greg Estren373e3e22016-08-09 22:36:51 +00001102 throws EvalException, InvalidConfigurationException, InterruptedException {
Greg Estren9eb1cf02015-06-26 22:18:35 +00001103 BuildConfiguration targetConfig = target.getConfiguration();
Ulf Adams79f05212015-02-27 16:40:00 +00001104 return new RuleContext.Builder(
Mark Schaller0312f912016-07-22 18:45:02 +00001105 env,
1106 (Rule) target.getTarget(),
1107 null,
Carmi Grushko33aa3062016-11-11 02:45:29 +00001108 null,
Mark Schaller0312f912016-07-22 18:45:02 +00001109 targetConfig,
1110 configurations.getHostConfiguration(),
1111 ruleClassProvider.getPrerequisiteValidator(),
1112 ((Rule) target.getTarget()).getRuleClassObject().getConfigurationFragmentPolicy())
1113 .setVisibility(
1114 NestedSetBuilder.<PackageSpecification>create(
1115 Order.STABLE_ORDER, PackageSpecification.everything()))
1116 .setPrerequisites(getPrerequisiteMapForTesting(eventHandler, target, configurations))
1117 .setConfigConditions(ImmutableMap.<Label, ConfigMatchingProvider>of())
1118 .setUniversalFragment(ruleClassProvider.getUniversalFragment())
1119 .build();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001120 }
1121
1122 /**
Googler9263b462015-05-13 19:22:24 +00001123 * For a configured target dependentTarget, returns the desired configured target
1124 * that is depended upon. Useful for obtaining the a target with aspects
1125 * required by the dependent.
1126 */
1127 @VisibleForTesting
1128 public ConfiguredTarget getPrerequisiteConfiguredTargetForTesting(
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001129 EventHandler eventHandler, ConfiguredTarget dependentTarget, Label desiredTarget,
Ulf Adamse7704672015-09-21 14:37:41 +00001130 BuildConfigurationCollection configurations)
Greg Estren373e3e22016-08-09 22:36:51 +00001131 throws EvalException, InvalidConfigurationException, InterruptedException {
Googler9263b462015-05-13 19:22:24 +00001132 Collection<ConfiguredTarget> configuredTargets =
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001133 getPrerequisiteMapForTesting(eventHandler, dependentTarget, configurations).values();
Googler9263b462015-05-13 19:22:24 +00001134 for (ConfiguredTarget ct : configuredTargets) {
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001135 if (ct.getLabel().equals(desiredTarget)) {
Googler9263b462015-05-13 19:22:24 +00001136 return ct;
1137 }
1138 }
1139 return null;
1140 }
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +00001141
1142 /**
1143 * A converter for loading phase thread count. Since the default is not a true constant, we create
1144 * a converter here to implement the default logic.
1145 */
1146 public static final class LoadingPhaseThreadCountConverter implements Converter<Integer> {
1147 @Override
1148 public Integer convert(String input) throws OptionsParsingException {
1149 if ("-1".equals(input)) {
1150 // Reduce thread count while running tests. Test cases are typically small, and large thread
1151 // pools vying for a relatively small number of CPU cores may induce non-optimal
1152 // performance.
1153 return System.getenv("TEST_TMPDIR") == null ? 200 : 5;
1154 }
1155
1156 try {
1157 int result = Integer.decode(input);
1158 if (result < 0) {
1159 throw new OptionsParsingException("'" + input + "' must be at least -1");
1160 }
1161 return result;
1162 } catch (NumberFormatException e) {
1163 throw new OptionsParsingException("'" + input + "' is not an int");
1164 }
1165 }
1166
1167 @Override
1168 public String getTypeDescription() {
1169 return "an integer";
1170 }
1171 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001172}