blob: 02a6dfd684305060abad20b2813184790bdbc2b2 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package com.google.devtools.build.lib.analysis;
16
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000017import static com.google.common.collect.Iterables.concat;
18
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010019import com.google.common.annotations.VisibleForTesting;
20import com.google.common.base.Function;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010021import com.google.common.base.Predicate;
Greg Estren7883bf12016-11-18 20:03:43 +000022import com.google.common.collect.ArrayListMultimap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010023import com.google.common.collect.ImmutableList;
24import com.google.common.collect.ImmutableMap;
Greg Estren0db9b112016-12-05 21:55:54 +000025import com.google.common.collect.ImmutableMultimap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010026import com.google.common.collect.ImmutableSet;
27import com.google.common.collect.Iterables;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010028import com.google.common.collect.Lists;
Greg Estren7883bf12016-11-18 20:03:43 +000029import com.google.common.collect.Multimap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010030import com.google.common.collect.Sets;
31import com.google.common.eventbus.EventBus;
Rumou Duan33bab462016-04-25 17:55:12 +000032import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010033import com.google.devtools.build.lib.actions.ActionGraph;
janakr93e3eea2017-03-30 22:09:37 +000034import com.google.devtools.build.lib.actions.ActionLookupValue;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010035import com.google.devtools.build.lib.actions.Artifact;
36import com.google.devtools.build.lib.actions.ArtifactFactory;
Eric Fellheimer9c1e12f2015-08-06 20:23:55 +000037import com.google.devtools.build.lib.actions.ArtifactOwner;
janakrae323982017-09-29 21:11:53 +020038import com.google.devtools.build.lib.actions.PackageRoots;
Dmitry Lomovd83af9e2017-02-23 15:44:23 +000039import com.google.devtools.build.lib.analysis.DependencyResolver.InconsistentAspectOrderException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010040import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
41import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection;
Greg Estren373e3e22016-08-09 22:36:51 +000042import com.google.devtools.build.lib.analysis.config.BuildOptions;
gregce3b8ffd12017-05-05 20:53:32 +020043import com.google.devtools.build.lib.analysis.config.ComposingSplitTransition;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010044import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
gregce692f763f2017-07-06 22:51:30 -040045import com.google.devtools.build.lib.analysis.config.DynamicTransitionMapper;
Greg Estren373e3e22016-08-09 22:36:51 +000046import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
gregce692f763f2017-07-06 22:51:30 -040047import com.google.devtools.build.lib.analysis.config.PatchTransition;
gregce45ae0962017-07-22 00:11:13 +020048import com.google.devtools.build.lib.analysis.constraints.TopLevelConstraintSemantics;
ulfjackab21d182017-08-10 15:36:14 +020049import com.google.devtools.build.lib.analysis.test.CoverageReportActionFactory;
50import com.google.devtools.build.lib.analysis.test.CoverageReportActionFactory.CoverageReportActionsWrapper;
51import com.google.devtools.build.lib.analysis.test.InstrumentedFilesProvider;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000052import com.google.devtools.build.lib.cmdline.Label;
Lukacs Berki6916be22015-02-19 13:36:06 +000053import com.google.devtools.build.lib.collect.nestedset.NestedSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010054import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
55import com.google.devtools.build.lib.collect.nestedset.Order;
56import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010057import com.google.devtools.build.lib.events.Event;
Klaus Aehlig777b30d2017-02-24 16:30:15 +000058import com.google.devtools.build.lib.events.ExtendedEventHandler;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010059import com.google.devtools.build.lib.events.StoredEventHandler;
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000060import com.google.devtools.build.lib.packages.AspectClass;
Dmitry Lomov15756522016-12-16 16:52:37 +000061import com.google.devtools.build.lib.packages.AspectDescriptor;
Dmitry Lomovca9bfa42016-11-15 13:22:36 +000062import com.google.devtools.build.lib.packages.AspectParameters;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010063import com.google.devtools.build.lib.packages.Attribute;
Cal Peyser8a638d52017-03-24 15:44:24 +000064import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition;
65import com.google.devtools.build.lib.packages.Attribute.Transition;
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;
72import com.google.devtools.build.lib.packages.RawAttributeMapper;
73import com.google.devtools.build.lib.packages.Rule;
Michael Staib2a675202017-03-20 18:06:48 +000074import com.google.devtools.build.lib.packages.RuleTransitionFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010075import com.google.devtools.build.lib.packages.Target;
76import com.google.devtools.build.lib.packages.TargetUtils;
Ulf Adamsd8099362015-11-02 14:56:46 +000077import com.google.devtools.build.lib.pkgcache.LoadingResult;
nharmatac4335cf2017-07-18 21:39:13 +020078import com.google.devtools.build.lib.pkgcache.PackageManager.PackageManagerStatistics;
Dmitry Lomove2033b12015-08-19 16:57:49 +000079import com.google.devtools.build.lib.skyframe.AspectValue;
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000080import com.google.devtools.build.lib.skyframe.AspectValue.AspectKey;
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +000081import com.google.devtools.build.lib.skyframe.AspectValue.AspectValueKey;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010082import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
Greg Estren7971e672016-06-01 23:22:48 +000083import com.google.devtools.build.lib.skyframe.ConfiguredTargetValue;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010084import com.google.devtools.build.lib.skyframe.CoverageReportValue;
Dmitry Lomove2033b12015-08-19 16:57:49 +000085import com.google.devtools.build.lib.skyframe.SkyframeAnalysisResult;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010086import com.google.devtools.build.lib.skyframe.SkyframeBuildView;
87import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
cpeyser1099b542017-09-06 18:19:20 +020088import com.google.devtools.build.lib.skyframe.ToolchainUtil.ToolchainContextException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010089import com.google.devtools.build.lib.syntax.EvalException;
Dmitry Lomov51aafc12016-11-18 14:02:54 +000090import com.google.devtools.build.lib.syntax.SkylarkImport;
91import com.google.devtools.build.lib.syntax.SkylarkImports;
92import com.google.devtools.build.lib.syntax.SkylarkImports.SkylarkImportSyntaxException;
Greg Estrend5353252016-08-11 22:13:31 +000093import com.google.devtools.build.lib.util.OrderedSetMultimap;
Klaus Aehligc27b4da2017-09-01 10:33:22 +020094import com.google.devtools.build.lib.util.Pair;
Mark Schaller6df81792015-12-10 18:47:47 +000095import com.google.devtools.build.lib.util.Preconditions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010096import com.google.devtools.build.lib.util.RegexFilter;
Dmitry Lomov0b832ce2015-10-20 10:03:14 +000097import com.google.devtools.build.lib.vfs.PathFragment;
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;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100115import javax.annotation.Nullable;
116
117/**
118 * <p>The BuildView presents a semantically-consistent and transitively-closed
119 * dependency graph for some set of packages.
120 *
121 * <h2>Package design</h2>
122 *
123 * <p>This package contains the Blaze dependency analysis framework (aka
124 * "analysis phase"). The goal of this code is to perform semantic analysis of
125 * all of the build targets required for a given build, to report
126 * errors/warnings for any problems in the input, and to construct an "action
127 * graph" (see {@code lib.actions} package) correctly representing the work to
128 * be done during the execution phase of the build.
129 *
130 * <p><b>Configurations</b> the inputs to a build come from two sources: the
131 * intrinsic inputs, specified in the BUILD file, are called <em>targets</em>.
132 * The environmental inputs, coming from the build tool, the command-line, or
133 * configuration files, are called the <em>configuration</em>. Only when a
134 * target and a configuration are combined is there sufficient information to
135 * perform a build. </p>
136 *
137 * <p>Targets are implemented by the {@link Target} hierarchy in the {@code
138 * lib.packages} code. Configurations are implemented by {@link
139 * BuildConfiguration}. The pair of these together is represented by an
140 * instance of class {@link ConfiguredTarget}; this is the root of a hierarchy
141 * with different implementations for each kind of target: source file, derived
142 * file, rules, etc.
143 *
144 * <p>The framework code in this package (as opposed to its subpackages) is
145 * responsible for constructing the {@code ConfiguredTarget} graph for a given
146 * target and configuration, taking care of such issues as:
147 * <ul>
148 * <li>caching common subgraphs.
149 * <li>detecting and reporting cycles.
150 * <li>correct propagation of errors through the graph.
151 * <li>reporting universal errors, such as dependencies from production code
152 * to tests, or to experimental branches.
153 * <li>capturing and replaying errors.
154 * <li>maintaining the graph from one build to the next to
155 * avoid unnecessary recomputation.
156 * <li>checking software licenses.
157 * </ul>
158 *
159 * <p>See also {@link ConfiguredTarget} which documents some important
160 * invariants.
161 */
162public class BuildView {
163
164 /**
ccalvarin2eaa02e2017-04-17 23:37:46 +0200165 * Options that affect the <i>mechanism</i> of analysis. These are distinct from {@link
166 * com.google.devtools.build.lib.analysis.config.BuildOptions}, which affect the <i>value</i> of a
167 * BuildConfiguration.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100168 */
169 public static class Options extends OptionsBase {
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000170 @Option(
171 name = "loading_phase_threads",
172 defaultValue = "-1",
173 category = "what",
174 converter = LoadingPhaseThreadCountConverter.class,
ccalvarin3bc15472017-06-27 17:58:35 +0200175 documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
176 effectTags = {OptionEffectTag.UNKNOWN},
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000177 help = "Number of parallel threads to use for the loading/analysis phase."
178 )
179 public int loadingPhaseThreads;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100180
ccalvarin2eaa02e2017-04-17 23:37:46 +0200181 @Option(
182 name = "keep_going",
183 abbrev = 'k',
184 defaultValue = "false",
185 category = "strategy",
ccalvarin25735402017-09-19 19:09:26 +0200186 documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
187 effectTags = {OptionEffectTag.EAGERNESS_TO_EXIT},
ccalvarin2eaa02e2017-04-17 23:37:46 +0200188 help =
189 "Continue as much as possible after an error. While the target that failed, and those "
190 + "that depend on it, cannot be analyzed (or built), the other prerequisites of "
191 + "these targets can be analyzed (or built) all the same."
192 )
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100193 public boolean keepGoing;
194
ccalvarin2eaa02e2017-04-17 23:37:46 +0200195 @Option(
196 name = "analysis_warnings_as_errors",
197 deprecationWarning =
198 "analysis_warnings_as_errors is now a no-op and will be removed in"
199 + " an upcoming Blaze release",
200 defaultValue = "false",
201 category = "strategy",
ccalvarin3bc15472017-06-27 17:58:35 +0200202 documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
203 effectTags = {OptionEffectTag.UNKNOWN},
ccalvarin2eaa02e2017-04-17 23:37:46 +0200204 help = "Treat visible analysis warnings as errors."
205 )
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100206 public boolean analysisWarningsAsErrors;
207
ccalvarin2eaa02e2017-04-17 23:37:46 +0200208 @Option(
209 name = "discard_analysis_cache",
210 defaultValue = "false",
211 category = "strategy",
ccalvarin3bc15472017-06-27 17:58:35 +0200212 documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
213 effectTags = {OptionEffectTag.UNKNOWN},
ccalvarin2eaa02e2017-04-17 23:37:46 +0200214 help =
215 "Discard the analysis cache immediately after the analysis phase completes."
216 + " Reduces memory usage by ~10%, but makes further incremental builds slower."
217 )
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100218 public boolean discardAnalysisCache;
219
ccalvarin2eaa02e2017-04-17 23:37:46 +0200220 @Option(
221 name = "experimental_extra_action_filter",
222 defaultValue = "",
223 category = "experimental",
224 converter = RegexFilter.RegexFilterConverter.class,
ccalvarin3bc15472017-06-27 17:58:35 +0200225 documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
226 effectTags = {OptionEffectTag.UNKNOWN},
ccalvarin2eaa02e2017-04-17 23:37:46 +0200227 help = "Filters set of targets to schedule extra_actions for."
228 )
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100229 public RegexFilter extraActionFilter;
230
ccalvarin2eaa02e2017-04-17 23:37:46 +0200231 @Option(
232 name = "experimental_extra_action_top_level_only",
233 defaultValue = "false",
234 category = "experimental",
ccalvarin3bc15472017-06-27 17:58:35 +0200235 documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
236 effectTags = {OptionEffectTag.UNKNOWN},
ccalvarin2eaa02e2017-04-17 23:37:46 +0200237 help = "Only schedules extra_actions for top level targets."
238 )
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100239 public boolean extraActionTopLevelOnly;
240
Carmi Grushko9a796de2016-11-13 12:22:30 +0000241 @Option(
ccalvarin2eaa02e2017-04-17 23:37:46 +0200242 name = "version_window_for_dirty_node_gc",
243 defaultValue = "0",
ccalvarin456adb22017-07-11 14:23:46 +0200244 documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
ccalvarin3bc15472017-06-27 17:58:35 +0200245 effectTags = {OptionEffectTag.UNKNOWN},
ccalvarin2eaa02e2017-04-17 23:37:46 +0200246 help =
247 "Nodes that have been dirty for more than this many versions will be deleted"
248 + " from the graph upon the next update. Values must be non-negative long integers,"
249 + " or -1 indicating the maximum possible window."
250 )
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100251 public long versionWindowForDirtyNodeGc;
Ulf Adamsab64e592016-09-05 09:40:13 +0000252
253 @Deprecated
254 @Option(
255 name = "experimental_interleave_loading_and_analysis",
256 defaultValue = "true",
257 category = "experimental",
ccalvarin3bc15472017-06-27 17:58:35 +0200258 documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
259 effectTags = {OptionEffectTag.UNKNOWN},
Ulf Adamsab64e592016-09-05 09:40:13 +0000260 help = "No-op."
261 )
262 public boolean interleaveLoadingAndAnalysis;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100263 }
264
lberki998ec922017-09-05 10:08:25 +0200265 private static final Logger logger = Logger.getLogger(BuildView.class.getName());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100266
267 private final BlazeDirectories directories;
268
269 private final SkyframeExecutor skyframeExecutor;
270 private final SkyframeBuildView skyframeBuildView;
271
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100272 private final ConfiguredRuleClassProvider ruleClassProvider;
273
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100274 /**
275 * A factory class to create the coverage report action. May be null.
276 */
277 @Nullable private final CoverageReportActionFactory coverageReportActionFactory;
278
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100279 @VisibleForTesting
280 public Set<SkyKey> getSkyframeEvaluatedTargetKeysForTesting() {
281 return skyframeBuildView.getEvaluatedTargetKeys();
282 }
283
284 /** The number of targets freshly evaluated in the last analysis run. */
285 public int getTargetsVisited() {
286 return skyframeBuildView.getEvaluatedTargetKeys().size();
287 }
288
nharmatac4335cf2017-07-18 21:39:13 +0200289 public PackageManagerStatistics getAndClearPkgManagerStatistics() {
290 return skyframeExecutor.getPackageManager().getAndClearStatistics();
291 }
292
Ulf Adams59dbf682015-09-17 11:36:43 +0000293 public BuildView(BlazeDirectories directories,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100294 ConfiguredRuleClassProvider ruleClassProvider,
295 SkyframeExecutor skyframeExecutor,
Ulf Adams5a96d532015-09-26 09:00:57 +0000296 CoverageReportActionFactory coverageReportActionFactory) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100297 this.directories = directories;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100298 this.coverageReportActionFactory = coverageReportActionFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100299 this.ruleClassProvider = ruleClassProvider;
300 this.skyframeExecutor = Preconditions.checkNotNull(skyframeExecutor);
Ulf Adams89eefd72015-09-23 08:00:43 +0000301 this.skyframeBuildView = skyframeExecutor.getSkyframeBuildView();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100302 }
303
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100304 /**
305 * Returns whether the given configured target has errors.
306 */
307 @VisibleForTesting
308 public boolean hasErrors(ConfiguredTarget configuredTarget) {
309 return configuredTarget == null;
310 }
311
312 /**
313 * Sets the configurations. Not thread-safe. DO NOT CALL except from tests!
314 */
315 @VisibleForTesting
Ulf Adams79f05212015-02-27 16:40:00 +0000316 public void setConfigurationsForTesting(BuildConfigurationCollection configurations) {
Ulf Adams003fe962015-09-26 09:51:39 +0000317 skyframeBuildView.setConfigurations(configurations);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100318 }
319
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100320 public ArtifactFactory getArtifactFactory() {
Ulf Adams89eefd72015-09-23 08:00:43 +0000321 return skyframeBuildView.getArtifactFactory();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100322 }
323
324 @VisibleForTesting
janakr1cde8722017-10-10 03:22:21 +0200325 WorkspaceStatusAction getLastWorkspaceBuildInfoActionForTesting() throws InterruptedException {
janakrc8dce992017-09-25 21:48:27 +0200326 return skyframeExecutor.getLastWorkspaceStatusAction();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100327 }
328
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100329 @Override
330 public int hashCode() {
331 throw new UnsupportedOperationException(); // avoid nondeterminism
332 }
333
334 /**
335 * Return value for {@link BuildView#update} and {@code BuildTool.prepareToBuild}.
336 */
337 public static final class AnalysisResult {
gregce45ae0962017-07-22 00:11:13 +0200338 private final ImmutableSet<ConfiguredTarget> targetsToBuild;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100339 @Nullable private final ImmutableList<ConfiguredTarget> targetsToTest;
gregce45ae0962017-07-22 00:11:13 +0200340 private final ImmutableSet<ConfiguredTarget> targetsToSkip;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100341 @Nullable private final String error;
342 private final ActionGraph actionGraph;
343 private final ImmutableSet<Artifact> artifactsToBuild;
344 private final ImmutableSet<ConfiguredTarget> parallelTests;
345 private final ImmutableSet<ConfiguredTarget> exclusiveTests;
346 @Nullable private final TopLevelArtifactContext topLevelContext;
Dmitry Lomove2033b12015-08-19 16:57:49 +0000347 private final ImmutableList<AspectValue> aspects;
janakrae323982017-09-29 21:11:53 +0200348 private final PackageRoots packageRoots;
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000349 private final String workspaceName;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100350
351 private AnalysisResult(
Dmitry Lomove2033b12015-08-19 16:57:49 +0000352 Collection<ConfiguredTarget> targetsToBuild,
353 Collection<AspectValue> aspects,
354 Collection<ConfiguredTarget> targetsToTest,
gregce45ae0962017-07-22 00:11:13 +0200355 Collection<ConfiguredTarget> targetsToSkip,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000356 @Nullable String error,
357 ActionGraph actionGraph,
358 Collection<Artifact> artifactsToBuild,
359 Collection<ConfiguredTarget> parallelTests,
360 Collection<ConfiguredTarget> exclusiveTests,
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000361 TopLevelArtifactContext topLevelContext,
janakrae323982017-09-29 21:11:53 +0200362 PackageRoots packageRoots,
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000363 String workspaceName) {
gregce45ae0962017-07-22 00:11:13 +0200364 this.targetsToBuild = ImmutableSet.copyOf(targetsToBuild);
Dmitry Lomove2033b12015-08-19 16:57:49 +0000365 this.aspects = ImmutableList.copyOf(aspects);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100366 this.targetsToTest = targetsToTest == null ? null : ImmutableList.copyOf(targetsToTest);
gregce45ae0962017-07-22 00:11:13 +0200367 this.targetsToSkip = ImmutableSet.copyOf(targetsToSkip);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100368 this.error = error;
369 this.actionGraph = actionGraph;
370 this.artifactsToBuild = ImmutableSet.copyOf(artifactsToBuild);
371 this.parallelTests = ImmutableSet.copyOf(parallelTests);
372 this.exclusiveTests = ImmutableSet.copyOf(exclusiveTests);
373 this.topLevelContext = topLevelContext;
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000374 this.packageRoots = packageRoots;
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000375 this.workspaceName = workspaceName;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100376 }
377
378 /**
379 * Returns configured targets to build.
380 */
gregce45ae0962017-07-22 00:11:13 +0200381 public ImmutableSet<ConfiguredTarget> getTargetsToBuild() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100382 return targetsToBuild;
383 }
384
janakrae323982017-09-29 21:11:53 +0200385 /** @see PackageRoots */
386 public PackageRoots getPackageRoots() {
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000387 return packageRoots;
388 }
389
390 /**
Dmitry Lomove2033b12015-08-19 16:57:49 +0000391 * Returns aspects of configured targets to build.
392 *
393 * <p>If this list is empty, build the targets returned by {@code getTargetsToBuild()}.
394 * Otherwise, only build these aspects of the targets returned by {@code getTargetsToBuild()}.
395 */
396 public Collection<AspectValue> getAspects() {
397 return aspects;
398 }
399
400 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100401 * Returns the configured targets to run as tests, or {@code null} if testing was not
402 * requested (e.g. "build" command rather than "test" command).
403 */
404 @Nullable
405 public Collection<ConfiguredTarget> getTargetsToTest() {
406 return targetsToTest;
407 }
408
gregce45ae0962017-07-22 00:11:13 +0200409 /**
410 * Returns the configured targets that should not be executed because they're not
411 * platform-compatible with the current build.
412 *
413 * <p>For example: tests that aren't intended for the designated CPU.
414 */
415 public ImmutableSet<ConfiguredTarget> getTargetsToSkip() {
416 return targetsToSkip;
417 }
418
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100419 public ImmutableSet<Artifact> getAdditionalArtifactsToBuild() {
420 return artifactsToBuild;
421 }
422
423 public ImmutableSet<ConfiguredTarget> getExclusiveTests() {
424 return exclusiveTests;
425 }
426
427 public ImmutableSet<ConfiguredTarget> getParallelTests() {
428 return parallelTests;
429 }
430
431 /**
432 * Returns an error description (if any).
433 */
434 @Nullable public String getError() {
435 return error;
436 }
437
Ulf Adams988bb212015-08-25 12:51:48 +0000438 public boolean hasError() {
439 return error != null;
440 }
441
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100442 /**
443 * Returns the action graph.
444 */
445 public ActionGraph getActionGraph() {
446 return actionGraph;
447 }
448
449 public TopLevelArtifactContext getTopLevelContext() {
450 return topLevelContext;
451 }
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000452
453 public String getWorkspaceName() {
454 return workspaceName;
455 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100456 }
457
458
459 /**
460 * Returns the collection of configured targets corresponding to any of the provided targets.
461 */
462 @VisibleForTesting
463 static Iterable<? extends ConfiguredTarget> filterTestsByTargets(
464 Collection<? extends ConfiguredTarget> targets,
465 final Set<? extends Target> allowedTargets) {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000466 return Iterables.filter(
467 targets,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100468 new Predicate<ConfiguredTarget>() {
469 @Override
Dmitry Lomove2033b12015-08-19 16:57:49 +0000470 public boolean apply(ConfiguredTarget rule) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100471 return allowedTargets.contains(rule.getTarget());
472 }
473 });
474 }
475
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100476 @ThreadCompatible
Dmitry Lomove2033b12015-08-19 16:57:49 +0000477 public AnalysisResult update(
478 LoadingResult loadingResult,
479 BuildConfigurationCollection configurations,
480 List<String> aspects,
481 Options viewOptions,
482 TopLevelArtifactContext topLevelOptions,
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000483 ExtendedEventHandler eventHandler,
Ulf Adams8c4ae672016-03-30 11:20:41 +0000484 EventBus eventBus)
Dmitry Lomove2033b12015-08-19 16:57:49 +0000485 throws ViewCreationFailedException, InterruptedException {
lberki998ec922017-09-05 10:08:25 +0200486 logger.info("Starting analysis");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100487 pollInterruptedStatus();
488
489 skyframeBuildView.resetEvaluatedConfiguredTargetKeysSet();
490
491 Collection<Target> targets = loadingResult.getTargets();
492 eventBus.post(new AnalysisPhaseStartedEvent(targets));
493
Ulf Adams003fe962015-09-26 09:51:39 +0000494 skyframeBuildView.setConfigurations(configurations);
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000495
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100496 // Determine the configurations.
Greg Estren7971e672016-06-01 23:22:48 +0000497 List<TargetAndConfiguration> topLevelTargetsWithConfigs =
498 nodesForTopLevelTargets(configurations, targets, eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100499
Klaus Aehlig71c993b2017-05-09 07:49:46 -0400500 // Report the generated association of targets to configurations
501 Multimap<Label, BuildConfiguration> byLabel =
502 ArrayListMultimap.<Label, BuildConfiguration>create();
503 for (TargetAndConfiguration pair : topLevelTargetsWithConfigs) {
504 byLabel.put(pair.getLabel(), pair.getConfiguration());
505 }
Klaus Aehlig2a92c902017-08-11 14:03:31 +0200506 for (Target target : targets) {
507 eventBus.post(new TargetConfiguredEvent(target, byLabel.get(target.getLabel())));
Klaus Aehlig71c993b2017-05-09 07:49:46 -0400508 }
509
Greg Estren7971e672016-06-01 23:22:48 +0000510 List<ConfiguredTargetKey> topLevelCtKeys = Lists.transform(topLevelTargetsWithConfigs,
511 new Function<TargetAndConfiguration, ConfiguredTargetKey>() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100512 @Override
513 public ConfiguredTargetKey apply(TargetAndConfiguration node) {
514 return new ConfiguredTargetKey(node.getLabel(), node.getConfiguration());
515 }
516 });
517
Klaus Aehligc27b4da2017-09-01 10:33:22 +0200518 Multimap<Pair<Label, String>, BuildConfiguration> aspectConfigurations =
519 ArrayListMultimap.create();
Klaus Aehlig71c993b2017-05-09 07:49:46 -0400520
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000521 List<AspectValueKey> aspectKeys = new ArrayList<>();
Dmitry Lomove2033b12015-08-19 16:57:49 +0000522 for (String aspect : aspects) {
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000523 // Syntax: label%aspect
524 int delimiterPosition = aspect.indexOf('%');
525 if (delimiterPosition >= 0) {
John Fielda97e17f2015-11-13 02:19:52 +0000526 // TODO(jfield): For consistency with Skylark loads, the aspect should be specified
527 // as an absolute path. Also, we probably need to do at least basic validation of
528 // path well-formedness here.
Dmitry Lomov51aafc12016-11-18 14:02:54 +0000529 String bzlFileLoadLikeString = aspect.substring(0, delimiterPosition);
530 if (!bzlFileLoadLikeString.startsWith("//") && !bzlFileLoadLikeString.startsWith("@")) {
531 // "Legacy" behavior of '--aspects' parameter.
nharmatab4060b62017-04-04 17:11:39 +0000532 bzlFileLoadLikeString = PathFragment.create("/" + bzlFileLoadLikeString).toString();
Dmitry Lomov51aafc12016-11-18 14:02:54 +0000533 if (bzlFileLoadLikeString.endsWith(".bzl")) {
534 bzlFileLoadLikeString = bzlFileLoadLikeString.substring(0,
535 bzlFileLoadLikeString.length() - ".bzl".length());
536 }
537 }
538 SkylarkImport skylarkImport;
539 try {
540 skylarkImport = SkylarkImports.create(bzlFileLoadLikeString);
541 } catch (SkylarkImportSyntaxException e) {
542 throw new ViewCreationFailedException(
543 String.format("Invalid aspect '%s': %s", aspect, e.getMessage()), e);
544 }
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000545
546 String skylarkFunctionName = aspect.substring(delimiterPosition + 1);
Dmitry Lomov01f85c02016-06-29 06:37:50 +0000547 for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) {
Klaus Aehligc27b4da2017-09-01 10:33:22 +0200548 aspectConfigurations.put(
549 Pair.of(targetSpec.getLabel(), aspect), targetSpec.getConfiguration());
Dmitry Lomove2033b12015-08-19 16:57:49 +0000550 aspectKeys.add(
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000551 AspectValue.createSkylarkAspectKey(
552 targetSpec.getLabel(),
Michael Staib04f6f242016-03-01 15:40:29 +0000553 // For invoking top-level aspects, use the top-level configuration for both the
554 // aspect and the base target while the top-level configuration is untrimmed.
555 targetSpec.getConfiguration(),
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000556 targetSpec.getConfiguration(),
Dmitry Lomov51aafc12016-11-18 14:02:54 +0000557 skylarkImport,
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000558 skylarkFunctionName));
Dmitry Lomove2033b12015-08-19 16:57:49 +0000559 }
560 } else {
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000561 final NativeAspectClass aspectFactoryClass =
562 ruleClassProvider.getNativeAspectClassMap().get(aspect);
dslomov99ea6b42017-04-25 17:46:17 +0200563
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000564 if (aspectFactoryClass != null) {
Dmitry Lomov01f85c02016-06-29 06:37:50 +0000565 for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) {
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000566 // For invoking top-level aspects, use the top-level configuration for both the
567 // aspect and the base target while the top-level configuration is untrimmed.
568 BuildConfiguration configuration = targetSpec.getConfiguration();
Klaus Aehligc27b4da2017-09-01 10:33:22 +0200569 aspectConfigurations.put(Pair.of(targetSpec.getLabel(), aspect), configuration);
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000570 aspectKeys.add(
571 AspectValue.createAspectKey(
Dmitry Lomov8ff06452015-10-21 19:16:30 +0000572 targetSpec.getLabel(),
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000573 configuration,
dslomovfa50c3d2017-05-08 08:47:44 -0400574 new AspectDescriptor(aspectFactoryClass, AspectParameters.EMPTY),
Dmitry Lomovca9bfa42016-11-15 13:22:36 +0000575 configuration
576 ));
Dmitry Lomov0b832ce2015-10-20 10:03:14 +0000577 }
578 } else {
579 throw new ViewCreationFailedException("Aspect '" + aspect + "' is unknown");
580 }
Dmitry Lomove2033b12015-08-19 16:57:49 +0000581 }
582 }
583
Klaus Aehligc27b4da2017-09-01 10:33:22 +0200584 for (Pair<Label, String> target : aspectConfigurations.keys()) {
585 eventBus.post(
586 new AspectConfiguredEvent(
587 target.getFirst(), target.getSecond(), aspectConfigurations.get(target)));
588 }
589
janakrc8dce992017-09-25 21:48:27 +0200590 skyframeExecutor.maybeInvalidateWorkspaceStatusValue(loadingResult.getWorkspaceName());
Dmitry Lomove2033b12015-08-19 16:57:49 +0000591 SkyframeAnalysisResult skyframeAnalysisResult;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100592 try {
Dmitry Lomove2033b12015-08-19 16:57:49 +0000593 skyframeAnalysisResult =
594 skyframeBuildView.configureTargets(
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +0000595 eventHandler,
596 topLevelCtKeys,
597 aspectKeys,
598 eventBus,
599 viewOptions.keepGoing,
600 viewOptions.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 =
616 TopLevelConstraintSemantics.checkTargetEnvironmentRestrictions(
617 skyframeAnalysisResult.getConfiguredTargets(),
618 skyframeExecutor.getPackageManager(),
619 eventHandler);
620
Dmitry Lomove2033b12015-08-19 16:57:49 +0000621 AnalysisResult result =
622 createResult(
Ulf Adams5b9009b2015-09-24 09:52:53 +0000623 eventHandler,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000624 loadingResult,
625 topLevelOptions,
626 viewOptions,
gregce45ae0962017-07-22 00:11:13 +0200627 skyframeAnalysisResult,
628 targetsToSkip);
lberki998ec922017-09-05 10:08:25 +0200629 logger.info("Finished analysis");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100630 return result;
631 }
632
Dmitry Lomove2033b12015-08-19 16:57:49 +0000633 private AnalysisResult createResult(
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000634 ExtendedEventHandler eventHandler,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000635 LoadingResult loadingResult,
636 TopLevelArtifactContext topLevelOptions,
637 BuildView.Options viewOptions,
gregce45ae0962017-07-22 00:11:13 +0200638 SkyframeAnalysisResult skyframeAnalysisResult,
639 Set<ConfiguredTarget> targetsToSkip)
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());
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000644 Collection<AspectValue> aspects = skyframeAnalysisResult.getAspects();
645
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.
gregce45ae0962017-07-22 00:11:13 +0200649 allTargetsToTest = Sets.newLinkedHashSet(
650 filterTestsByTargets(configuredTargets, Sets.newHashSet(testsToRun)));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100651 }
652
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100653 Set<Artifact> artifactsToBuild = new HashSet<>();
654 Set<ConfiguredTarget> parallelTests = new HashSet<>();
655 Set<ConfiguredTarget> exclusiveTests = new HashSet<>();
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000656
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100657 // build-info and build-changelist.
Ulf Adams5b9009b2015-09-24 09:52:53 +0000658 Collection<Artifact> buildInfoArtifacts =
659 skyframeExecutor.getWorkspaceStatusArtifacts(eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100660 Preconditions.checkState(buildInfoArtifacts.size() == 2, buildInfoArtifacts);
661 artifactsToBuild.addAll(buildInfoArtifacts);
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000662
663 // Extra actions
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000664 addExtraActionsIfRequested(viewOptions, configuredTargets, aspects, artifactsToBuild);
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000665
666 // Coverage
667 NestedSet<Artifact> baselineCoverageArtifacts = getBaselineCoverageArtifacts(configuredTargets);
668 Iterables.addAll(artifactsToBuild, baselineCoverageArtifacts);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100669 if (coverageReportActionFactory != null) {
Googlercdc90e92015-02-11 00:18:07 +0000670 CoverageReportActionsWrapper actionsWrapper;
671 actionsWrapper = coverageReportActionFactory.createCoverageReportActionsWrapper(
Ulf Adams5834e2b2016-04-18 12:03:51 +0000672 eventHandler,
673 directories,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100674 allTargetsToTest,
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000675 baselineCoverageArtifacts,
Ulf Adams89eefd72015-09-23 08:00:43 +0000676 getArtifactFactory(),
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100677 CoverageReportValue.ARTIFACT_OWNER);
Googlercdc90e92015-02-11 00:18:07 +0000678 if (actionsWrapper != null) {
Rumou Duan33bab462016-04-25 17:55:12 +0000679 ImmutableList<ActionAnalysisMetadata> actions = actionsWrapper.getActions();
Googlercdc90e92015-02-11 00:18:07 +0000680 skyframeExecutor.injectCoverageReportData(actions);
681 artifactsToBuild.addAll(actionsWrapper.getCoverageOutputs());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100682 }
683 }
684
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000685 // Tests. This must come last, so that the exclusive tests are scheduled after everything else.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100686 scheduleTestsIfRequested(parallelTests, exclusiveTests, topLevelOptions, allTargetsToTest);
687
Janak Ramakrishnan6f9d7d12016-08-09 08:45:34 +0000688 String error = createErrorMessage(loadingResult, skyframeAnalysisResult);
Eric Fellheimer9c1e12f2015-08-06 20:23:55 +0000689
Ulf Adams53abece2016-02-03 08:30:07 +0000690 final WalkableGraph graph = skyframeAnalysisResult.getWalkableGraph();
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000691 final ActionGraph actionGraph =
692 new ActionGraph() {
693 @Nullable
694 @Override
695 public ActionAnalysisMetadata getGeneratingAction(Artifact artifact) {
696 ArtifactOwner artifactOwner = artifact.getArtifactOwner();
697 if (artifactOwner instanceof ActionLookupValue.ActionLookupKey) {
698 SkyKey key = ActionLookupValue.key((ActionLookupValue.ActionLookupKey) artifactOwner);
699 ActionLookupValue val;
700 try {
701 val = (ActionLookupValue) graph.getValue(key);
702 } catch (InterruptedException e) {
703 throw new IllegalStateException(
704 "Interruption not expected from this graph: " + key, e);
705 }
janakr93e3eea2017-03-30 22:09:37 +0000706 return val == null ? null : val.getGeneratingActionDangerousReadJavadoc(artifact);
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000707 }
708 return null;
709 }
710 };
Dmitry Lomove2033b12015-08-19 16:57:49 +0000711 return new AnalysisResult(
712 configuredTargets,
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000713 aspects,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000714 allTargetsToTest,
gregce45ae0962017-07-22 00:11:13 +0200715 targetsToSkip,
Dmitry Lomove2033b12015-08-19 16:57:49 +0000716 error,
717 actionGraph,
718 artifactsToBuild,
719 parallelTests,
720 exclusiveTests,
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000721 topLevelOptions,
Kristina Chodorow36a6c172016-07-22 15:18:07 +0000722 skyframeAnalysisResult.getPackageRoots(),
723 loadingResult.getWorkspaceName());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100724 }
725
Janak Ramakrishnan6f9d7d12016-08-09 08:45:34 +0000726 @Nullable
727 public static String createErrorMessage(
728 LoadingResult loadingResult, @Nullable SkyframeAnalysisResult skyframeAnalysisResult) {
729 return loadingResult.hasTargetPatternError()
730 ? "command succeeded, but there were errors parsing the target pattern"
731 : loadingResult.hasLoadingError()
732 || (skyframeAnalysisResult != null && skyframeAnalysisResult.hasLoadingError())
733 ? "command succeeded, but there were loading phase errors"
734 : (skyframeAnalysisResult != null && skyframeAnalysisResult.hasAnalysisError())
735 ? "command succeeded, but not all targets were analyzed"
736 : null;
737 }
738
Lukacs Berki6916be22015-02-19 13:36:06 +0000739 private static NestedSet<Artifact> getBaselineCoverageArtifacts(
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100740 Collection<ConfiguredTarget> configuredTargets) {
Lukacs Berki6916be22015-02-19 13:36:06 +0000741 NestedSetBuilder<Artifact> baselineCoverageArtifacts = NestedSetBuilder.stableOrder();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100742 for (ConfiguredTarget target : configuredTargets) {
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000743 InstrumentedFilesProvider provider = target.getProvider(InstrumentedFilesProvider.class);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100744 if (provider != null) {
Ulf Adamsfc154ae2015-08-31 12:32:14 +0000745 baselineCoverageArtifacts.addTransitive(provider.getBaselineCoverageArtifacts());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100746 }
747 }
Lukacs Berki6916be22015-02-19 13:36:06 +0000748 return baselineCoverageArtifacts.build();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100749 }
750
Dmitry Lomovcf6021a2016-08-09 16:49:32 +0000751 private void addExtraActionsIfRequested(Options viewOptions,
752 Collection<ConfiguredTarget> configuredTargets,
753 Collection<AspectValue> aspects,
754 Set<Artifact> artifactsToBuild) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000755 Iterable<Artifact> extraActionArtifacts =
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000756 concat(
757 addExtraActionsFromTargets(viewOptions, configuredTargets),
758 addExtraActionsFromAspects(viewOptions, aspects));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100759
760 RegexFilter filter = viewOptions.extraActionFilter;
Carmi Grushkobabd4852016-11-18 17:58:09 +0000761 for (Artifact artifact : extraActionArtifacts) {
762 boolean filterMatches =
763 filter == null || filter.isIncluded(artifact.getOwnerLabel().toString());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100764 if (filterMatches) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000765 artifactsToBuild.add(artifact);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100766 }
767 }
768 }
769
Carmi Grushkobabd4852016-11-18 17:58:09 +0000770 private NestedSet<Artifact> addExtraActionsFromTargets(
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000771 BuildView.Options viewOptions, Collection<ConfiguredTarget> configuredTargets) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000772 NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000773 for (ConfiguredTarget target : configuredTargets) {
774 ExtraActionArtifactsProvider provider =
775 target.getProvider(ExtraActionArtifactsProvider.class);
776 if (provider != null) {
777 if (viewOptions.extraActionTopLevelOnly) {
lberki9137a752017-06-09 12:49:10 +0200778 // Collect all aspect-classes that topLevel might inject.
779 Set<AspectClass> aspectClasses = new HashSet<>();
780 for (Attribute attr : target.getTarget().getAssociatedRule().getAttributes()) {
781 aspectClasses.addAll(attr.getAspectClasses());
782 }
Carmi Grushko9a796de2016-11-13 12:22:30 +0000783
lberki9137a752017-06-09 12:49:10 +0200784 builder.addTransitive(provider.getExtraActionArtifacts());
785 if (!aspectClasses.isEmpty()) {
786 builder.addAll(filterTransitiveExtraActions(provider, aspectClasses));
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000787 }
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000788 } else {
789 builder.addTransitive(provider.getTransitiveExtraActionArtifacts());
790 }
791 }
792 }
793 return builder.build();
794 }
795
796 /**
797 * Returns a list of actions from 'provider' that were registered by an aspect from
798 * 'aspectClasses'. All actions in 'provider' are considered - both direct and transitive.
799 */
800 private ImmutableList<Artifact> filterTransitiveExtraActions(
801 ExtraActionArtifactsProvider provider, Set<AspectClass> aspectClasses) {
802 ImmutableList.Builder<Artifact> artifacts = ImmutableList.builder();
803 // Add to 'artifacts' all extra-actions which were registered by aspects which 'topLevel'
804 // might have injected.
Carmi Grushkobabd4852016-11-18 17:58:09 +0000805 for (Artifact artifact : provider.getTransitiveExtraActionArtifacts()) {
806 ArtifactOwner owner = artifact.getArtifactOwner();
807 if (owner instanceof AspectKey) {
808 if (aspectClasses.contains(((AspectKey) owner).getAspectClass())) {
809 artifacts.add(artifact);
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000810 }
811 }
812 }
813 return artifacts.build();
814 }
815
Carmi Grushkobabd4852016-11-18 17:58:09 +0000816 private NestedSet<Artifact> addExtraActionsFromAspects(
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000817 BuildView.Options viewOptions, Collection<AspectValue> aspects) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000818 NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000819 for (AspectValue aspect : aspects) {
820 ExtraActionArtifactsProvider provider =
821 aspect.getConfiguredAspect().getProvider(ExtraActionArtifactsProvider.class);
822 if (provider != null) {
823 if (viewOptions.extraActionTopLevelOnly) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000824 builder.addTransitive(provider.getExtraActionArtifacts());
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000825 } else {
826 builder.addTransitive(provider.getTransitiveExtraActionArtifacts());
827 }
828 }
829 }
830 return builder.build();
831 }
832
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100833 private static void scheduleTestsIfRequested(Collection<ConfiguredTarget> targetsToTest,
834 Collection<ConfiguredTarget> targetsToTestExclusive, TopLevelArtifactContext topLevelOptions,
835 Collection<ConfiguredTarget> allTestTargets) {
Lukacs Berki3f4d4e92015-02-24 10:28:26 +0000836 Set<String> outputGroups = topLevelOptions.outputGroups();
Lukacs Berki1e79b962015-03-03 10:59:21 +0000837 if (!outputGroups.contains(OutputGroupProvider.FILES_TO_COMPILE)
838 && !outputGroups.contains(OutputGroupProvider.COMPILATION_PREREQUISITES)
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100839 && allTestTargets != null) {
840 scheduleTests(targetsToTest, targetsToTestExclusive, allTestTargets,
841 topLevelOptions.runTestsExclusively());
842 }
843 }
844
845
846 /**
847 * Returns set of artifacts representing test results, writing into targetsToTest and
848 * targetsToTestExclusive.
849 */
850 private static void scheduleTests(Collection<ConfiguredTarget> targetsToTest,
851 Collection<ConfiguredTarget> targetsToTestExclusive,
852 Collection<ConfiguredTarget> allTestTargets,
853 boolean isExclusive) {
854 for (ConfiguredTarget target : allTestTargets) {
855 if (target.getTarget() instanceof Rule) {
856 boolean exclusive =
857 isExclusive || TargetUtils.isExclusiveTestRule((Rule) target.getTarget());
858 Collection<ConfiguredTarget> testCollection = exclusive
859 ? targetsToTestExclusive
860 : targetsToTest;
861 testCollection.add(target);
862 }
863 }
864 }
865
Greg Estren7971e672016-06-01 23:22:48 +0000866 /**
867 * Given a set of top-level targets and a configuration collection, returns the appropriate
868 * <Target, Configuration> pair for each target.
869 *
870 * <p>Preserves the original input ordering.
871 */
872 private List<TargetAndConfiguration> nodesForTopLevelTargets(
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000873 BuildConfigurationCollection configurations,
874 Collection<Target> targets,
875 ExtendedEventHandler eventHandler)
876 throws InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100877 // We use a hash set here to remove duplicate nodes; this can happen for input files and package
878 // groups.
879 LinkedHashSet<TargetAndConfiguration> nodes = new LinkedHashSet<>(targets.size());
880 for (BuildConfiguration config : configurations.getTargetConfigurations()) {
881 for (Target target : targets) {
gregce8b4f9f52017-08-17 20:50:22 +0200882 nodes.add(new TargetAndConfiguration(target, target.isConfigurable() ? config : null));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100883 }
884 }
gregce408bfe472017-09-14 00:47:27 +0200885 return ImmutableList.copyOf(getConfigurations(nodes, eventHandler));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100886 }
887
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100888 /**
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000889 * If {@link BuildConfiguration.Options#trimConfigurations()} is true, transforms a collection of
890 * <Target, Configuration> pairs by trimming each target's configuration to only the fragments the
891 * target and its transitive dependencies need.
Greg Estren7971e672016-06-01 23:22:48 +0000892 *
Greg Estren1d8ba902016-09-21 21:18:19 +0000893 * <p>Else returns configurations that unconditionally include all fragments.
894 *
gregce3b8ffd12017-05-05 20:53:32 +0200895 * <p>Preserves the original input order (but merges duplicate nodes that might occur due to
896 * top-level configuration transitions) . Uses original (untrimmed) configurations for targets
Greg Estren7971e672016-06-01 23:22:48 +0000897 * that can't be evaluated (e.g. due to loading phase errors).
898 *
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000899 * <p>This is suitable for feeding {@link ConfiguredTargetValue} keys: as general principle {@link
900 * ConfiguredTarget}s should have exactly as much information in their configurations as they need
901 * to evaluate and no more (e.g. there's no need for Android settings in a C++ configured target).
Greg Estren7971e672016-06-01 23:22:48 +0000902 */
903 // TODO(bazel-team): error out early for targets that fail - untrimmed configurations should
904 // never make it through analysis (and especially not seed ConfiguredTargetValues)
gregce408bfe472017-09-14 00:47:27 +0200905 private LinkedHashSet<TargetAndConfiguration> getConfigurations(
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000906 Iterable<TargetAndConfiguration> inputs, ExtendedEventHandler eventHandler)
Greg Estren1d8ba902016-09-21 21:18:19 +0000907 throws InterruptedException {
Greg Estren7883bf12016-11-18 20:03:43 +0000908 Map<Label, Target> labelsToTargets = new LinkedHashMap<>();
909 // We'll get the configs from SkyframeExecutor#getConfigurations, which gets configurations
910 // for deps including transitions. So to satisfy its API we repackage each target as a
911 // Dependency with a NONE transition.
912 Multimap<BuildConfiguration, Dependency> asDeps =
913 ArrayListMultimap.<BuildConfiguration, Dependency>create();
Greg Estren7971e672016-06-01 23:22:48 +0000914
915 for (TargetAndConfiguration targetAndConfig : inputs) {
Greg Estren7883bf12016-11-18 20:03:43 +0000916 labelsToTargets.put(targetAndConfig.getLabel(), targetAndConfig.getTarget());
917 if (targetAndConfig.getConfiguration() != null) {
918 asDeps.put(targetAndConfig.getConfiguration(),
919 Dependency.withTransitionAndAspects(
gregce692f763f2017-07-06 22:51:30 -0400920 targetAndConfig.getLabel(),
921 getTopLevelTransition(targetAndConfig,
922 ruleClassProvider.getDynamicTransitionMapper()),
Greg Estren7883bf12016-11-18 20:03:43 +0000923 // TODO(bazel-team): support top-level aspects
Dmitry Lomove851fe22017-02-14 23:11:23 +0000924 AspectCollection.EMPTY));
Greg Estren7971e672016-06-01 23:22:48 +0000925 }
926 }
927
gregce408bfe472017-09-14 00:47:27 +0200928 // Maps <target, originalConfig> pairs to <target, finalConfig> pairs for targets that
Greg Estren7883bf12016-11-18 20:03:43 +0000929 // could be successfully Skyframe-evaluated.
930 Map<TargetAndConfiguration, TargetAndConfiguration> successfullyEvaluatedTargets =
931 new LinkedHashMap<>();
Greg Estren7971e672016-06-01 23:22:48 +0000932 if (!asDeps.isEmpty()) {
Greg Estren7883bf12016-11-18 20:03:43 +0000933 for (BuildConfiguration fromConfig : asDeps.keySet()) {
Greg Estren0db9b112016-12-05 21:55:54 +0000934 Multimap<Dependency, BuildConfiguration> trimmedTargets =
Greg Estren7883bf12016-11-18 20:03:43 +0000935 skyframeExecutor.getConfigurations(eventHandler, fromConfig.getOptions(),
936 asDeps.get(fromConfig));
Greg Estren0db9b112016-12-05 21:55:54 +0000937 for (Map.Entry<Dependency, BuildConfiguration> trimmedTarget : trimmedTargets.entries()) {
Greg Estren7883bf12016-11-18 20:03:43 +0000938 Target target = labelsToTargets.get(trimmedTarget.getKey().getLabel());
939 successfullyEvaluatedTargets.put(
940 new TargetAndConfiguration(target, fromConfig),
941 new TargetAndConfiguration(target, trimmedTarget.getValue()));
942 }
Greg Estren7971e672016-06-01 23:22:48 +0000943 }
944 }
945
gregce3b8ffd12017-05-05 20:53:32 +0200946 LinkedHashSet<TargetAndConfiguration> result = new LinkedHashSet<>();
Greg Estren7971e672016-06-01 23:22:48 +0000947 for (TargetAndConfiguration originalInput : inputs) {
Greg Estren7883bf12016-11-18 20:03:43 +0000948 if (successfullyEvaluatedTargets.containsKey(originalInput)) {
Greg Estren7971e672016-06-01 23:22:48 +0000949 // The configuration was successfully trimmed.
Greg Estren7883bf12016-11-18 20:03:43 +0000950 result.add(successfullyEvaluatedTargets.get(originalInput));
Greg Estren7971e672016-06-01 23:22:48 +0000951 } else {
952 // Either the configuration couldn't be determined (e.g. loading phase error) or it's null.
953 result.add(originalInput);
954 }
955 }
gregce3b8ffd12017-05-05 20:53:32 +0200956 return result;
Greg Estren7971e672016-06-01 23:22:48 +0000957 }
958
Greg Estren01a78e72016-06-17 16:16:16 +0000959 /**
gregce3b8ffd12017-05-05 20:53:32 +0200960 * Returns the transition to apply to the top-level configuration before applying it to this
961 * target. This enables support for rule-triggered top-level configuration hooks.
962 */
gregce692f763f2017-07-06 22:51:30 -0400963 private static Attribute.Transition getTopLevelTransition(TargetAndConfiguration targetAndConfig,
964 DynamicTransitionMapper dynamicTransitionMapper) {
gregce3b8ffd12017-05-05 20:53:32 +0200965 Target target = targetAndConfig.getTarget();
966 BuildConfiguration fromConfig = targetAndConfig.getConfiguration();
gregce3b8ffd12017-05-05 20:53:32 +0200967
968 // Top-level transitions (chosen by configuration fragments):
969 Transition topLevelTransition = fromConfig.topLevelConfigurationHook(target);
970 if (topLevelTransition == null) {
971 topLevelTransition = ConfigurationTransition.NONE;
972 }
973
974 // Rule class transitions (chosen by rule class definitions):
975 if (target.getAssociatedRule() == null) {
976 return topLevelTransition;
977 }
978 Rule associatedRule = target.getAssociatedRule();
979 RuleTransitionFactory transitionFactory =
980 associatedRule.getRuleClassObject().getTransitionFactory();
981 if (transitionFactory == null) {
982 return topLevelTransition;
983 }
gregce692f763f2017-07-06 22:51:30 -0400984 // dynamicTransitionMapper is only needed because of Attribute.ConfigurationTransition.DATA:
985 // this is C++-specific but non-C++ rules declare it. So they can't directly provide the
986 // C++-specific patch transition that implements it.
987 PatchTransition ruleClassTransition = (PatchTransition)
988 dynamicTransitionMapper.map(transitionFactory.buildTransitionFor(associatedRule));
gregce3b8ffd12017-05-05 20:53:32 +0200989 if (ruleClassTransition == null) {
990 return topLevelTransition;
991 } else if (topLevelTransition == ConfigurationTransition.NONE) {
992 return ruleClassTransition;
993 } else {
994 return new ComposingSplitTransition(topLevelTransition, ruleClassTransition);
995 }
996 }
997
998
999 /**
gregce408bfe472017-09-14 00:47:27 +02001000 * Gets a configuration for the given target.
Greg Estren1d8ba902016-09-21 21:18:19 +00001001 *
1002 * <p>If {@link BuildConfiguration.Options#trimConfigurations()} is true, the configuration only
1003 * includes the fragments needed by the fragment and its transitive closure. Else unconditionally
1004 * includes all fragments.
Greg Estren01a78e72016-06-17 16:16:16 +00001005 */
1006 @VisibleForTesting
gregce408bfe472017-09-14 00:47:27 +02001007 public BuildConfiguration getConfigurationForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001008 Target target, BuildConfiguration config, ExtendedEventHandler eventHandler)
1009 throws InterruptedException {
gregce408bfe472017-09-14 00:47:27 +02001010 return Iterables.getOnlyElement(getConfigurations(
Greg Estren01a78e72016-06-17 16:16:16 +00001011 ImmutableList.<TargetAndConfiguration>of(new TargetAndConfiguration(target, config)),
1012 eventHandler)).getConfiguration();
1013 }
Greg Estren7971e672016-06-01 23:22:48 +00001014
1015 /**
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001016 * Sets the possible artifact roots in the artifact factory. This allows the factory to resolve
1017 * paths with unknown roots to artifacts.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001018 */
1019 @VisibleForTesting // for BuildViewTestCase
janakrae323982017-09-29 21:11:53 +02001020 public void setArtifactRoots(PackageRoots packageRoots) {
1021 getArtifactFactory().setPackageRoots(packageRoots.getPackageRootLookup());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001022 }
1023
1024 /**
Ulf Adams9c505cb2015-09-28 13:38:14 +00001025 * Tests and clears the current thread's pending "interrupted" status, and
1026 * throws InterruptedException iff it was set.
1027 */
1028 protected final void pollInterruptedStatus() throws InterruptedException {
1029 if (Thread.interrupted()) {
1030 throw new InterruptedException();
1031 }
1032 }
1033
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001034 // For testing
1035 @VisibleForTesting
1036 public Iterable<ConfiguredTarget> getDirectPrerequisitesForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001037 ExtendedEventHandler eventHandler, ConfiguredTarget ct,
1038 BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +00001039 throws EvalException, InvalidConfigurationException,
1040 InterruptedException, InconsistentAspectOrderException {
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001041 return skyframeExecutor.getConfiguredTargets(
cpeyserb38e3af2017-09-11 16:58:58 +02001042 eventHandler,
1043 ct.getConfiguration(),
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001044 ImmutableSet.copyOf(
cpeyserb38e3af2017-09-11 16:58:58 +02001045 getDirectPrerequisiteDependenciesForTesting(
1046 eventHandler, ct, configurations, /*toolchainContext=*/ null)
gregce5303cc02017-09-13 22:08:14 +02001047 .values()));
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001048 }
1049
1050 @VisibleForTesting
Greg Estrend5353252016-08-11 22:13:31 +00001051 public OrderedSetMultimap<Attribute, Dependency> getDirectPrerequisiteDependenciesForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001052 final ExtendedEventHandler eventHandler,
1053 final ConfiguredTarget ct,
cpeyserb38e3af2017-09-11 16:58:58 +02001054 BuildConfigurationCollection configurations,
1055 ToolchainContext toolchainContext)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +00001056 throws EvalException, InvalidConfigurationException, InterruptedException,
cpeyserb38e3af2017-09-11 16:58:58 +02001057 InconsistentAspectOrderException {
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001058 if (!(ct.getTarget() instanceof Rule)) {
Greg Estrend5353252016-08-11 22:13:31 +00001059 return OrderedSetMultimap.create();
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001060 }
1061
1062 class SilentDependencyResolver extends DependencyResolver {
gregce85297462017-08-18 21:20:29 +02001063 private SilentDependencyResolver() {
1064 super(ruleClassProvider.getDynamicTransitionMapper());
1065 }
1066
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001067 @Override
1068 protected void invalidVisibilityReferenceHook(TargetAndConfiguration node, Label label) {
Ulf Adams84901732016-01-28 15:05:16 +00001069 throw new RuntimeException("bad visibility on " + label + " during testing unexpected");
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001070 }
1071
1072 @Override
1073 protected void invalidPackageGroupReferenceHook(TargetAndConfiguration node, Label label) {
Ulf Adams84901732016-01-28 15:05:16 +00001074 throw new RuntimeException("bad package group on " + label + " during testing unexpected");
1075 }
1076
1077 @Override
1078 protected void missingEdgeHook(Target from, Label to, NoSuchThingException e) {
1079 throw new RuntimeException(
1080 "missing dependency from " + from.getLabel() + " to " + to + ": " + e.getMessage(),
1081 e);
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001082 }
1083
1084 @Override
Janak Ramakrishnan03e4f9c2016-08-16 18:59:56 +00001085 protected Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses)
1086 throws InterruptedException {
Ulf Adams2ac20962016-02-01 13:04:54 +00001087 try {
Janak Ramakrishnan03e4f9c2016-08-16 18:59:56 +00001088 return skyframeExecutor.getPackageManager().getTarget(eventHandler, label);
Ulf Adams2ac20962016-02-01 13:04:54 +00001089 } catch (NoSuchThingException e) {
1090 throw new IllegalStateException(e);
1091 }
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001092 }
Greg Estren373e3e22016-08-09 22:36:51 +00001093
1094 @Override
1095 protected List<BuildConfiguration> getConfigurations(
1096 Set<Class<? extends BuildConfiguration.Fragment>> fragments,
1097 Iterable<BuildOptions> buildOptions) {
1098 Preconditions.checkArgument(ct.getConfiguration().fragmentClasses().equals(fragments));
1099 Dependency asDep = Dependency.withTransitionAndAspects(ct.getLabel(),
Dmitry Lomove851fe22017-02-14 23:11:23 +00001100 Attribute.ConfigurationTransition.NONE, AspectCollection.EMPTY);
Greg Estren373e3e22016-08-09 22:36:51 +00001101 ImmutableList.Builder<BuildConfiguration> builder = ImmutableList.builder();
1102 for (BuildOptions options : buildOptions) {
1103 builder.add(Iterables.getOnlyElement(
1104 skyframeExecutor
1105 .getConfigurations(eventHandler, options, ImmutableList.<Dependency>of(asDep))
1106 .values()
1107 ));
1108 }
1109 return builder.build();
1110 }
Ulf Adamsa4ca6372016-01-11 14:20:28 +00001111 }
1112
1113 DependencyResolver dependencyResolver = new SilentDependencyResolver();
1114 TargetAndConfiguration ctgNode =
1115 new TargetAndConfiguration(ct.getTarget(), ct.getConfiguration());
1116 return dependencyResolver.dependentNodeMap(
cpeyserb38e3af2017-09-11 16:58:58 +02001117 ctgNode,
1118 configurations.getHostConfiguration(),
1119 /*aspect=*/ null,
1120 getConfigurableAttributeKeysForTesting(eventHandler, ctgNode),
1121 toolchainContext);
Ulf Adams9c505cb2015-09-28 13:38:14 +00001122 }
1123
1124 /**
1125 * Returns ConfigMatchingProvider instances corresponding to the configurable attribute keys
1126 * present in this rule's attributes.
1127 */
Lukacs Berki7894c182016-05-10 12:07:01 +00001128 private ImmutableMap<Label, ConfigMatchingProvider> getConfigurableAttributeKeysForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001129 ExtendedEventHandler eventHandler, TargetAndConfiguration ctg) {
Ulf Adams9c505cb2015-09-28 13:38:14 +00001130 if (!(ctg.getTarget() instanceof Rule)) {
Lukacs Berki7894c182016-05-10 12:07:01 +00001131 return ImmutableMap.of();
Ulf Adams9c505cb2015-09-28 13:38:14 +00001132 }
1133 Rule rule = (Rule) ctg.getTarget();
Lukacs Berki53e03912016-05-19 16:26:09 +00001134 Map<Label, ConfigMatchingProvider> keys = new LinkedHashMap<>();
Ulf Adams9c505cb2015-09-28 13:38:14 +00001135 RawAttributeMapper mapper = RawAttributeMapper.of(rule);
1136 for (Attribute attribute : rule.getAttributes()) {
1137 for (Label label : mapper.getConfigurabilityKeys(attribute.getName(), attribute.getType())) {
1138 if (BuildType.Selector.isReservedLabel(label)) {
1139 continue;
1140 }
1141 ConfiguredTarget ct = getConfiguredTargetForTesting(
1142 eventHandler, label, ctg.getConfiguration());
Lukacs Berki7894c182016-05-10 12:07:01 +00001143 keys.put(label, Preconditions.checkNotNull(ct.getProvider(ConfigMatchingProvider.class)));
Ulf Adams9c505cb2015-09-28 13:38:14 +00001144 }
1145 }
Lukacs Berki53e03912016-05-19 16:26:09 +00001146 return ImmutableMap.copyOf(keys);
Ulf Adams9c505cb2015-09-28 13:38:14 +00001147 }
1148
Greg Estrend5353252016-08-11 22:13:31 +00001149 private OrderedSetMultimap<Attribute, ConfiguredTarget> getPrerequisiteMapForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001150 final ExtendedEventHandler eventHandler,
1151 ConfiguredTarget target,
cpeyserb38e3af2017-09-11 16:58:58 +02001152 BuildConfigurationCollection configurations,
1153 ToolchainContext toolchainContext)
1154 throws EvalException, InvalidConfigurationException, InterruptedException,
1155 InconsistentAspectOrderException {
Greg Estrend5353252016-08-11 22:13:31 +00001156 OrderedSetMultimap<Attribute, Dependency> depNodeNames =
cpeyserb38e3af2017-09-11 16:58:58 +02001157 getDirectPrerequisiteDependenciesForTesting(
1158 eventHandler, target, configurations, toolchainContext);
Ulf Adams9c505cb2015-09-28 13:38:14 +00001159
Greg Estren0db9b112016-12-05 21:55:54 +00001160 ImmutableMultimap<Dependency, ConfiguredTarget> cts = skyframeExecutor.getConfiguredTargetMap(
Ulf Adams9c505cb2015-09-28 13:38:14 +00001161 eventHandler,
gregce5303cc02017-09-13 22:08:14 +02001162 target.getConfiguration(), ImmutableSet.copyOf(depNodeNames.values()));
Ulf Adams9c505cb2015-09-28 13:38:14 +00001163
Greg Estrend5353252016-08-11 22:13:31 +00001164 OrderedSetMultimap<Attribute, ConfiguredTarget> result = OrderedSetMultimap.create();
Ulf Adams9c505cb2015-09-28 13:38:14 +00001165 for (Map.Entry<Attribute, Dependency> entry : depNodeNames.entries()) {
Greg Estren0db9b112016-12-05 21:55:54 +00001166 result.putAll(entry.getKey(), cts.get(entry.getValue()));
Ulf Adams9c505cb2015-09-28 13:38:14 +00001167 }
Greg Estrend5353252016-08-11 22:13:31 +00001168 return result;
Ulf Adams9c505cb2015-09-28 13:38:14 +00001169 }
1170
Cal Peyser8a638d52017-03-24 15:44:24 +00001171 private Transition getTopLevelTransitionForTarget(Label label, ExtendedEventHandler handler) {
1172 Rule rule;
1173 try {
1174 rule = skyframeExecutor
1175 .getPackageManager()
1176 .getTarget(handler, label)
1177 .getAssociatedRule();
1178 } catch (NoSuchPackageException | NoSuchTargetException e) {
1179 return ConfigurationTransition.NONE;
1180 } catch (InterruptedException e) {
1181 Thread.currentThread().interrupt();
1182 throw new AssertionError("Configuration of " + label + " interrupted");
1183 }
1184 if (rule == null) {
1185 return ConfigurationTransition.NONE;
1186 }
1187 RuleTransitionFactory factory = rule
1188 .getRuleClassObject()
1189 .getTransitionFactory();
mstaib274cb262017-03-29 20:12:19 +00001190 if (factory == null) {
1191 return ConfigurationTransition.NONE;
1192 }
gregce692f763f2017-07-06 22:51:30 -04001193
1194 // dynamicTransitionMapper is only needed because of Attribute.ConfigurationTransition.DATA:
1195 // this is C++-specific but non-C++ rules declare it. So they can't directly provide the
1196 // C++-specific patch transition that implements it.
1197 PatchTransition transition = (PatchTransition)
1198 ruleClassProvider.getDynamicTransitionMapper().map(factory.buildTransitionFor(rule));
mstaib274cb262017-03-29 20:12:19 +00001199 return (transition == null) ? ConfigurationTransition.NONE : transition;
Cal Peyser8a638d52017-03-24 15:44:24 +00001200 }
1201
Ulf Adams9c505cb2015-09-28 13:38:14 +00001202 /**
gregce408bfe472017-09-14 00:47:27 +02001203 * Returns a configured target for the specified target and configuration. If the target in
1204 * question has a top-level rule class transition, that transition is applied in the returned
1205 * ConfiguredTarget.
1206 *
1207 * <p>Returns {@code null} if something goes wrong.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001208 */
1209 @VisibleForTesting
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001210 public ConfiguredTarget getConfiguredTargetForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001211 ExtendedEventHandler eventHandler, Label label, BuildConfiguration config) {
Cal Peyser8a638d52017-03-24 15:44:24 +00001212 return skyframeExecutor.getConfiguredTargetForTesting(eventHandler, label, config,
1213 getTopLevelTransitionForTarget(label, eventHandler));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001214 }
1215
1216 /**
1217 * Returns a RuleContext which is the same as the original RuleContext of the target parameter.
1218 */
1219 @VisibleForTesting
Florian Weikert4b67d4f2015-09-14 13:35:34 +00001220 public RuleContext getRuleContextForTesting(
cpeyser1099b542017-09-06 18:19:20 +02001221 ConfiguredTarget target,
1222 StoredEventHandler eventHandler,
Lukacs Berki76cb02e2017-02-17 14:06:11 +00001223 BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +00001224 throws EvalException, InvalidConfigurationException, InterruptedException,
cpeyser1099b542017-09-06 18:19:20 +02001225 InconsistentAspectOrderException, ToolchainContextException {
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001226 BuildConfiguration targetConfig = target.getConfiguration();
1227 CachingAnalysisEnvironment env =
Ulf Adams89eefd72015-09-23 08:00:43 +00001228 new CachingAnalysisEnvironment(getArtifactFactory(),
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001229 new ConfiguredTargetKey(target.getLabel(), targetConfig),
1230 /*isSystemEnv=*/false, targetConfig.extendedSanityChecks(), eventHandler,
cushone1d2e392017-09-29 13:54:04 -04001231 /*env=*/null, targetConfig.isActionsEnabled());
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001232 return getRuleContextForTesting(eventHandler, target, env, configurations);
Ulf Adams79f05212015-02-27 16:40:00 +00001233 }
1234
1235 /**
1236 * Creates and returns a rule context that is equivalent to the one that was used to create the
1237 * given configured target.
1238 */
1239 @VisibleForTesting
cpeyser1099b542017-09-06 18:19:20 +02001240 public RuleContext getRuleContextForTesting(
1241 ExtendedEventHandler eventHandler,
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001242 ConfiguredTarget target,
cpeyser1099b542017-09-06 18:19:20 +02001243 AnalysisEnvironment env,
1244 BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +00001245 throws EvalException, InvalidConfigurationException, InterruptedException,
cpeyser1099b542017-09-06 18:19:20 +02001246 InconsistentAspectOrderException, ToolchainContextException {
Greg Estren9eb1cf02015-06-26 22:18:35 +00001247 BuildConfiguration targetConfig = target.getConfiguration();
cpeyserfb829992017-09-07 17:17:03 +02001248 Set<Label> requiredToolchains =
cpeyser1099b542017-09-06 18:19:20 +02001249 target.getTarget().getAssociatedRule().getRuleClassObject().getRequiredToolchains();
1250 ToolchainContext toolchainContext =
1251 skyframeExecutor.getToolchainContextForTesting(
1252 requiredToolchains, targetConfig, eventHandler);
cpeyserb38e3af2017-09-11 16:58:58 +02001253 OrderedSetMultimap<Attribute, ConfiguredTarget> prerequisiteMap =
1254 getPrerequisiteMapForTesting(eventHandler, target, configurations, toolchainContext);
1255 toolchainContext.resolveToolchains(prerequisiteMap);
cpeyser1099b542017-09-06 18:19:20 +02001256
Ulf Adams79f05212015-02-27 16:40:00 +00001257 return new RuleContext.Builder(
Mark Schaller0312f912016-07-22 18:45:02 +00001258 env,
1259 (Rule) target.getTarget(),
Dmitry Lomov15756522016-12-16 16:52:37 +00001260 ImmutableList.<AspectDescriptor>of(),
Mark Schaller0312f912016-07-22 18:45:02 +00001261 targetConfig,
1262 configurations.getHostConfiguration(),
1263 ruleClassProvider.getPrerequisiteValidator(),
1264 ((Rule) target.getTarget()).getRuleClassObject().getConfigurationFragmentPolicy())
1265 .setVisibility(
1266 NestedSetBuilder.<PackageSpecification>create(
1267 Order.STABLE_ORDER, PackageSpecification.everything()))
cpeyserb38e3af2017-09-11 16:58:58 +02001268 .setPrerequisites(
1269 getPrerequisiteMapForTesting(eventHandler, target, configurations, toolchainContext))
Mark Schaller0312f912016-07-22 18:45:02 +00001270 .setConfigConditions(ImmutableMap.<Label, ConfigMatchingProvider>of())
1271 .setUniversalFragment(ruleClassProvider.getUniversalFragment())
cpeyser1099b542017-09-06 18:19:20 +02001272 .setToolchainContext(toolchainContext)
Mark Schaller0312f912016-07-22 18:45:02 +00001273 .build();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001274 }
1275
1276 /**
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001277 * For a configured target dependentTarget, returns the desired configured target that is depended
1278 * upon. Useful for obtaining the a target with aspects required by the dependent.
Googler9263b462015-05-13 19:22:24 +00001279 */
1280 @VisibleForTesting
1281 public ConfiguredTarget getPrerequisiteConfiguredTargetForTesting(
Klaus Aehlig777b30d2017-02-24 16:30:15 +00001282 ExtendedEventHandler eventHandler,
1283 ConfiguredTarget dependentTarget,
1284 Label desiredTarget,
Ulf Adamse7704672015-09-21 14:37:41 +00001285 BuildConfigurationCollection configurations)
Dmitry Lomovd83af9e2017-02-23 15:44:23 +00001286 throws EvalException, InvalidConfigurationException, InterruptedException,
1287 InconsistentAspectOrderException {
Googler9263b462015-05-13 19:22:24 +00001288 Collection<ConfiguredTarget> configuredTargets =
cpeyserb38e3af2017-09-11 16:58:58 +02001289 getPrerequisiteMapForTesting(
1290 eventHandler, dependentTarget, configurations, /*toolchainContext=*/ null)
1291 .values();
Googler9263b462015-05-13 19:22:24 +00001292 for (ConfiguredTarget ct : configuredTargets) {
Ulf Adamsa385d3e2015-09-28 13:21:45 +00001293 if (ct.getLabel().equals(desiredTarget)) {
Googler9263b462015-05-13 19:22:24 +00001294 return ct;
1295 }
1296 }
1297 return null;
1298 }
Janak Ramakrishnanbede7b42016-11-17 18:34:08 +00001299
1300 /**
1301 * A converter for loading phase thread count. Since the default is not a true constant, we create
1302 * a converter here to implement the default logic.
1303 */
1304 public static final class LoadingPhaseThreadCountConverter implements Converter<Integer> {
1305 @Override
1306 public Integer convert(String input) throws OptionsParsingException {
1307 if ("-1".equals(input)) {
1308 // Reduce thread count while running tests. Test cases are typically small, and large thread
1309 // pools vying for a relatively small number of CPU cores may induce non-optimal
1310 // performance.
1311 return System.getenv("TEST_TMPDIR") == null ? 200 : 5;
1312 }
1313
1314 try {
1315 int result = Integer.decode(input);
1316 if (result < 0) {
1317 throw new OptionsParsingException("'" + input + "' must be at least -1");
1318 }
1319 return result;
1320 } catch (NumberFormatException e) {
1321 throw new OptionsParsingException("'" + input + "' is not an int");
1322 }
1323 }
1324
1325 @Override
1326 public String getTypeDescription() {
1327 return "an integer";
1328 }
1329 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001330}