| // Copyright 2020 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| package com.google.devtools.build.lib.skyframe; |
| |
| import com.google.devtools.build.lib.actions.CompletionContext; |
| import com.google.devtools.build.lib.actions.CompletionContext.PathResolverFactory; |
| import com.google.devtools.build.lib.actions.MissingInputFileException; |
| import com.google.devtools.build.lib.analysis.AspectCompleteEvent; |
| import com.google.devtools.build.lib.analysis.AspectValue; |
| import com.google.devtools.build.lib.analysis.TopLevelArtifactHelper.ArtifactsInOutputGroup; |
| import com.google.devtools.build.lib.analysis.TopLevelArtifactHelper.ArtifactsToBuild; |
| import com.google.devtools.build.lib.buildeventstream.BuildEventIdUtil; |
| import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId; |
| import com.google.devtools.build.lib.causes.Cause; |
| import com.google.devtools.build.lib.causes.LabelCause; |
| import com.google.devtools.build.lib.collect.nestedset.NestedSet; |
| import com.google.devtools.build.lib.events.Event; |
| import com.google.devtools.build.lib.events.ExtendedEventHandler; |
| import com.google.devtools.build.lib.skyframe.AspectCompletionValue.AspectCompletionKey; |
| import com.google.devtools.build.lib.skyframe.AspectValueKey.AspectKey; |
| import com.google.devtools.build.lib.skyframe.CompletionFunction.Completor; |
| import com.google.devtools.build.skyframe.SkyFunction; |
| import com.google.devtools.build.skyframe.SkyFunction.Environment; |
| import javax.annotation.Nullable; |
| |
| /** Manages completing builds for aspects. */ |
| class AspectCompletor |
| implements Completor<AspectValue, AspectCompletionValue, AspectCompletionKey> { |
| |
| static SkyFunction aspectCompletionFunction( |
| PathResolverFactory pathResolverFactory, SkyframeActionExecutor skyframeActionExecutor) { |
| return new CompletionFunction<>( |
| pathResolverFactory, new AspectCompletor(), skyframeActionExecutor); |
| } |
| |
| @Override |
| public Event getRootCauseError( |
| AspectValue value, AspectCompletionKey key, LabelCause rootCause, Environment env) { |
| AspectKey aspectKey = key.actionLookupKey(); |
| return Event.error( |
| value.getLocation(), |
| String.format( |
| "%s, aspect %s: %s", |
| aspectKey.getLabel(), aspectKey.getAspectClass().getName(), rootCause.getMessage())); |
| } |
| |
| @Override |
| public MissingInputFileException getMissingFilesException( |
| AspectValue value, AspectCompletionKey key, int missingCount, Environment env) { |
| AspectKey aspectKey = key.actionLookupKey(); |
| return new MissingInputFileException( |
| aspectKey.getLabel() |
| + ", aspect " |
| + aspectKey.getAspectClass().getName() |
| + missingCount |
| + " input file(s) do not exist", |
| value.getLocation()); |
| } |
| |
| @Override |
| public AspectCompletionValue getResult() { |
| return AspectCompletionValue.INSTANCE; |
| } |
| |
| @Override |
| public ExtendedEventHandler.Postable createFailed( |
| AspectValue value, |
| NestedSet<Cause> rootCauses, |
| NestedSet<ArtifactsInOutputGroup> outputs, |
| Environment env, |
| AspectCompletionKey key) |
| throws InterruptedException { |
| BuildEventId configurationEventId = |
| getConfigurationEventIdFromAspectKey(key.actionLookupKey(), env); |
| if (configurationEventId == null) { |
| return null; |
| } |
| return AspectCompleteEvent.createFailed(value, rootCauses, configurationEventId, outputs); |
| } |
| |
| @Nullable |
| private BuildEventId getConfigurationEventIdFromAspectKey(AspectKey aspectKey, Environment env) |
| throws InterruptedException { |
| if (aspectKey.getBaseConfiguredTargetKey().getConfigurationKey() == null) { |
| return BuildEventIdUtil.nullConfigurationId(); |
| } else { |
| BuildConfigurationValue buildConfigurationValue = |
| (BuildConfigurationValue) |
| env.getValue(aspectKey.getBaseConfiguredTargetKey().getConfigurationKey()); |
| if (buildConfigurationValue == null) { |
| return null; |
| } |
| return buildConfigurationValue.getConfiguration().getEventId(); |
| } |
| } |
| |
| @Override |
| public ExtendedEventHandler.Postable createSucceeded( |
| AspectCompletionKey skyKey, |
| AspectValue value, |
| CompletionContext completionContext, |
| ArtifactsToBuild artifactsToBuild, |
| Environment env) |
| throws InterruptedException { |
| AspectKey aspectKey = skyKey.actionLookupKey(); |
| BuildEventId configurationEventId = getConfigurationEventIdFromAspectKey(aspectKey, env); |
| if (configurationEventId == null) { |
| return null; |
| } |
| |
| return AspectCompleteEvent.createSuccessful( |
| value, |
| completionContext, |
| artifactsToBuild.getAllArtifactsByOutputGroup(), |
| configurationEventId); |
| } |
| } |