in src/main/java/com/google/devtools/build/lib/analysis/BuildView.java [194:494]
public AnalysisResult update(
TargetPatternPhaseValue loadingResult,
BuildOptions targetOptions,
Set<String> multiCpu,
ImmutableSet<String> explicitTargetPatterns,
List<String> aspects,
ImmutableMap<String, String> aspectsParameters,
AnalysisOptions viewOptions,
boolean keepGoing,
boolean checkForActionConflicts,
int loadingPhaseThreads,
TopLevelArtifactContext topLevelOptions,
boolean reportIncompatibleTargets,
ExtendedEventHandler eventHandler,
EventBus eventBus,
boolean includeExecutionPhase,
int mergedPhasesExecutionJobsCount)
throws ViewCreationFailedException, InvalidConfigurationException, InterruptedException {
logger.atInfo().log("Starting analysis");
pollInterruptedStatus();
skyframeBuildView.resetProgressReceiver();
ImmutableMap.Builder<Label, Target> labelToTargetsMapBuilder =
ImmutableMap.builderWithExpectedSize(loadingResult.getTargetLabels().size());
loadingResult
.getTargets(eventHandler, skyframeExecutor.getPackageManager())
.forEach(target -> labelToTargetsMapBuilder.put(target.getLabel(), target));
ImmutableMap<Label, Target> labelToTargetMap = labelToTargetsMapBuilder.buildOrThrow();
eventBus.post(new AnalysisPhaseStartedEvent(labelToTargetMap.values()));
// Prepare the analysis phase
BuildConfigurationCollection configurations;
TopLevelTargetsAndConfigsResult topLevelTargetsWithConfigsResult;
if (viewOptions.skyframePrepareAnalysis) {
PrepareAnalysisPhaseValue prepareAnalysisPhaseValue;
try (SilentCloseable c = Profiler.instance().profile("Prepare analysis phase")) {
prepareAnalysisPhaseValue =
skyframeExecutor.prepareAnalysisPhase(
eventHandler, targetOptions, multiCpu, loadingResult.getTargetLabels());
// Determine the configurations
configurations =
prepareAnalysisPhaseValue.getConfigurations(eventHandler, skyframeExecutor);
topLevelTargetsWithConfigsResult =
prepareAnalysisPhaseValue.getTopLevelCts(eventHandler, skyframeExecutor);
}
} else {
// Configuration creation.
// TODO(gregce): Consider dropping this phase and passing on-the-fly target / host configs as
// needed. This requires cleaning up the invalidation in SkyframeBuildView.setConfigurations.
try (SilentCloseable c = Profiler.instance().profile("createConfigurations")) {
configurations =
skyframeExecutor.createConfigurations(eventHandler, targetOptions, multiCpu, keepGoing);
}
try (SilentCloseable c = Profiler.instance().profile("AnalysisUtils.getTargetsWithConfigs")) {
topLevelTargetsWithConfigsResult =
AnalysisUtils.getTargetsWithConfigs(
configurations,
labelToTargetMap.values(),
eventHandler,
ruleClassProvider,
skyframeExecutor);
}
}
skyframeBuildView.setConfigurations(
eventHandler, configurations, viewOptions.maxConfigChangesToShow);
if (configurations.getTargetConfigurations().size() == 1) {
eventBus.post(
new MakeEnvironmentEvent(
configurations.getTargetConfigurations().get(0).getMakeEnvironment()));
}
for (BuildConfigurationValue targetConfig : configurations.getTargetConfigurations()) {
eventBus.post(targetConfig.toBuildEvent());
}
Collection<TargetAndConfiguration> topLevelTargetsWithConfigs =
topLevelTargetsWithConfigsResult.getTargetsAndConfigs();
// Report the generated association of targets to configurations
Multimap<Label, BuildConfigurationValue> byLabel = ArrayListMultimap.create();
for (TargetAndConfiguration pair : topLevelTargetsWithConfigs) {
byLabel.put(pair.getLabel(), pair.getConfiguration());
}
for (Target target : labelToTargetMap.values()) {
eventBus.post(new TargetConfiguredEvent(target, byLabel.get(target.getLabel())));
}
List<ConfiguredTargetKey> topLevelCtKeys =
topLevelTargetsWithConfigs.stream()
.map(BuildView::getConfiguredTargetKey)
.collect(Collectors.toList());
ImmutableList.Builder<AspectClass> aspectClassesBuilder = ImmutableList.builder();
for (String aspect : aspects) {
// Syntax: label%aspect
int delimiterPosition = aspect.indexOf('%');
if (delimiterPosition >= 0) {
// TODO(jfield): For consistency with Starlark loads, the aspect should be specified
// as an absolute label.
// We convert it for compatibility reasons (this will be removed in the future).
String bzlFileLoadLikeString = aspect.substring(0, delimiterPosition);
if (!bzlFileLoadLikeString.startsWith("//") && !bzlFileLoadLikeString.startsWith("@")) {
// "Legacy" behavior of '--aspects' parameter.
if (bzlFileLoadLikeString.startsWith("/")) {
bzlFileLoadLikeString = bzlFileLoadLikeString.substring(1);
}
int lastSlashPosition = bzlFileLoadLikeString.lastIndexOf('/');
if (lastSlashPosition >= 0) {
bzlFileLoadLikeString =
"//"
+ bzlFileLoadLikeString.substring(0, lastSlashPosition)
+ ":"
+ bzlFileLoadLikeString.substring(lastSlashPosition + 1);
} else {
bzlFileLoadLikeString = "//:" + bzlFileLoadLikeString;
}
if (!bzlFileLoadLikeString.endsWith(".bzl")) {
bzlFileLoadLikeString = bzlFileLoadLikeString + ".bzl";
}
}
Label starlarkFileLabel;
try {
starlarkFileLabel =
Label.parseAbsolute(
bzlFileLoadLikeString, /* repositoryMapping= */ ImmutableMap.of());
} catch (LabelSyntaxException e) {
String errorMessage = String.format("Invalid aspect '%s': %s", aspect, e.getMessage());
throw new ViewCreationFailedException(
errorMessage,
createFailureDetail(errorMessage, Analysis.Code.ASPECT_LABEL_SYNTAX_ERROR),
e);
}
String starlarkFunctionName = aspect.substring(delimiterPosition + 1);
aspectClassesBuilder.add(new StarlarkAspectClass(starlarkFileLabel, starlarkFunctionName));
} else {
final NativeAspectClass aspectFactoryClass =
ruleClassProvider.getNativeAspectClassMap().get(aspect);
if (aspectFactoryClass != null) {
aspectClassesBuilder.add(aspectFactoryClass);
} else {
String errorMessage = "Aspect '" + aspect + "' is unknown";
throw new ViewCreationFailedException(
errorMessage, createFailureDetail(errorMessage, Analysis.Code.ASPECT_NOT_FOUND));
}
}
}
Multimap<Pair<Label, String>, BuildConfigurationValue> aspectConfigurations =
ArrayListMultimap.create();
ImmutableList<AspectClass> aspectClasses = aspectClassesBuilder.build();
ImmutableList.Builder<TopLevelAspectsKey> aspectsKeys = ImmutableList.builder();
for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) {
BuildConfigurationValue configuration = targetSpec.getConfiguration();
for (AspectClass aspectClass : aspectClasses) {
aspectConfigurations.put(
Pair.of(targetSpec.getLabel(), aspectClass.getName()), configuration);
}
// For invoking top-level aspects, use the top-level configuration for both the
// aspect and the base target while the top-level configuration is untrimmed.
if (!aspectClasses.isEmpty()) {
aspectsKeys.add(
AspectKeyCreator.createTopLevelAspectsKey(
aspectClasses, targetSpec.getLabel(), configuration, aspectsParameters));
}
}
for (Pair<Label, String> target : aspectConfigurations.keys()) {
eventBus.post(
new AspectConfiguredEvent(
target.getFirst(), target.getSecond(), aspectConfigurations.get(target)));
}
getArtifactFactory().noteAnalysisStarting();
SkyframeAnalysisResult skyframeAnalysisResult;
try {
Supplier<Map<BuildConfigurationKey, BuildConfigurationValue>>
memoizedConfigurationLookupSupplier =
Suppliers.memoize(
() -> {
Map<BuildConfigurationKey, BuildConfigurationValue> result = new HashMap<>();
for (TargetAndConfiguration node : topLevelTargetsWithConfigs) {
if (node.getConfiguration() != null) {
result.put(node.getConfiguration().getKey(), node.getConfiguration());
}
}
return result;
});
if (!includeExecutionPhase) {
skyframeAnalysisResult =
skyframeBuildView.configureTargets(
eventHandler,
topLevelCtKeys,
aspectsKeys.build(),
memoizedConfigurationLookupSupplier,
topLevelOptions,
eventBus,
keepGoing,
loadingPhaseThreads,
viewOptions.strictConflictChecks,
checkForActionConflicts,
viewOptions.cpuHeavySkyKeysThreadPoolSize);
setArtifactRoots(skyframeAnalysisResult.getPackageRoots());
} else {
skyframeAnalysisResult =
skyframeBuildView.analyzeAndExecuteTargets(
eventHandler,
topLevelCtKeys,
aspectsKeys.build(),
memoizedConfigurationLookupSupplier,
topLevelOptions,
eventBus,
keepGoing,
viewOptions.strictConflictChecks,
checkForActionConflicts,
loadingPhaseThreads,
viewOptions.cpuHeavySkyKeysThreadPoolSize,
mergedPhasesExecutionJobsCount);
}
} finally {
skyframeBuildView.clearInvalidatedActionLookupKeys();
}
int numTargetsToAnalyze = topLevelTargetsWithConfigs.size();
int numSuccessful = skyframeAnalysisResult.getConfiguredTargets().size();
if (0 < numSuccessful && numSuccessful < numTargetsToAnalyze) {
String msg =
String.format(
"Analysis succeeded for only %d of %d top-level targets",
numSuccessful, numTargetsToAnalyze);
eventHandler.handle(Event.info(msg));
logger.atInfo().log("%s", msg);
}
AnalysisResult result;
if (includeExecutionPhase) {
// TODO(b/199053098): Also consider targets with errors like below.
result =
createResult(
eventHandler,
eventBus,
loadingResult,
configurations,
topLevelOptions,
viewOptions,
skyframeAnalysisResult,
/*targetsToSkip=*/ ImmutableSet.of(),
/*labelToTargetMap=*/ labelToTargetMap,
topLevelTargetsWithConfigsResult,
/*includeExecutionPhase=*/ true);
} else {
ImmutableSet<ConfiguredTarget> targetsToSkip = ImmutableSet.of();
if (reportIncompatibleTargets) {
TopLevelConstraintSemantics topLevelConstraintSemantics =
new TopLevelConstraintSemantics(
(RuleContextConstraintSemantics) ruleClassProvider.getConstraintSemantics(),
skyframeExecutor.getPackageManager(),
input -> skyframeExecutor.getConfiguration(eventHandler, input),
eventHandler);
PlatformRestrictionsResult platformRestrictions =
topLevelConstraintSemantics.checkPlatformRestrictions(
skyframeAnalysisResult.getConfiguredTargets(), explicitTargetPatterns, keepGoing);
if (!platformRestrictions.targetsWithErrors().isEmpty()) {
// If there are any errored targets (e.g. incompatible targets that are explicitly
// specified on the command line), remove them from the list of targets to be built.
skyframeAnalysisResult =
skyframeAnalysisResult.withAdditionalErroredTargets(
platformRestrictions.targetsWithErrors());
}
targetsToSkip =
Sets.union(
topLevelConstraintSemantics.checkTargetEnvironmentRestrictions(
skyframeAnalysisResult.getConfiguredTargets()),
platformRestrictions.targetsToSkip())
.immutableCopy();
}
result =
createResult(
eventHandler,
eventBus,
loadingResult,
configurations,
topLevelOptions,
viewOptions,
skyframeAnalysisResult,
targetsToSkip,
labelToTargetMap,
topLevelTargetsWithConfigsResult,
/*includeExecutionPhase=*/ false);
}
logger.atInfo().log("Finished analysis");
return result;
}