blob: c788f5686123e95d3cb24d7e1a5038e973e1d47f [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;
tomlua155b532017-11-08 20:12:47 +010021import com.google.common.base.Preconditions;
Greg Estren7883bf12016-11-18 20:03:43 +000022import com.google.common.collect.ArrayListMultimap;
janakrf3e6f252018-01-18 07:45:12 -080023import com.google.common.collect.Collections2;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010024import com.google.common.collect.ImmutableList;
25import com.google.common.collect.ImmutableMap;
Greg Estren0db9b112016-12-05 21:55:54 +000026import com.google.common.collect.ImmutableMultimap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010027import com.google.common.collect.ImmutableSet;
28import com.google.common.collect.Iterables;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010029import com.google.common.collect.Lists;
Greg Estren7883bf12016-11-18 20:03:43 +000030import com.google.common.collect.Multimap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010031import com.google.common.collect.Sets;
32import com.google.common.eventbus.EventBus;
Rumou Duan33bab462016-04-25 17:55:12 +000033import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010034import com.google.devtools.build.lib.actions.ActionGraph;
janakr93e3eea2017-03-30 22:09:37 +000035import com.google.devtools.build.lib.actions.ActionLookupValue;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010036import com.google.devtools.build.lib.actions.Artifact;
37import com.google.devtools.build.lib.actions.ArtifactFactory;
Eric Fellheimer9c1e12f2015-08-06 20:23:55 +000038import com.google.devtools.build.lib.actions.ArtifactOwner;
janakrae323982017-09-29 21:11:53 +020039import com.google.devtools.build.lib.actions.PackageRoots;
Dmitry Lomovd83af9e2017-02-23 15:44:23 +000040import com.google.devtools.build.lib.analysis.DependencyResolver.InconsistentAspectOrderException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010041import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
42import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection;
Greg Estren373e3e22016-08-09 22:36:51 +000043import com.google.devtools.build.lib.analysis.config.BuildOptions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010044import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
juliexxia8ee423d2017-10-18 16:36:57 -040045import com.google.devtools.build.lib.analysis.config.ConfigurationResolver;
janakra39a5622018-01-24 08:43:35 -080046import com.google.devtools.build.lib.analysis.config.FragmentClassSet;
Greg Estren373e3e22016-08-09 22:36:51 +000047import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
gregcebe55e112018-01-30 11:04:53 -080048import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
gregce7fa23ea2018-01-18 12:46:04 -080049import com.google.devtools.build.lib.analysis.config.transitions.NoTransition;
gregce45ae0962017-07-22 00:11:13 +020050import com.google.devtools.build.lib.analysis.constraints.TopLevelConstraintSemantics;
ulfjackab21d182017-08-10 15:36:14 +020051import com.google.devtools.build.lib.analysis.test.CoverageReportActionFactory;
52import com.google.devtools.build.lib.analysis.test.CoverageReportActionFactory.CoverageReportActionsWrapper;
53import com.google.devtools.build.lib.analysis.test.InstrumentedFilesProvider;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000054import com.google.devtools.build.lib.cmdline.Label;
Lukacs Berki6916be22015-02-19 13:36:06 +000055import com.google.devtools.build.lib.collect.nestedset.NestedSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010056import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
57import com.google.devtools.build.lib.collect.nestedset.Order;
58import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010059import com.google.devtools.build.lib.events.Event;
Klaus Aehlig777b30d2017-02-24 16:30:15 +000060import com.google.devtools.build.lib.events.ExtendedEventHandler;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010061import com.google.devtools.build.lib.events.StoredEventHandler;
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000062import com.google.devtools.build.lib.packages.AspectClass;
Dmitry Lomov15756522016-12-16 16:52:37 +000063import com.google.devtools.build.lib.packages.AspectDescriptor;
Dmitry Lomovca9bfa42016-11-15 13:22:36 +000064import com.google.devtools.build.lib.packages.AspectParameters;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010065import com.google.devtools.build.lib.packages.Attribute;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000066import com.google.devtools.build.lib.packages.BuildType;
Dmitry Lomov8ff06452015-10-21 19:16:30 +000067import com.google.devtools.build.lib.packages.NativeAspectClass;
Cal Peyser8a638d52017-03-24 15:44:24 +000068import com.google.devtools.build.lib.packages.NoSuchPackageException;
69import com.google.devtools.build.lib.packages.NoSuchTargetException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010070import com.google.devtools.build.lib.packages.NoSuchThingException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010071import com.google.devtools.build.lib.packages.PackageSpecification;
cushon34ff85e2017-11-15 08:59:27 -080072import com.google.devtools.build.lib.packages.PackageSpecification.PackageGroupContents;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010073import com.google.devtools.build.lib.packages.RawAttributeMapper;
74import com.google.devtools.build.lib.packages.Rule;
Michael Staib2a675202017-03-20 18:06:48 +000075import com.google.devtools.build.lib.packages.RuleTransitionFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010076import com.google.devtools.build.lib.packages.Target;
77import com.google.devtools.build.lib.packages.TargetUtils;
Ulf Adamsd8099362015-11-02 14:56:46 +000078import com.google.devtools.build.lib.pkgcache.LoadingResult;
mjhalupka7675dbd2018-01-29 12:46:58 -080079import com.google.devtools.build.lib.pkgcache.PackageManager;
nharmatac4335cf2017-07-18 21:39:13 +020080import com.google.devtools.build.lib.pkgcache.PackageManager.PackageManagerStatistics;
Dmitry Lomove2033b12015-08-19 16:57:49 +000081import com.google.devtools.build.lib.skyframe.AspectValue;
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000082import com.google.devtools.build.lib.skyframe.AspectValue.AspectKey;
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +000083import com.google.devtools.build.lib.skyframe.AspectValue.AspectValueKey;
janakr9c101402018-03-10 06:48:59 -080084import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010085import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
86import com.google.devtools.build.lib.skyframe.CoverageReportValue;
Dmitry Lomove2033b12015-08-19 16:57:49 +000087import com.google.devtools.build.lib.skyframe.SkyframeAnalysisResult;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010088import com.google.devtools.build.lib.skyframe.SkyframeBuildView;
89import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
cpeyser1099b542017-09-06 18:19:20 +020090import com.google.devtools.build.lib.skyframe.ToolchainUtil.ToolchainContextException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010091import com.google.devtools.build.lib.syntax.EvalException;
Dmitry Lomov51aafc12016-11-18 14:02:54 +000092import com.google.devtools.build.lib.syntax.SkylarkImport;
93import com.google.devtools.build.lib.syntax.SkylarkImports;
94import com.google.devtools.build.lib.syntax.SkylarkImports.SkylarkImportSyntaxException;
Greg Estrend5353252016-08-11 22:13:31 +000095import com.google.devtools.build.lib.util.OrderedSetMultimap;
Klaus Aehligc27b4da2017-09-01 10:33:22 +020096import com.google.devtools.build.lib.util.Pair;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010097import com.google.devtools.build.lib.util.RegexFilter;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010098import com.google.devtools.build.skyframe.SkyKey;
Eric Fellheimer9c1e12f2015-08-06 20:23:55 +000099import com.google.devtools.build.skyframe.WalkableGraph;
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000100import com.google.devtools.common.options.Converter;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100101import com.google.devtools.common.options.Option;
ccalvarin3bc15472017-06-27 17:58:35 +0200102import com.google.devtools.common.options.OptionDocumentationCategory;
ccalvarinc82a1972017-07-17 21:13:39 +0200103import com.google.devtools.common.options.OptionEffectTag;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100104import com.google.devtools.common.options.OptionsBase;
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000105import com.google.devtools.common.options.OptionsParsingException;
Dmitry Lomove2033b12015-08-19 16:57:49 +0000106import java.util.ArrayList;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100107import java.util.Collection;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100108import java.util.HashSet;
Lukacs Berki53e03912016-05-19 16:26:09 +0000109import java.util.LinkedHashMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100110import java.util.LinkedHashSet;
111import java.util.List;
112import java.util.Map;
113import java.util.Set;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100114import java.util.logging.Logger;
mjhalupka7675dbd2018-01-29 12:46:58 -0800115import java.util.stream.Collectors;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100116import javax.annotation.Nullable;
117
118/**
119 * <p>The BuildView presents a semantically-consistent and transitively-closed
120 * dependency graph for some set of packages.
121 *
122 * <h2>Package design</h2>
123 *
124 * <p>This package contains the Blaze dependency analysis framework (aka
125 * "analysis phase"). The goal of this code is to perform semantic analysis of
126 * all of the build targets required for a given build, to report
127 * errors/warnings for any problems in the input, and to construct an "action
128 * graph" (see {@code lib.actions} package) correctly representing the work to
129 * be done during the execution phase of the build.
130 *
131 * <p><b>Configurations</b> the inputs to a build come from two sources: the
132 * intrinsic inputs, specified in the BUILD file, are called <em>targets</em>.
133 * The environmental inputs, coming from the build tool, the command-line, or
134 * configuration files, are called the <em>configuration</em>. Only when a
135 * target and a configuration are combined is there sufficient information to
136 * perform a build. </p>
137 *
138 * <p>Targets are implemented by the {@link Target} hierarchy in the {@code
139 * lib.packages} code. Configurations are implemented by {@link
140 * BuildConfiguration}. The pair of these together is represented by an
141 * instance of class {@link ConfiguredTarget}; this is the root of a hierarchy
142 * with different implementations for each kind of target: source file, derived
143 * file, rules, etc.
144 *
145 * <p>The framework code in this package (as opposed to its subpackages) is
146 * responsible for constructing the {@code ConfiguredTarget} graph for a given
147 * target and configuration, taking care of such issues as:
148 * <ul>
149 * <li>caching common subgraphs.
150 * <li>detecting and reporting cycles.
151 * <li>correct propagation of errors through the graph.
152 * <li>reporting universal errors, such as dependencies from production code
153 * to tests, or to experimental branches.
154 * <li>capturing and replaying errors.
155 * <li>maintaining the graph from one build to the next to
156 * avoid unnecessary recomputation.
157 * <li>checking software licenses.
158 * </ul>
159 *
160 * <p>See also {@link ConfiguredTarget} which documents some important
161 * invariants.
162 */
163public class BuildView {
164
165 /**
ccalvarin2eaa02e2017-04-17 23:37:46 +0200166 * Options that affect the <i>mechanism</i> of analysis. These are distinct from {@link
167 * com.google.devtools.build.lib.analysis.config.BuildOptions}, which affect the <i>value</i> of a
168 * BuildConfiguration.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100169 */
170 public static class Options extends OptionsBase {
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000171 @Option(
ccalvarin2eaa02e2017-04-17 23:37:46 +0200172 name = "analysis_warnings_as_errors",
173 deprecationWarning =
174 "analysis_warnings_as_errors is now a no-op and will be removed in"
175 + " an upcoming Blaze release",
176 defaultValue = "false",
177 category = "strategy",
Benjamin Peterson152e4642018-01-25 08:20:20 -0800178 documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
179 effectTags = {OptionEffectTag.NO_OP},
ccalvarin2eaa02e2017-04-17 23:37:46 +0200180 help = "Treat visible analysis warnings as errors."
181 )
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100182 public boolean analysisWarningsAsErrors;
183
ccalvarin2eaa02e2017-04-17 23:37:46 +0200184 @Option(
185 name = "discard_analysis_cache",
186 defaultValue = "false",
187 category = "strategy",
ccalvarin3bc15472017-06-27 17:58:35 +0200188 documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
189 effectTags = {OptionEffectTag.UNKNOWN},
ccalvarin2eaa02e2017-04-17 23:37:46 +0200190 help =
191 "Discard the analysis cache immediately after the analysis phase completes."
192 + " Reduces memory usage by ~10%, but makes further incremental builds slower."
193 )
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100194 public boolean discardAnalysisCache;
195
ccalvarin2eaa02e2017-04-17 23:37:46 +0200196 @Option(
197 name = "experimental_extra_action_filter",
198 defaultValue = "",
199 category = "experimental",
200 converter = RegexFilter.RegexFilterConverter.class,
ccalvarin3bc15472017-06-27 17:58:35 +0200201 documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
202 effectTags = {OptionEffectTag.UNKNOWN},
ccalvarin2eaa02e2017-04-17 23:37:46 +0200203 help = "Filters set of targets to schedule extra_actions for."
204 )
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100205 public RegexFilter extraActionFilter;
206
ccalvarin2eaa02e2017-04-17 23:37:46 +0200207 @Option(
208 name = "experimental_extra_action_top_level_only",
209 defaultValue = "false",
210 category = "experimental",
ccalvarin3bc15472017-06-27 17:58:35 +0200211 documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
212 effectTags = {OptionEffectTag.UNKNOWN},
ccalvarin2eaa02e2017-04-17 23:37:46 +0200213 help = "Only schedules extra_actions for top level targets."
214 )
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100215 public boolean extraActionTopLevelOnly;
216
Carmi Grushko9a796de2016-11-13 12:22:30 +0000217 @Option(
ccalvarin2eaa02e2017-04-17 23:37:46 +0200218 name = "version_window_for_dirty_node_gc",
219 defaultValue = "0",
ccalvarin456adb22017-07-11 14:23:46 +0200220 documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
ccalvarin3bc15472017-06-27 17:58:35 +0200221 effectTags = {OptionEffectTag.UNKNOWN},
ccalvarin2eaa02e2017-04-17 23:37:46 +0200222 help =
223 "Nodes that have been dirty for more than this many versions will be deleted"
224 + " from the graph upon the next update. Values must be non-negative long integers,"
225 + " or -1 indicating the maximum possible window."
226 )
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100227 public long versionWindowForDirtyNodeGc;
Ulf Adamsab64e592016-09-05 09:40:13 +0000228
229 @Deprecated
230 @Option(
231 name = "experimental_interleave_loading_and_analysis",
232 defaultValue = "true",
233 category = "experimental",
ccalvarin3bc15472017-06-27 17:58:35 +0200234 documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
235 effectTags = {OptionEffectTag.UNKNOWN},
Ulf Adamsab64e592016-09-05 09:40:13 +0000236 help = "No-op."
237 )
238 public boolean interleaveLoadingAndAnalysis;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100239 }
240
lberki998ec922017-09-05 10:08:25 +0200241 private static final Logger logger = Logger.getLogger(BuildView.class.getName());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100242
243 private final BlazeDirectories directories;
244
245 private final SkyframeExecutor skyframeExecutor;
246 private final SkyframeBuildView skyframeBuildView;
247
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100248 private final ConfiguredRuleClassProvider ruleClassProvider;
249
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100250 /**
251 * A factory class to create the coverage report action. May be null.
252 */
253 @Nullable private final CoverageReportActionFactory coverageReportActionFactory;
254
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100255 @VisibleForTesting
256 public Set<SkyKey> getSkyframeEvaluatedTargetKeysForTesting() {
257 return skyframeBuildView.getEvaluatedTargetKeys();
258 }
259
260 /** The number of targets freshly evaluated in the last analysis run. */
261 public int getTargetsVisited() {
262 return skyframeBuildView.getEvaluatedTargetKeys().size();
263 }
264
nharmatac4335cf2017-07-18 21:39:13 +0200265 public PackageManagerStatistics getAndClearPkgManagerStatistics() {
266 return skyframeExecutor.getPackageManager().getAndClearStatistics();
267 }
268
Ulf Adams59dbf682015-09-17 11:36:43 +0000269 public BuildView(BlazeDirectories directories,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100270 ConfiguredRuleClassProvider ruleClassProvider,
271 SkyframeExecutor skyframeExecutor,
Ulf Adams5a96d532015-09-26 09:00:57 +0000272 CoverageReportActionFactory coverageReportActionFactory) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100273 this.directories = directories;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100274 this.coverageReportActionFactory = coverageReportActionFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100275 this.ruleClassProvider = ruleClassProvider;
276 this.skyframeExecutor = Preconditions.checkNotNull(skyframeExecutor);
Ulf Adams89eefd72015-09-23 08:00:43 +0000277 this.skyframeBuildView = skyframeExecutor.getSkyframeBuildView();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100278 }
279
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100280 /**
281 * Returns whether the given configured target has errors.
282 */
283 @VisibleForTesting
284 public boolean hasErrors(ConfiguredTarget configuredTarget) {
285 return configuredTarget == null;
286 }
287
288 /**
289 * Sets the configurations. Not thread-safe. DO NOT CALL except from tests!
290 */
291 @VisibleForTesting
Ulf Adams79f05212015-02-27 16:40:00 +0000292 public void setConfigurationsForTesting(BuildConfigurationCollection configurations) {
Ulf Adams003fe962015-09-26 09:51:39 +0000293 skyframeBuildView.setConfigurations(configurations);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100294 }
295
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100296 public ArtifactFactory getArtifactFactory() {
Ulf Adams89eefd72015-09-23 08:00:43 +0000297 return skyframeBuildView.getArtifactFactory();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100298 }
299
300 @VisibleForTesting
janakr1cde8722017-10-10 03:22:21 +0200301 WorkspaceStatusAction getLastWorkspaceBuildInfoActionForTesting() throws InterruptedException {
janakrc8dce992017-09-25 21:48:27 +0200302 return skyframeExecutor.getLastWorkspaceStatusAction();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100303 }
304
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100305 @Override
306 public int hashCode() {
307 throw new UnsupportedOperationException(); // avoid nondeterminism
308 }
309
310 /**
311 * Return value for {@link BuildView#update} and {@code BuildTool.prepareToBuild}.
312 */
313 public static final class AnalysisResult {
gregce45ae0962017-07-22 00:11:13 +0200314 private final ImmutableSet<ConfiguredTarget> targetsToBuild;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100315 @Nullable private final ImmutableList<ConfiguredTarget> targetsToTest;
gregce45ae0962017-07-22 00:11:13 +0200316 private final ImmutableSet<ConfiguredTarget> targetsToSkip;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100317 @Nullable private final String error;
318 private final ActionGraph actionGraph;
319 private final ImmutableSet<Artifact> artifactsToBuild;
320 private final ImmutableSet<ConfiguredTarget> parallelTests;
321 private final ImmutableSet<ConfiguredTarget> exclusiveTests;
322 @Nullable private final TopLevelArtifactContext topLevelContext;
Googler92044992018-03-14 14:26:30 -0700323 private final ImmutableSet<AspectValue> aspects;
janakrae323982017-09-29 21:11:53 +0200324 private final PackageRoots packageRoots;
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000325 private final String workspaceName;
juliexxia693abdc2018-01-03 08:59:18 -0800326 List<TargetAndConfiguration> topLevelTargetsWithConfigs;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100327
328 private AnalysisResult(
Dmitry Lomove2033b12015-08-19 16:57:49 +0000329 Collection<ConfiguredTarget> targetsToBuild,
Googler92044992018-03-14 14:26:30 -0700330 ImmutableSet<AspectValue> aspects,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000331 Collection<ConfiguredTarget> targetsToTest,
gregce45ae0962017-07-22 00:11:13 +0200332 Collection<ConfiguredTarget> targetsToSkip,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000333 @Nullable String error,
334 ActionGraph actionGraph,
335 Collection<Artifact> artifactsToBuild,
336 Collection<ConfiguredTarget> parallelTests,
337 Collection<ConfiguredTarget> exclusiveTests,
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000338 TopLevelArtifactContext topLevelContext,
janakrae323982017-09-29 21:11:53 +0200339 PackageRoots packageRoots,
juliexxia693abdc2018-01-03 08:59:18 -0800340 String workspaceName,
341 List<TargetAndConfiguration> topLevelTargetsWithConfigs) {
gregce45ae0962017-07-22 00:11:13 +0200342 this.targetsToBuild = ImmutableSet.copyOf(targetsToBuild);
Googler92044992018-03-14 14:26:30 -0700343 this.aspects = aspects;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100344 this.targetsToTest = targetsToTest == null ? null : ImmutableList.copyOf(targetsToTest);
gregce45ae0962017-07-22 00:11:13 +0200345 this.targetsToSkip = ImmutableSet.copyOf(targetsToSkip);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100346 this.error = error;
347 this.actionGraph = actionGraph;
348 this.artifactsToBuild = ImmutableSet.copyOf(artifactsToBuild);
349 this.parallelTests = ImmutableSet.copyOf(parallelTests);
350 this.exclusiveTests = ImmutableSet.copyOf(exclusiveTests);
351 this.topLevelContext = topLevelContext;
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000352 this.packageRoots = packageRoots;
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000353 this.workspaceName = workspaceName;
juliexxia693abdc2018-01-03 08:59:18 -0800354 this.topLevelTargetsWithConfigs = topLevelTargetsWithConfigs;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100355 }
356
357 /**
358 * Returns configured targets to build.
359 */
gregce45ae0962017-07-22 00:11:13 +0200360 public ImmutableSet<ConfiguredTarget> getTargetsToBuild() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100361 return targetsToBuild;
362 }
363
janakrae323982017-09-29 21:11:53 +0200364 /** @see PackageRoots */
365 public PackageRoots getPackageRoots() {
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000366 return packageRoots;
367 }
368
369 /**
Dmitry Lomove2033b12015-08-19 16:57:49 +0000370 * Returns aspects of configured targets to build.
371 *
372 * <p>If this list is empty, build the targets returned by {@code getTargetsToBuild()}.
373 * Otherwise, only build these aspects of the targets returned by {@code getTargetsToBuild()}.
374 */
Googler92044992018-03-14 14:26:30 -0700375 public ImmutableSet<AspectValue> getAspects() {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000376 return aspects;
377 }
378
379 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100380 * Returns the configured targets to run as tests, or {@code null} if testing was not
381 * requested (e.g. "build" command rather than "test" command).
382 */
383 @Nullable
384 public Collection<ConfiguredTarget> getTargetsToTest() {
385 return targetsToTest;
386 }
387
gregce45ae0962017-07-22 00:11:13 +0200388 /**
389 * Returns the configured targets that should not be executed because they're not
390 * platform-compatible with the current build.
391 *
392 * <p>For example: tests that aren't intended for the designated CPU.
393 */
394 public ImmutableSet<ConfiguredTarget> getTargetsToSkip() {
395 return targetsToSkip;
396 }
397
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100398 public ImmutableSet<Artifact> getAdditionalArtifactsToBuild() {
399 return artifactsToBuild;
400 }
401
402 public ImmutableSet<ConfiguredTarget> getExclusiveTests() {
403 return exclusiveTests;
404 }
405
406 public ImmutableSet<ConfiguredTarget> getParallelTests() {
407 return parallelTests;
408 }
409
410 /**
411 * Returns an error description (if any).
412 */
413 @Nullable public String getError() {
414 return error;
415 }
416
Ulf Adams988bb212015-08-25 12:51:48 +0000417 public boolean hasError() {
418 return error != null;
419 }
420
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100421 /**
422 * Returns the action graph.
423 */
424 public ActionGraph getActionGraph() {
425 return actionGraph;
426 }
427
428 public TopLevelArtifactContext getTopLevelContext() {
429 return topLevelContext;
430 }
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000431
432 public String getWorkspaceName() {
433 return workspaceName;
434 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100435
juliexxia693abdc2018-01-03 08:59:18 -0800436 public List<TargetAndConfiguration> getTopLevelTargetsWithConfigs() {
437 return topLevelTargetsWithConfigs;
438 }
439 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100440
mjhalupka7675dbd2018-01-29 12:46:58 -0800441 /** Returns the collection of configured targets corresponding to any of the provided targets. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100442 @VisibleForTesting
443 static Iterable<? extends ConfiguredTarget> filterTestsByTargets(
444 Collection<? extends ConfiguredTarget> targets,
mjhalupka7675dbd2018-01-29 12:46:58 -0800445 final Set<? extends Target> allowedTargets,
446 ExtendedEventHandler eventHandler,
447 PackageManager packageManager) {
448 return targets
449 .stream()
450 .filter(
451 ct -> {
452 Target target = null;
453 try {
454 target = packageManager.getTarget(eventHandler, ct.getLabel());
455 } catch (NoSuchTargetException | NoSuchPackageException | InterruptedException e) {
456 eventHandler.handle(
457 Event.error("Failed to get target from package when filtering."));
458 return false;
459 }
460 return allowedTargets.contains(target);
461 })
462 .collect(Collectors.toSet());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100463 }
464
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100465 @ThreadCompatible
Dmitry Lomove2033b12015-08-19 16:57:49 +0000466 public AnalysisResult update(
467 LoadingResult loadingResult,
468 BuildConfigurationCollection configurations,
469 List<String> aspects,
470 Options viewOptions,
juliexxia8a2baea2017-12-18 14:33:45 -0800471 boolean keepGoing,
juliexxiaf8b57c52017-12-21 11:37:46 -0800472 int loadingPhaseThreads,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000473 TopLevelArtifactContext topLevelOptions,
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000474 ExtendedEventHandler eventHandler,
Ulf Adams8c4ae672016-03-30 11:20:41 +0000475 EventBus eventBus)
Dmitry Lomove2033b12015-08-19 16:57:49 +0000476 throws ViewCreationFailedException, InterruptedException {
lberki998ec922017-09-05 10:08:25 +0200477 logger.info("Starting analysis");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100478 pollInterruptedStatus();
479
480 skyframeBuildView.resetEvaluatedConfiguredTargetKeysSet();
481
482 Collection<Target> targets = loadingResult.getTargets();
483 eventBus.post(new AnalysisPhaseStartedEvent(targets));
484
Ulf Adams003fe962015-09-26 09:51:39 +0000485 skyframeBuildView.setConfigurations(configurations);
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000486
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100487 // Determine the configurations.
Greg Estren7971e672016-06-01 23:22:48 +0000488 List<TargetAndConfiguration> topLevelTargetsWithConfigs =
juliexxia8ee423d2017-10-18 16:36:57 -0400489 AnalysisUtils.getTargetsWithConfigs(
490 configurations, targets, eventHandler, ruleClassProvider, skyframeExecutor);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100491
Klaus Aehlig71c993b2017-05-09 07:49:46 -0400492 // Report the generated association of targets to configurations
493 Multimap<Label, BuildConfiguration> byLabel =
494 ArrayListMultimap.<Label, BuildConfiguration>create();
495 for (TargetAndConfiguration pair : topLevelTargetsWithConfigs) {
496 byLabel.put(pair.getLabel(), pair.getConfiguration());
497 }
Klaus Aehlig2a92c902017-08-11 14:03:31 +0200498 for (Target target : targets) {
499 eventBus.post(new TargetConfiguredEvent(target, byLabel.get(target.getLabel())));
Klaus Aehlig71c993b2017-05-09 07:49:46 -0400500 }
501
janakr573807d2018-01-11 14:02:35 -0800502 List<ConfiguredTargetKey> topLevelCtKeys =
503 Lists.transform(
504 topLevelTargetsWithConfigs,
505 new Function<TargetAndConfiguration, ConfiguredTargetKey>() {
506 @Override
507 public ConfiguredTargetKey apply(TargetAndConfiguration node) {
508 return ConfiguredTargetKey.of(node.getLabel(), node.getConfiguration());
509 }
510 });
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100511
Klaus Aehligc27b4da2017-09-01 10:33:22 +0200512 Multimap<Pair<Label, String>, BuildConfiguration> aspectConfigurations =
513 ArrayListMultimap.create();
Klaus Aehlig71c993b2017-05-09 07:49:46 -0400514
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000515 List<AspectValueKey> aspectKeys = new ArrayList<>();
Dmitry Lomove2033b12015-08-19 16:57:49 +0000516 for (String aspect : aspects) {
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000517 // Syntax: label%aspect
518 int delimiterPosition = aspect.indexOf('%');
519 if (delimiterPosition >= 0) {
John Fielda97e17f2015-11-13 02:19:52 +0000520 // TODO(jfield): For consistency with Skylark loads, the aspect should be specified
laurentlb940dbc52018-03-01 08:07:14 -0800521 // as an absolute label.
522 // We convert it for compatibility reasons (this will be removed in the future).
Dmitry Lomov51aafc12016-11-18 14:02:54 +0000523 String bzlFileLoadLikeString = aspect.substring(0, delimiterPosition);
524 if (!bzlFileLoadLikeString.startsWith("//") && !bzlFileLoadLikeString.startsWith("@")) {
525 // "Legacy" behavior of '--aspects' parameter.
laurentlb940dbc52018-03-01 08:07:14 -0800526 if (bzlFileLoadLikeString.startsWith("/")) {
527 bzlFileLoadLikeString = bzlFileLoadLikeString.substring(1);
528 }
529 int lastSlashPosition = bzlFileLoadLikeString.lastIndexOf('/');
530 if (lastSlashPosition >= 0) {
531 bzlFileLoadLikeString =
532 "//"
533 + bzlFileLoadLikeString.substring(0, lastSlashPosition)
534 + ":"
535 + bzlFileLoadLikeString.substring(lastSlashPosition + 1);
536 } else {
537 bzlFileLoadLikeString = "//:" + bzlFileLoadLikeString;
538 }
539 if (!bzlFileLoadLikeString.endsWith(".bzl")) {
540 bzlFileLoadLikeString = bzlFileLoadLikeString + ".bzl";
Dmitry Lomov51aafc12016-11-18 14:02:54 +0000541 }
542 }
543 SkylarkImport skylarkImport;
544 try {
545 skylarkImport = SkylarkImports.create(bzlFileLoadLikeString);
546 } catch (SkylarkImportSyntaxException e) {
547 throw new ViewCreationFailedException(
548 String.format("Invalid aspect '%s': %s", aspect, e.getMessage()), e);
549 }
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000550
551 String skylarkFunctionName = aspect.substring(delimiterPosition + 1);
Dmitry Lomov01f85c02016-06-29 06:37:50 +0000552 for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) {
Klaus Aehligc27b4da2017-09-01 10:33:22 +0200553 aspectConfigurations.put(
554 Pair.of(targetSpec.getLabel(), aspect), targetSpec.getConfiguration());
Dmitry Lomove2033b12015-08-19 16:57:49 +0000555 aspectKeys.add(
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000556 AspectValue.createSkylarkAspectKey(
557 targetSpec.getLabel(),
Michael Staib04f6f242016-03-01 15:40:29 +0000558 // For invoking top-level aspects, use the top-level configuration for both the
559 // aspect and the base target while the top-level configuration is untrimmed.
560 targetSpec.getConfiguration(),
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000561 targetSpec.getConfiguration(),
Dmitry Lomov51aafc12016-11-18 14:02:54 +0000562 skylarkImport,
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000563 skylarkFunctionName));
Dmitry Lomove2033b12015-08-19 16:57:49 +0000564 }
565 } else {
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000566 final NativeAspectClass aspectFactoryClass =
567 ruleClassProvider.getNativeAspectClassMap().get(aspect);
dslomov99ea6b42017-04-25 17:46:17 +0200568
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000569 if (aspectFactoryClass != null) {
Dmitry Lomov01f85c02016-06-29 06:37:50 +0000570 for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) {
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000571 // For invoking top-level aspects, use the top-level configuration for both the
572 // aspect and the base target while the top-level configuration is untrimmed.
573 BuildConfiguration configuration = targetSpec.getConfiguration();
Klaus Aehligc27b4da2017-09-01 10:33:22 +0200574 aspectConfigurations.put(Pair.of(targetSpec.getLabel(), aspect), configuration);
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000575 aspectKeys.add(
576 AspectValue.createAspectKey(
Dmitry Lomov8ff06452015-10-21 19:16:30 +0000577 targetSpec.getLabel(),
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000578 configuration,
dslomovfa50c3d2017-05-08 08:47:44 -0400579 new AspectDescriptor(aspectFactoryClass, AspectParameters.EMPTY),
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000580 configuration
581 ));
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000582 }
583 } else {
584 throw new ViewCreationFailedException("Aspect '" + aspect + "' is unknown");
585 }
Dmitry Lomove2033b12015-08-19 16:57:49 +0000586 }
587 }
588
Klaus Aehligc27b4da2017-09-01 10:33:22 +0200589 for (Pair<Label, String> target : aspectConfigurations.keys()) {
590 eventBus.post(
591 new AspectConfiguredEvent(
592 target.getFirst(), target.getSecond(), aspectConfigurations.get(target)));
593 }
594
janakrc8dce992017-09-25 21:48:27 +0200595 skyframeExecutor.maybeInvalidateWorkspaceStatusValue(loadingResult.getWorkspaceName());
Dmitry Lomove2033b12015-08-19 16:57:49 +0000596 SkyframeAnalysisResult skyframeAnalysisResult;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100597 try {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000598 skyframeAnalysisResult =
599 skyframeBuildView.configureTargets(
juliexxiaf8b57c52017-12-21 11:37:46 -0800600 eventHandler, topLevelCtKeys, aspectKeys, eventBus, keepGoing, loadingPhaseThreads);
Kristina Chodorow94e27422016-08-25 14:17:30 +0000601 setArtifactRoots(skyframeAnalysisResult.getPackageRoots());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100602 } finally {
603 skyframeBuildView.clearInvalidatedConfiguredTargets();
604 }
605
Greg Estren7971e672016-06-01 23:22:48 +0000606 int numTargetsToAnalyze = topLevelTargetsWithConfigs.size();
Dmitry Lomove2033b12015-08-19 16:57:49 +0000607 int numSuccessful = skyframeAnalysisResult.getConfiguredTargets().size();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100608 if (0 < numSuccessful && numSuccessful < numTargetsToAnalyze) {
609 String msg = String.format("Analysis succeeded for only %d of %d top-level targets",
610 numSuccessful, numTargetsToAnalyze);
611 eventHandler.handle(Event.info(msg));
lberki998ec922017-09-05 10:08:25 +0200612 logger.info(msg);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100613 }
614
gregce45ae0962017-07-22 00:11:13 +0200615 Set<ConfiguredTarget> targetsToSkip =
gregce21fdc482017-12-05 16:10:47 -0800616 new TopLevelConstraintSemantics(skyframeExecutor.getPackageManager(), eventHandler)
617 .checkTargetEnvironmentRestrictions(skyframeAnalysisResult.getConfiguredTargets());
gregce45ae0962017-07-22 00:11:13 +0200618
Dmitry Lomove2033b12015-08-19 16:57:49 +0000619 AnalysisResult result =
620 createResult(
Ulf Adams5b9009b2015-09-24 09:52:53 +0000621 eventHandler,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000622 loadingResult,
623 topLevelOptions,
624 viewOptions,
gregce45ae0962017-07-22 00:11:13 +0200625 skyframeAnalysisResult,
juliexxia693abdc2018-01-03 08:59:18 -0800626 targetsToSkip,
627 topLevelTargetsWithConfigs);
lberki998ec922017-09-05 10:08:25 +0200628 logger.info("Finished analysis");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100629 return result;
630 }
631
Dmitry Lomove2033b12015-08-19 16:57:49 +0000632 private AnalysisResult createResult(
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000633 ExtendedEventHandler eventHandler,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000634 LoadingResult loadingResult,
635 TopLevelArtifactContext topLevelOptions,
636 BuildView.Options viewOptions,
gregce45ae0962017-07-22 00:11:13 +0200637 SkyframeAnalysisResult skyframeAnalysisResult,
juliexxia693abdc2018-01-03 08:59:18 -0800638 Set<ConfiguredTarget> targetsToSkip,
639 List<TargetAndConfiguration> topLevelTargetsWithConfigs)
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000640 throws InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100641 Collection<Target> testsToRun = loadingResult.getTestsToRun();
gregce45ae0962017-07-22 00:11:13 +0200642 Set<ConfiguredTarget> configuredTargets =
643 Sets.newLinkedHashSet(skyframeAnalysisResult.getConfiguredTargets());
Googler92044992018-03-14 14:26:30 -0700644 ImmutableSet<AspectValue> aspects = ImmutableSet.copyOf(skyframeAnalysisResult.getAspects());
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000645
gregce45ae0962017-07-22 00:11:13 +0200646 Set<ConfiguredTarget> allTargetsToTest = null;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100647 if (testsToRun != null) {
648 // Determine the subset of configured targets that are meant to be run as tests.
mjhalupka7675dbd2018-01-29 12:46:58 -0800649 allTargetsToTest =
650 Sets.newLinkedHashSet(
651 filterTestsByTargets(
652 configuredTargets,
653 Sets.newHashSet(testsToRun),
654 eventHandler,
655 skyframeExecutor.getPackageManager()));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100656 }
657
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100658 Set<Artifact> artifactsToBuild = new HashSet<>();
659 Set<ConfiguredTarget> parallelTests = new HashSet<>();
660 Set<ConfiguredTarget> exclusiveTests = new HashSet<>();
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000661
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100662 // build-info and build-changelist.
Ulf Adams5b9009b2015-09-24 09:52:53 +0000663 Collection<Artifact> buildInfoArtifacts =
664 skyframeExecutor.getWorkspaceStatusArtifacts(eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100665 Preconditions.checkState(buildInfoArtifacts.size() == 2, buildInfoArtifacts);
666 artifactsToBuild.addAll(buildInfoArtifacts);
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000667
668 // Extra actions
mjhalupka7675dbd2018-01-29 12:46:58 -0800669 addExtraActionsIfRequested(
670 viewOptions, configuredTargets, aspects, artifactsToBuild, eventHandler);
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000671
672 // Coverage
673 NestedSet<Artifact> baselineCoverageArtifacts = getBaselineCoverageArtifacts(configuredTargets);
674 Iterables.addAll(artifactsToBuild, baselineCoverageArtifacts);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100675 if (coverageReportActionFactory != null) {
Googlercdc90e92015-02-11 00:18:07 +0000676 CoverageReportActionsWrapper actionsWrapper;
janakr573807d2018-01-11 14:02:35 -0800677 actionsWrapper =
678 coverageReportActionFactory.createCoverageReportActionsWrapper(
679 eventHandler,
680 directories,
681 allTargetsToTest,
682 baselineCoverageArtifacts,
683 getArtifactFactory(),
684 CoverageReportValue.COVERAGE_REPORT_KEY);
Googlercdc90e92015-02-11 00:18:07 +0000685 if (actionsWrapper != null) {
Rumou Duan33bab462016-04-25 17:55:12 +0000686 ImmutableList<ActionAnalysisMetadata> actions = actionsWrapper.getActions();
Googlercdc90e92015-02-11 00:18:07 +0000687 skyframeExecutor.injectCoverageReportData(actions);
688 artifactsToBuild.addAll(actionsWrapper.getCoverageOutputs());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100689 }
690 }
691
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000692 // Tests. This must come last, so that the exclusive tests are scheduled after everything else.
mjhalupka7675dbd2018-01-29 12:46:58 -0800693 scheduleTestsIfRequested(
694 parallelTests,
695 exclusiveTests,
696 topLevelOptions,
697 allTargetsToTest,
698 skyframeExecutor,
699 eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100700
Janak Ramakrishnan6f9d7d12016-08-09 08:45:34 +0000701 String error = createErrorMessage(loadingResult, skyframeAnalysisResult);
Eric Fellheimer9c1e12f2015-08-06 20:23:55 +0000702
Ulf Adams53abece2016-02-03 08:30:07 +0000703 final WalkableGraph graph = skyframeAnalysisResult.getWalkableGraph();
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000704 final ActionGraph actionGraph =
705 new ActionGraph() {
706 @Nullable
707 @Override
708 public ActionAnalysisMetadata getGeneratingAction(Artifact artifact) {
709 ArtifactOwner artifactOwner = artifact.getArtifactOwner();
710 if (artifactOwner instanceof ActionLookupValue.ActionLookupKey) {
janakr573807d2018-01-11 14:02:35 -0800711 SkyKey key = (ActionLookupValue.ActionLookupKey) artifactOwner;
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000712 ActionLookupValue val;
713 try {
714 val = (ActionLookupValue) graph.getValue(key);
715 } catch (InterruptedException e) {
716 throw new IllegalStateException(
717 "Interruption not expected from this graph: " + key, e);
718 }
janakr93e3eea2017-03-30 22:09:37 +0000719 return val == null ? null : val.getGeneratingActionDangerousReadJavadoc(artifact);
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000720 }
721 return null;
722 }
723 };
Dmitry Lomove2033b12015-08-19 16:57:49 +0000724 return new AnalysisResult(
725 configuredTargets,
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000726 aspects,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000727 allTargetsToTest,
gregce45ae0962017-07-22 00:11:13 +0200728 targetsToSkip,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000729 error,
730 actionGraph,
731 artifactsToBuild,
732 parallelTests,
733 exclusiveTests,
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000734 topLevelOptions,
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000735 skyframeAnalysisResult.getPackageRoots(),
juliexxia693abdc2018-01-03 08:59:18 -0800736 loadingResult.getWorkspaceName(),
737 topLevelTargetsWithConfigs);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100738 }
739
Janak Ramakrishnan6f9d7d12016-08-09 08:45:34 +0000740 @Nullable
741 public static String createErrorMessage(
742 LoadingResult loadingResult, @Nullable SkyframeAnalysisResult skyframeAnalysisResult) {
743 return loadingResult.hasTargetPatternError()
744 ? "command succeeded, but there were errors parsing the target pattern"
745 : loadingResult.hasLoadingError()
746 || (skyframeAnalysisResult != null && skyframeAnalysisResult.hasLoadingError())
747 ? "command succeeded, but there were loading phase errors"
748 : (skyframeAnalysisResult != null && skyframeAnalysisResult.hasAnalysisError())
749 ? "command succeeded, but not all targets were analyzed"
750 : null;
751 }
752
Lukacs Berki6916be22015-02-19 13:36:06 +0000753 private static NestedSet<Artifact> getBaselineCoverageArtifacts(
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100754 Collection<ConfiguredTarget> configuredTargets) {
Lukacs Berki6916be22015-02-19 13:36:06 +0000755 NestedSetBuilder<Artifact> baselineCoverageArtifacts = NestedSetBuilder.stableOrder();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100756 for (ConfiguredTarget target : configuredTargets) {
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000757 InstrumentedFilesProvider provider = target.getProvider(InstrumentedFilesProvider.class);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100758 if (provider != null) {
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000759 baselineCoverageArtifacts.addTransitive(provider.getBaselineCoverageArtifacts());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100760 }
761 }
Lukacs Berki6916be22015-02-19 13:36:06 +0000762 return baselineCoverageArtifacts.build();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100763 }
764
mjhalupka7675dbd2018-01-29 12:46:58 -0800765 private void addExtraActionsIfRequested(
766 Options viewOptions,
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000767 Collection<ConfiguredTarget> configuredTargets,
768 Collection<AspectValue> aspects,
mjhalupka7675dbd2018-01-29 12:46:58 -0800769 Set<Artifact> artifactsToBuild,
770 ExtendedEventHandler eventHandler) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000771 Iterable<Artifact> extraActionArtifacts =
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000772 concat(
mjhalupka7675dbd2018-01-29 12:46:58 -0800773 addExtraActionsFromTargets(viewOptions, configuredTargets, eventHandler),
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000774 addExtraActionsFromAspects(viewOptions, aspects));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100775
776 RegexFilter filter = viewOptions.extraActionFilter;
Carmi Grushkobabd4852016-11-18 17:58:09 +0000777 for (Artifact artifact : extraActionArtifacts) {
778 boolean filterMatches =
779 filter == null || filter.isIncluded(artifact.getOwnerLabel().toString());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100780 if (filterMatches) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000781 artifactsToBuild.add(artifact);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100782 }
783 }
784 }
785
Carmi Grushkobabd4852016-11-18 17:58:09 +0000786 private NestedSet<Artifact> addExtraActionsFromTargets(
mjhalupka7675dbd2018-01-29 12:46:58 -0800787 BuildView.Options viewOptions,
788 Collection<ConfiguredTarget> configuredTargets,
789 ExtendedEventHandler eventHandler) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000790 NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000791 for (ConfiguredTarget target : configuredTargets) {
792 ExtraActionArtifactsProvider provider =
793 target.getProvider(ExtraActionArtifactsProvider.class);
794 if (provider != null) {
795 if (viewOptions.extraActionTopLevelOnly) {
lberki9137a752017-06-09 12:49:10 +0200796 // Collect all aspect-classes that topLevel might inject.
797 Set<AspectClass> aspectClasses = new HashSet<>();
mjhalupka7675dbd2018-01-29 12:46:58 -0800798 Target actualTarget = null;
799 try {
800 actualTarget =
801 skyframeExecutor.getPackageManager().getTarget(eventHandler, target.getLabel());
802 } catch (NoSuchPackageException | NoSuchTargetException | InterruptedException e) {
803 eventHandler.handle(Event.error(""));
804 }
805 for (Attribute attr : actualTarget.getAssociatedRule().getAttributes()) {
lberki9137a752017-06-09 12:49:10 +0200806 aspectClasses.addAll(attr.getAspectClasses());
807 }
Carmi Grushko9a796de2016-11-13 12:22:30 +0000808
lberki9137a752017-06-09 12:49:10 +0200809 builder.addTransitive(provider.getExtraActionArtifacts());
810 if (!aspectClasses.isEmpty()) {
811 builder.addAll(filterTransitiveExtraActions(provider, aspectClasses));
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000812 }
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000813 } else {
814 builder.addTransitive(provider.getTransitiveExtraActionArtifacts());
815 }
816 }
817 }
818 return builder.build();
819 }
820
821 /**
822 * Returns a list of actions from 'provider' that were registered by an aspect from
823 * 'aspectClasses'. All actions in 'provider' are considered - both direct and transitive.
824 */
825 private ImmutableList<Artifact> filterTransitiveExtraActions(
826 ExtraActionArtifactsProvider provider, Set<AspectClass> aspectClasses) {
827 ImmutableList.Builder<Artifact> artifacts = ImmutableList.builder();
828 // Add to 'artifacts' all extra-actions which were registered by aspects which 'topLevel'
829 // might have injected.
Carmi Grushkobabd4852016-11-18 17:58:09 +0000830 for (Artifact artifact : provider.getTransitiveExtraActionArtifacts()) {
831 ArtifactOwner owner = artifact.getArtifactOwner();
832 if (owner instanceof AspectKey) {
833 if (aspectClasses.contains(((AspectKey) owner).getAspectClass())) {
834 artifacts.add(artifact);
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000835 }
836 }
837 }
838 return artifacts.build();
839 }
840
Carmi Grushkobabd4852016-11-18 17:58:09 +0000841 private NestedSet<Artifact> addExtraActionsFromAspects(
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000842 BuildView.Options viewOptions, Collection<AspectValue> aspects) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000843 NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000844 for (AspectValue aspect : aspects) {
845 ExtraActionArtifactsProvider provider =
846 aspect.getConfiguredAspect().getProvider(ExtraActionArtifactsProvider.class);
847 if (provider != null) {
848 if (viewOptions.extraActionTopLevelOnly) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000849 builder.addTransitive(provider.getExtraActionArtifacts());
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000850 } else {
851 builder.addTransitive(provider.getTransitiveExtraActionArtifacts());
852 }
853 }
854 }
855 return builder.build();
856 }
857
mjhalupka7675dbd2018-01-29 12:46:58 -0800858 private static void scheduleTestsIfRequested(
859 Collection<ConfiguredTarget> targetsToTest,
860 Collection<ConfiguredTarget> targetsToTestExclusive,
861 TopLevelArtifactContext topLevelOptions,
862 Collection<ConfiguredTarget> allTestTargets,
863 SkyframeExecutor skyframeExecutor,
864 ExtendedEventHandler eventHandler)
865 throws InterruptedException {
Lukacs Berki3f4d4e92015-02-24 10:28:26 +0000866 Set<String> outputGroups = topLevelOptions.outputGroups();
dslomov69c45f82017-12-14 11:15:43 -0500867 if (!outputGroups.contains(OutputGroupInfo.FILES_TO_COMPILE)
868 && !outputGroups.contains(OutputGroupInfo.COMPILATION_PREREQUISITES)
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100869 && allTestTargets != null) {
mjhalupka7675dbd2018-01-29 12:46:58 -0800870 scheduleTests(
871 targetsToTest,
872 targetsToTestExclusive,
873 allTestTargets,
874 topLevelOptions.runTestsExclusively(),
875 skyframeExecutor,
876 eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100877 }
878 }
879
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100880 /**
881 * Returns set of artifacts representing test results, writing into targetsToTest and
882 * targetsToTestExclusive.
883 */
mjhalupka7675dbd2018-01-29 12:46:58 -0800884 private static void scheduleTests(
885 Collection<ConfiguredTarget> targetsToTest,
886 Collection<ConfiguredTarget> targetsToTestExclusive,
887 Collection<ConfiguredTarget> allTestTargets,
888 boolean isExclusive,
889 SkyframeExecutor skyframeExecutor,
890 ExtendedEventHandler eventHandler)
891 throws InterruptedException {
892 for (ConfiguredTarget configuredTarget : allTestTargets) {
893 Target target = null;
894 try {
895 target =
896 skyframeExecutor
897 .getPackageManager()
898 .getTarget(eventHandler, configuredTarget.getLabel());
899 } catch (NoSuchTargetException | NoSuchPackageException e) {
900 eventHandler.handle(Event.error("Failed to get target when scheduling tests"));
901 continue;
902 }
903 if (target instanceof Rule) {
904 boolean exclusive = isExclusive || TargetUtils.isExclusiveTestRule((Rule) target);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100905 Collection<ConfiguredTarget> testCollection = exclusive
906 ? targetsToTestExclusive
907 : targetsToTest;
mjhalupka7675dbd2018-01-29 12:46:58 -0800908 testCollection.add(configuredTarget);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100909 }
910 }
911 }
912
Greg Estren7971e672016-06-01 23:22:48 +0000913 /**
gregce408bfe472017-09-14 00:47:27 +0200914 * Gets a configuration for the given target.
Greg Estren1d8ba902016-09-21 21:18:19 +0000915 *
916 * <p>If {@link BuildConfiguration.Options#trimConfigurations()} is true, the configuration only
917 * includes the fragments needed by the fragment and its transitive closure. Else unconditionally
918 * includes all fragments.
Greg Estren01a78e72016-06-17 16:16:16 +0000919 */
920 @VisibleForTesting
gregce408bfe472017-09-14 00:47:27 +0200921 public BuildConfiguration getConfigurationForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000922 Target target, BuildConfiguration config, ExtendedEventHandler eventHandler)
923 throws InterruptedException {
juliexxia8ee423d2017-10-18 16:36:57 -0400924 List<TargetAndConfiguration> node =
925 ImmutableList.<TargetAndConfiguration>of(new TargetAndConfiguration(target, config));
926 LinkedHashSet<TargetAndConfiguration> configs =
927 ConfigurationResolver.getConfigurationsFromExecutor(
928 node,
929 AnalysisUtils.targetsToDeps(
930 new LinkedHashSet<TargetAndConfiguration>(node), ruleClassProvider),
931 eventHandler,
932 skyframeExecutor);
933 return configs.iterator().next().getConfiguration();
Greg Estren01a78e72016-06-17 16:16:16 +0000934 }
Greg Estren7971e672016-06-01 23:22:48 +0000935
936 /**
Ulf Adamsa385d3e2015-09-28 13:21:45 +0000937 * Sets the possible artifact roots in the artifact factory. This allows the factory to resolve
938 * paths with unknown roots to artifacts.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100939 */
940 @VisibleForTesting // for BuildViewTestCase
janakrae323982017-09-29 21:11:53 +0200941 public void setArtifactRoots(PackageRoots packageRoots) {
942 getArtifactFactory().setPackageRoots(packageRoots.getPackageRootLookup());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100943 }
944
945 /**
Ulf Adams9c505cb2015-09-28 13:38:14 +0000946 * Tests and clears the current thread's pending "interrupted" status, and
947 * throws InterruptedException iff it was set.
948 */
949 protected final void pollInterruptedStatus() throws InterruptedException {
950 if (Thread.interrupted()) {
951 throw new InterruptedException();
952 }
953 }
954
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000955 // For testing
956 @VisibleForTesting
957 public Iterable<ConfiguredTarget> getDirectPrerequisitesForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000958 ExtendedEventHandler eventHandler, ConfiguredTarget ct,
959 BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +0000960 throws EvalException, InvalidConfigurationException,
961 InterruptedException, InconsistentAspectOrderException {
janakrf3e6f252018-01-18 07:45:12 -0800962 return Collections2.transform(
janakr9fcef032018-01-23 13:38:24 -0800963 skyframeExecutor.getConfiguredTargetsForTesting(
janakrf3e6f252018-01-18 07:45:12 -0800964 eventHandler,
965 ct.getConfiguration(),
966 ImmutableSet.copyOf(
967 getDirectPrerequisiteDependenciesForTesting(
968 eventHandler, ct, configurations, /*toolchainContext=*/ null)
969 .values())),
janakr9c101402018-03-10 06:48:59 -0800970 ConfiguredTargetAndData::getConfiguredTarget);
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000971 }
972
973 @VisibleForTesting
Greg Estrend5353252016-08-11 22:13:31 +0000974 public OrderedSetMultimap<Attribute, Dependency> getDirectPrerequisiteDependenciesForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000975 final ExtendedEventHandler eventHandler,
976 final ConfiguredTarget ct,
cpeyserb38e3af2017-09-11 16:58:58 +0200977 BuildConfigurationCollection configurations,
978 ToolchainContext toolchainContext)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +0000979 throws EvalException, InvalidConfigurationException, InterruptedException,
cpeyserb38e3af2017-09-11 16:58:58 +0200980 InconsistentAspectOrderException {
mjhalupka7675dbd2018-01-29 12:46:58 -0800981
982 Target target = null;
983 try {
984 target = skyframeExecutor.getPackageManager().getTarget(eventHandler, ct.getLabel());
985 } catch (NoSuchPackageException | NoSuchTargetException | InterruptedException e) {
986 eventHandler.handle(
987 Event.error("Failed to get target from package during prerequisite analysis." + e));
988 return OrderedSetMultimap.create();
989 }
990
991 if (!(target instanceof Rule)) {
Greg Estrend5353252016-08-11 22:13:31 +0000992 return OrderedSetMultimap.create();
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000993 }
994
995 class SilentDependencyResolver extends DependencyResolver {
gregce85297462017-08-18 21:20:29 +0200996 private SilentDependencyResolver() {
gregce85297462017-08-18 21:20:29 +0200997 }
998
Ulf Adamsa4ca6372016-01-11 14:20:28 +0000999 @Override
1000 protected void invalidVisibilityReferenceHook(TargetAndConfiguration node, Label label) {
Ulf Adams84901732016-01-28 15:05:16 +00001001 throw new RuntimeException("bad visibility on " + label + " during testing unexpected");
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001002 }
1003
1004 @Override
1005 protected void invalidPackageGroupReferenceHook(TargetAndConfiguration node, Label label) {
Ulf Adams84901732016-01-28 15:05:16 +00001006 throw new RuntimeException("bad package group on " + label + " during testing unexpected");
1007 }
1008
1009 @Override
1010 protected void missingEdgeHook(Target from, Label to, NoSuchThingException e) {
1011 throw new RuntimeException(
1012 "missing dependency from " + from.getLabel() + " to " + to + ": " + e.getMessage(),
1013 e);
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001014 }
1015
1016 @Override
Janak Ramakrishnan03e4f9c2016-08-16 18:59:56 +00001017 protected Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses)
1018 throws InterruptedException {
Ulf Adams2ac20962016-02-01 13:04:54 +00001019 try {
Janak Ramakrishnan03e4f9c2016-08-16 18:59:56 +00001020 return skyframeExecutor.getPackageManager().getTarget(eventHandler, label);
Ulf Adams2ac20962016-02-01 13:04:54 +00001021 } catch (NoSuchThingException e) {
1022 throw new IllegalStateException(e);
1023 }
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001024 }
Greg Estren373e3e22016-08-09 22:36:51 +00001025
1026 @Override
1027 protected List<BuildConfiguration> getConfigurations(
janakra39a5622018-01-24 08:43:35 -08001028 FragmentClassSet fragments, Iterable<BuildOptions> buildOptions) {
1029 Preconditions.checkArgument(
1030 ct.getConfiguration().fragmentClasses().equals(fragments),
1031 "Mismatch: %s %s",
1032 ct,
1033 fragments);
Greg Estren373e3e22016-08-09 22:36:51 +00001034 Dependency asDep = Dependency.withTransitionAndAspects(ct.getLabel(),
gregce7fa23ea2018-01-18 12:46:04 -08001035 NoTransition.INSTANCE, AspectCollection.EMPTY);
Greg Estren373e3e22016-08-09 22:36:51 +00001036 ImmutableList.Builder<BuildConfiguration> builder = ImmutableList.builder();
1037 for (BuildOptions options : buildOptions) {
1038 builder.add(Iterables.getOnlyElement(
1039 skyframeExecutor
1040 .getConfigurations(eventHandler, options, ImmutableList.<Dependency>of(asDep))
1041 .values()
1042 ));
1043 }
1044 return builder.build();
1045 }
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001046 }
1047
1048 DependencyResolver dependencyResolver = new SilentDependencyResolver();
mjhalupka7675dbd2018-01-29 12:46:58 -08001049 TargetAndConfiguration ctgNode = new TargetAndConfiguration(target, ct.getConfiguration());
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001050 return dependencyResolver.dependentNodeMap(
cpeyserb38e3af2017-09-11 16:58:58 +02001051 ctgNode,
1052 configurations.getHostConfiguration(),
1053 /*aspect=*/ null,
1054 getConfigurableAttributeKeysForTesting(eventHandler, ctgNode),
juliexxiab892a9a2018-03-16 08:32:31 -07001055 toolchainContext == null
1056 ? ImmutableSet.of()
1057 : toolchainContext.getResolvedToolchainLabels());
Ulf Adams9c505cb2015-09-28 13:38:14 +00001058 }
1059
1060 /**
1061 * Returns ConfigMatchingProvider instances corresponding to the configurable attribute keys
1062 * present in this rule's attributes.
1063 */
Lukacs Berki7894c182016-05-10 12:07:01 +00001064 private ImmutableMap<Label, ConfigMatchingProvider> getConfigurableAttributeKeysForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001065 ExtendedEventHandler eventHandler, TargetAndConfiguration ctg) {
Ulf Adams9c505cb2015-09-28 13:38:14 +00001066 if (!(ctg.getTarget() instanceof Rule)) {
Lukacs Berki7894c182016-05-10 12:07:01 +00001067 return ImmutableMap.of();
Ulf Adams9c505cb2015-09-28 13:38:14 +00001068 }
1069 Rule rule = (Rule) ctg.getTarget();
Lukacs Berki53e03912016-05-19 16:26:09 +00001070 Map<Label, ConfigMatchingProvider> keys = new LinkedHashMap<>();
Ulf Adams9c505cb2015-09-28 13:38:14 +00001071 RawAttributeMapper mapper = RawAttributeMapper.of(rule);
1072 for (Attribute attribute : rule.getAttributes()) {
1073 for (Label label : mapper.getConfigurabilityKeys(attribute.getName(), attribute.getType())) {
1074 if (BuildType.Selector.isReservedLabel(label)) {
1075 continue;
1076 }
1077 ConfiguredTarget ct = getConfiguredTargetForTesting(
1078 eventHandler, label, ctg.getConfiguration());
Lukacs Berki7894c182016-05-10 12:07:01 +00001079 keys.put(label, Preconditions.checkNotNull(ct.getProvider(ConfigMatchingProvider.class)));
Ulf Adams9c505cb2015-09-28 13:38:14 +00001080 }
1081 }
Lukacs Berki53e03912016-05-19 16:26:09 +00001082 return ImmutableMap.copyOf(keys);
Ulf Adams9c505cb2015-09-28 13:38:14 +00001083 }
1084
janakr9c101402018-03-10 06:48:59 -08001085 private OrderedSetMultimap<Attribute, ConfiguredTargetAndData> getPrerequisiteMapForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001086 final ExtendedEventHandler eventHandler,
1087 ConfiguredTarget target,
cpeyserb38e3af2017-09-11 16:58:58 +02001088 BuildConfigurationCollection configurations,
1089 ToolchainContext toolchainContext)
1090 throws EvalException, InvalidConfigurationException, InterruptedException,
1091 InconsistentAspectOrderException {
Greg Estrend5353252016-08-11 22:13:31 +00001092 OrderedSetMultimap<Attribute, Dependency> depNodeNames =
cpeyserb38e3af2017-09-11 16:58:58 +02001093 getDirectPrerequisiteDependenciesForTesting(
1094 eventHandler, target, configurations, toolchainContext);
Ulf Adams9c505cb2015-09-28 13:38:14 +00001095
janakr9c101402018-03-10 06:48:59 -08001096 ImmutableMultimap<Dependency, ConfiguredTargetAndData> cts =
janakr9fcef032018-01-23 13:38:24 -08001097 skyframeExecutor.getConfiguredTargetMapForTesting(
janakrf3e6f252018-01-18 07:45:12 -08001098 eventHandler, target.getConfiguration(), ImmutableSet.copyOf(depNodeNames.values()));
Ulf Adams9c505cb2015-09-28 13:38:14 +00001099
janakr9c101402018-03-10 06:48:59 -08001100 OrderedSetMultimap<Attribute, ConfiguredTargetAndData> result = OrderedSetMultimap.create();
Ulf Adams9c505cb2015-09-28 13:38:14 +00001101 for (Map.Entry<Attribute, Dependency> entry : depNodeNames.entries()) {
Greg Estren0db9b112016-12-05 21:55:54 +00001102 result.putAll(entry.getKey(), cts.get(entry.getValue()));
Ulf Adams9c505cb2015-09-28 13:38:14 +00001103 }
Greg Estrend5353252016-08-11 22:13:31 +00001104 return result;
Ulf Adams9c505cb2015-09-28 13:38:14 +00001105 }
1106
gregcebe55e112018-01-30 11:04:53 -08001107 private ConfigurationTransition getTopLevelTransitionForTarget(Label label,
1108 ExtendedEventHandler handler) {
Cal Peyser8a638d52017-03-24 15:44:24 +00001109 Rule rule;
1110 try {
1111 rule = skyframeExecutor
1112 .getPackageManager()
1113 .getTarget(handler, label)
1114 .getAssociatedRule();
1115 } catch (NoSuchPackageException | NoSuchTargetException e) {
gregce7fa23ea2018-01-18 12:46:04 -08001116 return NoTransition.INSTANCE;
Cal Peyser8a638d52017-03-24 15:44:24 +00001117 } catch (InterruptedException e) {
1118 Thread.currentThread().interrupt();
1119 throw new AssertionError("Configuration of " + label + " interrupted");
1120 }
1121 if (rule == null) {
gregce7fa23ea2018-01-18 12:46:04 -08001122 return NoTransition.INSTANCE;
Cal Peyser8a638d52017-03-24 15:44:24 +00001123 }
1124 RuleTransitionFactory factory = rule
1125 .getRuleClassObject()
1126 .getTransitionFactory();
mstaib274cb262017-03-29 20:12:19 +00001127 if (factory == null) {
gregce7fa23ea2018-01-18 12:46:04 -08001128 return NoTransition.INSTANCE;
mstaib274cb262017-03-29 20:12:19 +00001129 }
gregcebe55e112018-01-30 11:04:53 -08001130 ConfigurationTransition transition = factory.buildTransitionFor(rule);
gregce7fa23ea2018-01-18 12:46:04 -08001131 return (transition == null) ? NoTransition.INSTANCE : transition;
Cal Peyser8a638d52017-03-24 15:44:24 +00001132 }
1133
Ulf Adams9c505cb2015-09-28 13:38:14 +00001134 /**
gregce408bfe472017-09-14 00:47:27 +02001135 * Returns a configured target for the specified target and configuration. If the target in
1136 * question has a top-level rule class transition, that transition is applied in the returned
1137 * ConfiguredTarget.
1138 *
1139 * <p>Returns {@code null} if something goes wrong.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001140 */
1141 @VisibleForTesting
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001142 public ConfiguredTarget getConfiguredTargetForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001143 ExtendedEventHandler eventHandler, Label label, BuildConfiguration config) {
Cal Peyser8a638d52017-03-24 15:44:24 +00001144 return skyframeExecutor.getConfiguredTargetForTesting(eventHandler, label, config,
1145 getTopLevelTransitionForTarget(label, eventHandler));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001146 }
1147
mjhalupka2fff9522018-02-07 12:22:17 -08001148 @VisibleForTesting
janakr9c101402018-03-10 06:48:59 -08001149 public ConfiguredTargetAndData getConfiguredTargetAndTargetForTesting(
mjhalupka2fff9522018-02-07 12:22:17 -08001150 ExtendedEventHandler eventHandler, Label label, BuildConfiguration config) {
1151 return skyframeExecutor.getConfiguredTargetAndTargetForTesting(eventHandler, label, config);
1152 }
1153
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001154 /**
1155 * Returns a RuleContext which is the same as the original RuleContext of the target parameter.
1156 */
1157 @VisibleForTesting
Florian Weikert4b67d4f2015-09-14 13:35:34 +00001158 public RuleContext getRuleContextForTesting(
cpeyser1099b542017-09-06 18:19:20 +02001159 ConfiguredTarget target,
1160 StoredEventHandler eventHandler,
Lukacs Berki76cb02e2017-02-17 14:06:11 +00001161 BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +00001162 throws EvalException, InvalidConfigurationException, InterruptedException,
cpeyser1099b542017-09-06 18:19:20 +02001163 InconsistentAspectOrderException, ToolchainContextException {
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001164 BuildConfiguration targetConfig = target.getConfiguration();
1165 CachingAnalysisEnvironment env =
tomlu3d1a1942017-11-29 14:01:21 -08001166 new CachingAnalysisEnvironment(
1167 getArtifactFactory(),
1168 skyframeExecutor.getActionKeyContext(),
janakr573807d2018-01-11 14:02:35 -08001169 ConfiguredTargetKey.of(target.getLabel(), targetConfig),
tomlu3d1a1942017-11-29 14:01:21 -08001170 /*isSystemEnv=*/ false,
1171 targetConfig.extendedSanityChecks(),
1172 eventHandler,
1173 /*env=*/ null,
1174 targetConfig.isActionsEnabled());
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001175 return getRuleContextForTesting(eventHandler, target, env, configurations);
Ulf Adams79f05212015-02-27 16:40:00 +00001176 }
1177
1178 /**
1179 * Creates and returns a rule context that is equivalent to the one that was used to create the
1180 * given configured target.
1181 */
1182 @VisibleForTesting
cpeyser1099b542017-09-06 18:19:20 +02001183 public RuleContext getRuleContextForTesting(
1184 ExtendedEventHandler eventHandler,
mjhalupka7675dbd2018-01-29 12:46:58 -08001185 ConfiguredTarget configuredTarget,
cpeyser1099b542017-09-06 18:19:20 +02001186 AnalysisEnvironment env,
1187 BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +00001188 throws EvalException, InvalidConfigurationException, InterruptedException,
cpeyser1099b542017-09-06 18:19:20 +02001189 InconsistentAspectOrderException, ToolchainContextException {
mjhalupka7675dbd2018-01-29 12:46:58 -08001190 BuildConfiguration targetConfig = configuredTarget.getConfiguration();
1191 Target target = null;
1192 try {
1193 target =
1194 skyframeExecutor.getPackageManager().getTarget(eventHandler, configuredTarget.getLabel());
1195 } catch (NoSuchPackageException | NoSuchTargetException e) {
1196 eventHandler.handle(
1197 Event.error("Failed to get target when trying to get rule context for testing"));
1198 throw new IllegalStateException(e);
1199 }
cpeyserfb829992017-09-07 17:17:03 +02001200 Set<Label> requiredToolchains =
mjhalupka7675dbd2018-01-29 12:46:58 -08001201 target.getAssociatedRule().getRuleClassObject().getRequiredToolchains();
cpeyser1099b542017-09-06 18:19:20 +02001202 ToolchainContext toolchainContext =
1203 skyframeExecutor.getToolchainContextForTesting(
1204 requiredToolchains, targetConfig, eventHandler);
janakr9c101402018-03-10 06:48:59 -08001205 OrderedSetMultimap<Attribute, ConfiguredTargetAndData> prerequisiteMap =
mjhalupka7675dbd2018-01-29 12:46:58 -08001206 getPrerequisiteMapForTesting(
1207 eventHandler, configuredTarget, configurations, toolchainContext);
cpeyserb38e3af2017-09-11 16:58:58 +02001208 toolchainContext.resolveToolchains(prerequisiteMap);
cpeyser1099b542017-09-06 18:19:20 +02001209
Ulf Adams79f05212015-02-27 16:40:00 +00001210 return new RuleContext.Builder(
Mark Schaller0312f912016-07-22 18:45:02 +00001211 env,
mjhalupka7675dbd2018-01-29 12:46:58 -08001212 (Rule) target,
dslomov44d15712017-12-20 05:42:28 -08001213 ImmutableList.of(),
Mark Schaller0312f912016-07-22 18:45:02 +00001214 targetConfig,
1215 configurations.getHostConfiguration(),
gregcee046d3a2018-01-29 13:52:40 -08001216 ruleClassProvider.getLipoDataTransition(),
Mark Schaller0312f912016-07-22 18:45:02 +00001217 ruleClassProvider.getPrerequisiteValidator(),
mjhalupka7675dbd2018-01-29 12:46:58 -08001218 ((Rule) target).getRuleClassObject().getConfigurationFragmentPolicy())
Mark Schaller0312f912016-07-22 18:45:02 +00001219 .setVisibility(
cushon34ff85e2017-11-15 08:59:27 -08001220 NestedSetBuilder.create(
1221 Order.STABLE_ORDER,
1222 PackageGroupContents.create(ImmutableList.of(PackageSpecification.everything()))))
cpeyserb38e3af2017-09-11 16:58:58 +02001223 .setPrerequisites(
mjhalupka7675dbd2018-01-29 12:46:58 -08001224 getPrerequisiteMapForTesting(
1225 eventHandler, configuredTarget, configurations, toolchainContext))
Mark Schaller0312f912016-07-22 18:45:02 +00001226 .setConfigConditions(ImmutableMap.<Label, ConfigMatchingProvider>of())
1227 .setUniversalFragment(ruleClassProvider.getUniversalFragment())
cpeyser1099b542017-09-06 18:19:20 +02001228 .setToolchainContext(toolchainContext)
Mark Schaller0312f912016-07-22 18:45:02 +00001229 .build();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001230 }
1231
1232 /**
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001233 * For a configured target dependentTarget, returns the desired configured target that is depended
1234 * upon. Useful for obtaining the a target with aspects required by the dependent.
Googler9263b462015-05-13 19:22:24 +00001235 */
1236 @VisibleForTesting
1237 public ConfiguredTarget getPrerequisiteConfiguredTargetForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001238 ExtendedEventHandler eventHandler,
1239 ConfiguredTarget dependentTarget,
1240 Label desiredTarget,
Ulf Adamse7704672015-09-21 14:37:41 +00001241 BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +00001242 throws EvalException, InvalidConfigurationException, InterruptedException,
1243 InconsistentAspectOrderException {
janakr9c101402018-03-10 06:48:59 -08001244 Collection<ConfiguredTargetAndData> configuredTargets =
cpeyserb38e3af2017-09-11 16:58:58 +02001245 getPrerequisiteMapForTesting(
1246 eventHandler, dependentTarget, configurations, /*toolchainContext=*/ null)
1247 .values();
janakr9c101402018-03-10 06:48:59 -08001248 for (ConfiguredTargetAndData ct : configuredTargets) {
janakrf3e6f252018-01-18 07:45:12 -08001249 if (ct.getTarget().getLabel().equals(desiredTarget)) {
1250 return ct.getConfiguredTarget();
Googler9263b462015-05-13 19:22:24 +00001251 }
1252 }
1253 return null;
1254 }
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +00001255
1256 /**
1257 * A converter for loading phase thread count. Since the default is not a true constant, we create
1258 * a converter here to implement the default logic.
1259 */
1260 public static final class LoadingPhaseThreadCountConverter implements Converter<Integer> {
1261 @Override
1262 public Integer convert(String input) throws OptionsParsingException {
1263 if ("-1".equals(input)) {
1264 // Reduce thread count while running tests. Test cases are typically small, and large thread
1265 // pools vying for a relatively small number of CPU cores may induce non-optimal
1266 // performance.
1267 return System.getenv("TEST_TMPDIR") == null ? 200 : 5;
1268 }
1269
1270 try {
1271 int result = Integer.decode(input);
1272 if (result < 0) {
1273 throw new OptionsParsingException("'" + input + "' must be at least -1");
1274 }
1275 return result;
1276 } catch (NumberFormatException e) {
1277 throw new OptionsParsingException("'" + input + "' is not an int");
1278 }
1279 }
1280
1281 @Override
1282 public String getTypeDescription() {
1283 return "an integer";
1284 }
1285 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001286}