blob: f7a9e0734a44e8db0f3001489b660dbb9d6ed7e3 [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.actions;
16
17import com.google.common.annotations.VisibleForTesting;
18import com.google.common.base.Function;
19import com.google.common.base.Functions;
tomlua155b532017-11-08 20:12:47 +010020import com.google.common.base.Preconditions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010021import com.google.common.collect.Collections2;
Googlerece75722016-02-11 17:55:41 +000022import com.google.common.collect.ImmutableSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010023import com.google.common.collect.Iterables;
Michael Thvedt434e68e2016-02-09 00:57:46 +000024import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
cpeyserac09f0a2018-02-05 09:33:15 -080025import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
Rumou Duana77f32c2016-04-13 21:59:21 +000026import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
Michael Thvedte3b1cb72016-02-08 23:32:27 +000027import com.google.devtools.build.lib.vfs.PathFragment;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010028import java.util.ArrayList;
29import java.util.Collection;
30import java.util.List;
Googlerece75722016-02-11 17:55:41 +000031import java.util.Set;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010032
33/**
34 * Helper utility to create ActionInput instances.
35 */
36public final class ActionInputHelper {
37 private ActionInputHelper() {
38 }
39
40 @VisibleForTesting
Michael Thvedt434e68e2016-02-09 00:57:46 +000041 public static ArtifactExpander actionGraphArtifactExpander(
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010042 final ActionGraph actionGraph) {
Michael Thvedt434e68e2016-02-09 00:57:46 +000043 return new ArtifactExpander() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010044 @Override
Rumou Duana77f32c2016-04-13 21:59:21 +000045 public void expand(Artifact mm, Collection<? super Artifact> output) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010046 // Skyframe is stricter in that it checks that "mm" is a input of the action, because
47 // it cannot expand arbitrary middlemen without access to a global action graph.
48 // We could check this constraint here too, but it seems unnecessary. This code is
49 // going away anyway.
50 Preconditions.checkArgument(mm.isMiddlemanArtifact(),
51 "%s is not a middleman artifact", mm);
Rumou Duan33bab462016-04-25 17:55:12 +000052 ActionAnalysisMetadata middlemanAction = actionGraph.getGeneratingAction(mm);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010053 Preconditions.checkState(middlemanAction != null, mm);
54 // TODO(bazel-team): Consider expanding recursively or throwing an exception here.
55 // Most likely, this code will cause silent errors if we ever have a middleman that
56 // contains a middleman.
57 if (middlemanAction.getActionType() == Action.MiddlemanType.AGGREGATING_MIDDLEMAN) {
58 Artifact.addNonMiddlemanArtifacts(middlemanAction.getInputs(), output,
59 Functions.<Artifact>identity());
60 }
61
62 }
63 };
64 }
65
66 /**
67 * Most ActionInputs are created and never used again. On the off chance that one is, however, we
68 * implement equality via path comparison. Since file caches are keyed by ActionInput, equality
69 * checking does come up.
70 */
71 private static class BasicActionInput implements ActionInput {
72 private final String path;
Ulf Adams14db5072017-03-20 16:00:51 +000073
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010074 public BasicActionInput(String path) {
75 this.path = Preconditions.checkNotNull(path);
ulfjack2918e782017-12-19 06:59:55 -080076 Preconditions.checkArgument(!path.isEmpty());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010077 }
78
79 @Override
80 public String getExecPathString() {
81 return path;
82 }
83
84 @Override
Ulf Adams14db5072017-03-20 16:00:51 +000085 public PathFragment getExecPath() {
nharmatab4060b62017-04-04 17:11:39 +000086 return PathFragment.create(path);
Ulf Adams14db5072017-03-20 16:00:51 +000087 }
88
89 @Override
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010090 public int hashCode() {
91 return path.hashCode();
92 }
93
94 @Override
95 public boolean equals(Object other) {
96 if (this == other) {
97 return true;
98 }
99 if (other == null) {
100 return false;
101 }
102 if (!this.getClass().equals(other.getClass())) {
103 return false;
104 }
105 return this.path.equals(((BasicActionInput) other).path);
106 }
107
108 @Override
109 public String toString() {
110 return "BasicActionInput: " + path;
111 }
112 }
113
114 /**
115 * Creates an ActionInput with just the given relative path and no digest.
116 *
117 * @param path the relative path of the input.
118 * @return a ActionInput.
119 */
120 public static ActionInput fromPath(String path) {
121 return new BasicActionInput(path);
122 }
123
Ulf Adams11e52b42017-01-11 11:00:24 +0000124 /**
125 * Creates an ActionInput with just the given relative path and no digest.
126 *
127 * @param path the relative path of the input.
128 * @return a ActionInput.
129 */
130 public static ActionInput fromPath(PathFragment path) {
131 return fromPath(path.getPathString());
132 }
133
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100134 /**
135 * Creates a sequence of {@link ActionInput}s from a sequence of string paths.
136 */
137 public static Collection<ActionInput> fromPaths(Collection<String> paths) {
laurentlb3d2a68c2017-06-30 00:32:04 +0200138 return Collections2.transform(paths, ActionInputHelper::fromPath);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100139 }
140
141 /**
cpeyserac09f0a2018-02-05 09:33:15 -0800142 * Instantiates a concrete TreeFileArtifact with the given parent Artifact and path relative to
143 * that Artifact.
Michael Thvedte3b1cb72016-02-08 23:32:27 +0000144 */
Rumou Duana77f32c2016-04-13 21:59:21 +0000145 public static TreeFileArtifact treeFileArtifact(
cpeyserac09f0a2018-02-05 09:33:15 -0800146 SpecialArtifact parent, PathFragment relativePath) {
Michael Thvedte3b1cb72016-02-08 23:32:27 +0000147 Preconditions.checkState(parent.isTreeArtifact(),
148 "Given parent %s must be a TreeArtifact", parent);
Rumou Duana77f32c2016-04-13 21:59:21 +0000149 return new TreeFileArtifact(parent, relativePath);
150 }
151
152 public static TreeFileArtifact treeFileArtifact(
cpeyserac09f0a2018-02-05 09:33:15 -0800153 SpecialArtifact parent, PathFragment relativePath, ArtifactOwner artifactOwner) {
Rumou Duana77f32c2016-04-13 21:59:21 +0000154 Preconditions.checkState(parent.isTreeArtifact(),
155 "Given parent %s must be a TreeArtifact", parent);
156 return new TreeFileArtifact(
157 parent,
158 relativePath,
159 artifactOwner);
Michael Thvedte3b1cb72016-02-08 23:32:27 +0000160 }
161
162 /**
cpeyserac09f0a2018-02-05 09:33:15 -0800163 * Instantiates a concrete TreeFileArtifact with the given parent Artifact and path relative to
164 * that Artifact.
Michael Thvedte3b1cb72016-02-08 23:32:27 +0000165 */
cpeyserac09f0a2018-02-05 09:33:15 -0800166 public static TreeFileArtifact treeFileArtifact(SpecialArtifact parent, String relativePath) {
nharmatab4060b62017-04-04 17:11:39 +0000167 return treeFileArtifact(parent, PathFragment.create(relativePath));
Michael Thvedte3b1cb72016-02-08 23:32:27 +0000168 }
169
Rumou Duana77f32c2016-04-13 21:59:21 +0000170 /** Returns an Iterable of TreeFileArtifacts with the given parent and parent relative paths. */
171 public static Iterable<TreeFileArtifact> asTreeFileArtifacts(
cpeyserac09f0a2018-02-05 09:33:15 -0800172 final SpecialArtifact parent, Iterable<? extends PathFragment> parentRelativePaths) {
Michael Thvedte3b1cb72016-02-08 23:32:27 +0000173 Preconditions.checkState(parent.isTreeArtifact(),
174 "Given parent %s must be a TreeArtifact", parent);
laurentlb3d2a68c2017-06-30 00:32:04 +0200175 return Iterables.transform(
176 parentRelativePaths, pathFragment -> treeFileArtifact(parent, pathFragment));
Michael Thvedte3b1cb72016-02-08 23:32:27 +0000177 }
178
Rumou Duana77f32c2016-04-13 21:59:21 +0000179 /** Returns a Set of TreeFileArtifacts with the given parent and parent-relative paths. */
180 public static Set<TreeFileArtifact> asTreeFileArtifacts(
cpeyserac09f0a2018-02-05 09:33:15 -0800181 final SpecialArtifact parent, Set<? extends PathFragment> parentRelativePaths) {
Googlerece75722016-02-11 17:55:41 +0000182 Preconditions.checkState(parent.isTreeArtifact(),
183 "Given parent %s must be a TreeArtifact", parent);
184
Rumou Duana77f32c2016-04-13 21:59:21 +0000185 ImmutableSet.Builder<TreeFileArtifact> builder = ImmutableSet.builder();
Googlerece75722016-02-11 17:55:41 +0000186 for (PathFragment path : parentRelativePaths) {
Rumou Duana77f32c2016-04-13 21:59:21 +0000187 builder.add(treeFileArtifact(parent, path));
Googlerece75722016-02-11 17:55:41 +0000188 }
189
190 return builder.build();
191 }
192
Michael Thvedte3b1cb72016-02-08 23:32:27 +0000193 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100194 * Expands middleman artifacts in a sequence of {@link ActionInput}s.
195 *
196 * <p>Non-middleman artifacts are returned untouched.
197 */
Michael Thvedt434e68e2016-02-09 00:57:46 +0000198 public static List<ActionInput> expandArtifacts(Iterable<? extends ActionInput> inputs,
199 ArtifactExpander artifactExpander) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100200
201 List<ActionInput> result = new ArrayList<>();
202 List<Artifact> containedArtifacts = new ArrayList<>();
203 for (ActionInput input : inputs) {
204 if (!(input instanceof Artifact)) {
205 result.add(input);
206 continue;
207 }
208 containedArtifacts.add((Artifact) input);
209 }
Michael Thvedt434e68e2016-02-09 00:57:46 +0000210 Artifact.addExpandedArtifacts(containedArtifacts, result, artifactExpander);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100211 return result;
212 }
213
Michael Thvedte3b1cb72016-02-08 23:32:27 +0000214 /** Formatter for execPath String output. Public because {@link Artifact} uses it directly. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100215 public static final Function<ActionInput, String> EXEC_PATH_STRING_FORMATTER =
laurentlb3d2a68c2017-06-30 00:32:04 +0200216 ActionInput::getExecPathString;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100217
218 public static Iterable<String> toExecPaths(Iterable<? extends ActionInput> artifacts) {
219 return Iterables.transform(artifacts, EXEC_PATH_STRING_FORMATTER);
220 }
221}