blob: 9fd9c348cf16709ecd96120a9d94400d9338cdc6 [file] [log] [blame]
tomlu880508c2018-08-03 11:21:29 -07001// Copyright 2018 The Bazel Authors. All rights reserved.
2//
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.
14package com.google.devtools.build.lib.skyframe;
15
16import com.google.common.base.Preconditions;
ajurkowski1e9ed642020-10-16 11:14:18 -070017import com.google.common.collect.ImmutableCollection;
tomlu880508c2018-08-03 11:21:29 -070018import com.google.common.collect.ImmutableList;
19import com.google.common.collect.ImmutableSet;
kushc03c8752018-09-13 12:13:20 -070020import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
mschaller4c7ca322018-11-20 13:22:05 -080021import com.google.devtools.build.lib.actions.ActionInputMapSink;
janakrefb3f152019-06-05 17:42:34 -070022import com.google.devtools.build.lib.actions.ActionLookupData;
jhorvitz3daedc32020-07-22 18:33:55 -070023import com.google.devtools.build.lib.actions.ActionLookupKey;
kushc03c8752018-09-13 12:13:20 -070024import com.google.devtools.build.lib.actions.ActionLookupValue;
tomlu880508c2018-08-03 11:21:29 -070025import com.google.devtools.build.lib.actions.Artifact;
ajurkowski280bbe22020-08-19 11:26:20 -070026import com.google.devtools.build.lib.actions.Artifact.ArchivedTreeArtifact;
Googler72d648a2020-05-21 11:56:40 -070027import com.google.devtools.build.lib.actions.Artifact.DerivedArtifact;
28import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
tomlu880508c2018-08-03 11:21:29 -070029import com.google.devtools.build.lib.actions.FileArtifactValue;
felly8dece492018-08-14 17:53:30 -070030import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
kushc03c8752018-09-13 12:13:20 -070031import com.google.devtools.build.lib.analysis.actions.SymlinkAction;
tomlu880508c2018-08-03 11:21:29 -070032import com.google.devtools.build.lib.util.Pair;
felly8dece492018-08-14 17:53:30 -070033import com.google.devtools.build.skyframe.SkyFunction.Environment;
tomlu880508c2018-08-03 11:21:29 -070034import com.google.devtools.build.skyframe.SkyValue;
tomlu880508c2018-08-03 11:21:29 -070035import java.util.Map;
36
Googleraed41602020-06-02 12:22:53 -070037/** Static utilities for working with action inputs. */
38final class ActionInputMapHelper {
tomlu880508c2018-08-03 11:21:29 -070039
Googleraed41602020-06-02 12:22:53 -070040 private ActionInputMapHelper() {}
41
42 /**
43 * Adds a value obtained by an Artifact skyvalue lookup to the action input map. May do Skyframe
44 * lookups.
45 */
tomlu880508c2018-08-03 11:21:29 -070046 static void addToMap(
mschaller4c7ca322018-11-20 13:22:05 -080047 ActionInputMapSink inputMap,
ajurkowski1e9ed642020-10-16 11:14:18 -070048 Map<Artifact, ImmutableCollection<Artifact>> expandedArtifacts,
ajurkowski280bbe22020-08-19 11:26:20 -070049 Map<SpecialArtifact, ArchivedTreeArtifact> archivedTreeArtifacts,
Googler5284e6c2019-10-30 07:43:54 -070050 Map<Artifact, ImmutableList<FilesetOutputSymlink>> filesetsInsideRunfiles,
51 Map<Artifact, ImmutableList<FilesetOutputSymlink>> topLevelFilesets,
tomlu880508c2018-08-03 11:21:29 -070052 Artifact key,
felly8dece492018-08-14 17:53:30 -070053 SkyValue value,
mschaller4c7ca322018-11-20 13:22:05 -080054 Environment env)
55 throws InterruptedException {
tomlu880508c2018-08-03 11:21:29 -070056 if (value instanceof AggregatingArtifactValue) {
57 AggregatingArtifactValue aggregatingValue = (AggregatingArtifactValue) value;
58 for (Pair<Artifact, FileArtifactValue> entry : aggregatingValue.getFileArtifacts()) {
felly8dece492018-08-14 17:53:30 -070059 Artifact artifact = entry.first;
mschaller4c7ca322018-11-20 13:22:05 -080060 inputMap.put(artifact, entry.second, /*depOwner=*/ key);
felly8dece492018-08-14 17:53:30 -070061 if (artifact.isFileset()) {
janakr658d47f2019-05-29 11:11:30 -070062 ImmutableList<FilesetOutputSymlink> expandedFileset =
Googler72d648a2020-05-21 11:56:40 -070063 getFilesets(env, (SpecialArtifact) artifact);
felly8dece492018-08-14 17:53:30 -070064 if (expandedFileset != null) {
Googler5284e6c2019-10-30 07:43:54 -070065 filesetsInsideRunfiles.put(artifact, expandedFileset);
felly8dece492018-08-14 17:53:30 -070066 }
67 }
tomlu880508c2018-08-03 11:21:29 -070068 }
69 for (Pair<Artifact, TreeArtifactValue> entry : aggregatingValue.getTreeArtifacts()) {
70 expandTreeArtifactAndPopulateArtifactData(
71 entry.getFirst(),
72 Preconditions.checkNotNull(entry.getSecond()),
73 expandedArtifacts,
ajurkowski280bbe22020-08-19 11:26:20 -070074 archivedTreeArtifacts,
mschaller4c7ca322018-11-20 13:22:05 -080075 inputMap,
76 /*depOwner=*/ key);
tomlu880508c2018-08-03 11:21:29 -070077 }
Googler206d6e42020-06-18 12:39:17 -070078 // We have to cache the "digest" of the aggregating value itself, because the action cache
79 // checker may want it.
80 inputMap.put(key, aggregatingValue.getMetadata(), /*depOwner=*/ key);
tomlu880508c2018-08-03 11:21:29 -070081 // While not obvious at all this code exists to ensure that we don't expand the
82 // .runfiles/MANIFEST file into the inputs. The reason for that being that the MANIFEST
83 // file contains absolute paths that don't work with remote execution.
84 // Instead, the way the SpawnInputExpander expands runfiles is via the Runfiles class
85 // which contains all artifacts in the runfiles tree minus the MANIFEST file.
86 // TODO(buchgr): Clean this up and get rid of the RunfilesArtifactValue type.
87 if (!(value instanceof RunfilesArtifactValue)) {
88 ImmutableList.Builder<Artifact> expansionBuilder = ImmutableList.builder();
89 for (Pair<Artifact, FileArtifactValue> pair : aggregatingValue.getFileArtifacts()) {
90 expansionBuilder.add(Preconditions.checkNotNull(pair.getFirst()));
91 }
92 expandedArtifacts.put(key, expansionBuilder.build());
93 }
94 } else if (value instanceof TreeArtifactValue) {
95 expandTreeArtifactAndPopulateArtifactData(
ajurkowski280bbe22020-08-19 11:26:20 -070096 key,
97 (TreeArtifactValue) value,
98 expandedArtifacts,
99 archivedTreeArtifacts,
100 inputMap,
101 /*depOwner=*/ key);
janakr8541f6d2019-06-11 14:40:21 -0700102 } else if (value instanceof ActionExecutionValue) {
Googleraed41602020-06-02 12:22:53 -0700103 inputMap.put(key, ((ActionExecutionValue) value).getExistingFileArtifactValue(key), key);
Googler5284e6c2019-10-30 07:43:54 -0700104 if (key.isFileset()) {
Googler72d648a2020-05-21 11:56:40 -0700105 topLevelFilesets.put(key, getFilesets(env, (SpecialArtifact) key));
Googler5284e6c2019-10-30 07:43:54 -0700106 }
tomlu880508c2018-08-03 11:21:29 -0700107 } else {
Googler807d4342020-06-29 11:58:07 -0700108 Preconditions.checkArgument(value instanceof FileArtifactValue, "Unexpected value %s", value);
mschaller4c7ca322018-11-20 13:22:05 -0800109 inputMap.put(key, (FileArtifactValue) value, /*depOwner=*/ key);
tomlu880508c2018-08-03 11:21:29 -0700110 }
111 }
112
janakr658d47f2019-05-29 11:11:30 -0700113 static ImmutableList<FilesetOutputSymlink> getFilesets(
Googler72d648a2020-05-21 11:56:40 -0700114 Environment env, SpecialArtifact actionInput) throws InterruptedException {
felly8dece492018-08-14 17:53:30 -0700115 Preconditions.checkState(actionInput.isFileset(), actionInput);
janakrefb3f152019-06-05 17:42:34 -0700116 ActionLookupData generatingActionKey = actionInput.getGeneratingActionKey();
117 ActionLookupKey filesetActionLookupKey = generatingActionKey.getActionLookupKey();
kushc03c8752018-09-13 12:13:20 -0700118
119 ActionLookupValue filesetActionLookupValue =
120 (ActionLookupValue) env.getValue(filesetActionLookupKey);
121
122 ActionAnalysisMetadata generatingAction =
janakrefb3f152019-06-05 17:42:34 -0700123 filesetActionLookupValue.getAction(generatingActionKey.getActionIndex());
124 ActionLookupData filesetActionKey;
kushc03c8752018-09-13 12:13:20 -0700125
126 if (generatingAction instanceof SymlinkAction) {
Googler72d648a2020-05-21 11:56:40 -0700127 DerivedArtifact outputManifest =
128 (DerivedArtifact) generatingAction.getInputs().getSingleton();
janakrefb3f152019-06-05 17:42:34 -0700129 ActionLookupData manifestGeneratingKey = outputManifest.getGeneratingActionKey();
130 Preconditions.checkState(
131 manifestGeneratingKey.getActionLookupKey().equals(filesetActionLookupKey),
132 "Mismatched actions and artifacts: %s %s %s %s",
133 actionInput,
134 outputManifest,
135 filesetActionLookupKey,
136 manifestGeneratingKey);
kushc03c8752018-09-13 12:13:20 -0700137 ActionAnalysisMetadata symlinkTreeAction =
janakrefb3f152019-06-05 17:42:34 -0700138 filesetActionLookupValue.getAction(manifestGeneratingKey.getActionIndex());
Googler72d648a2020-05-21 11:56:40 -0700139 DerivedArtifact inputManifest =
140 (DerivedArtifact) symlinkTreeAction.getInputs().getSingleton();
janakrefb3f152019-06-05 17:42:34 -0700141 ActionLookupData inputManifestGeneratingKey = inputManifest.getGeneratingActionKey();
142 Preconditions.checkState(
143 inputManifestGeneratingKey.getActionLookupKey().equals(filesetActionLookupKey),
144 "Mismatched actions and artifacts: %s %s %s %s",
145 actionInput,
146 inputManifest,
147 filesetActionLookupKey,
148 inputManifestGeneratingKey);
149 filesetActionKey = inputManifestGeneratingKey;
kushc03c8752018-09-13 12:13:20 -0700150 } else {
janakrefb3f152019-06-05 17:42:34 -0700151 filesetActionKey = generatingActionKey;
kushc03c8752018-09-13 12:13:20 -0700152 }
153
felly8dece492018-08-14 17:53:30 -0700154 ActionExecutionValue filesetValue = (ActionExecutionValue) env.getValue(filesetActionKey);
155 if (filesetValue == null) {
156 // At this point skyframe does not guarantee that the filesetValue will be ready, since
157 // the current action does not directly depend on the outputs of the
158 // SkyframeFilesetManifestAction whose ActionExecutionValue (filesetValue) is needed here.
felly8dece492018-08-14 17:53:30 -0700159 return null;
160 }
161 return filesetValue.getOutputSymlinks();
162 }
163
tomlu880508c2018-08-03 11:21:29 -0700164 private static void expandTreeArtifactAndPopulateArtifactData(
165 Artifact treeArtifact,
166 TreeArtifactValue value,
ajurkowski1e9ed642020-10-16 11:14:18 -0700167 Map<Artifact, ImmutableCollection<Artifact>> expandedArtifacts,
ajurkowski280bbe22020-08-19 11:26:20 -0700168 Map<SpecialArtifact, ArchivedTreeArtifact> archivedTreeArtifacts,
mschaller4c7ca322018-11-20 13:22:05 -0800169 ActionInputMapSink inputMap,
170 Artifact depOwner) {
Googler61a9f572020-06-02 10:28:24 -0700171 if (TreeArtifactValue.OMITTED_TREE_MARKER.equals(value)) {
172 inputMap.put(treeArtifact, FileArtifactValue.OMITTED_FILE_MARKER, depOwner);
173 return;
174 }
tomlu880508c2018-08-03 11:21:29 -0700175 ImmutableSet.Builder<Artifact> children = ImmutableSet.builder();
176 for (Map.Entry<Artifact.TreeFileArtifact, FileArtifactValue> child :
177 value.getChildValues().entrySet()) {
178 children.add(child.getKey());
mschaller4c7ca322018-11-20 13:22:05 -0800179 inputMap.put(child.getKey(), child.getValue(), depOwner);
tomlu880508c2018-08-03 11:21:29 -0700180 }
181 expandedArtifacts.put(treeArtifact, children.build());
182 // Again, we cache the "digest" of the value for cache checking.
Googler206d6e42020-06-18 12:39:17 -0700183 inputMap.put(treeArtifact, value.getMetadata(), depOwner);
ajurkowski280bbe22020-08-19 11:26:20 -0700184
185 value
186 .getArchivedRepresentation()
187 .ifPresent(
188 archivedRepresentation -> {
189 inputMap.put(
190 archivedRepresentation.archivedTreeFileArtifact(),
191 archivedRepresentation.archivedFileValue(),
192 depOwner);
193 archivedTreeArtifacts.put(
194 (SpecialArtifact) treeArtifact,
195 archivedRepresentation.archivedTreeFileArtifact());
196 });
tomlu880508c2018-08-03 11:21:29 -0700197 }
198}