close
Skip to content

Commit 5ea2b14

Browse files
lberkihermione521
authored andcommitted
Clean up the semantics of input discovering actions a bit by making updateInputs() and inputsKnown() non-overridable and removing setInputs().
This comes at the cost of adding a flag to every action instance that's not used for non-input-discovering actions, but I think that's a deal. Simpler APIs are good, mmmmkay? Also fixed a few pre-existing issues in TestAction and ObjcCompileAction. -- PiperOrigin-RevId: 148749734 MOS_MIGRATED_REVID=148749734
1 parent 8afbd3c commit 5ea2b14

14 files changed

Lines changed: 82 additions & 214 deletions

File tree

‎src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java‎

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import java.util.Collection;
4646
import java.util.Map;
4747
import java.util.Map.Entry;
48+
import javax.annotation.concurrent.GuardedBy;
4849

4950
/**
5051
* Abstract implementation of Action which implements basic functionality: the inputs, outputs, and
@@ -94,8 +95,13 @@ public abstract class AbstractAction implements Action, SkylarkValue {
9495
*/
9596
private final Iterable<Artifact> tools;
9697

98+
@GuardedBy("this")
99+
private boolean inputsDiscovered = false; // Only used when discoversInputs() returns true
100+
97101
// The variable inputs is non-final only so that actions that discover their inputs can modify it.
102+
@GuardedBy("this")
98103
private Iterable<Artifact> inputs;
104+
99105
private final Iterable<String> clientEnvironmentVariables;
100106
private final RunfilesSupplier runfilesSupplier;
101107
private final ImmutableSet<Artifact> outputs;
@@ -164,15 +170,36 @@ public final ActionOwner getOwner() {
164170
}
165171

166172
@Override
167-
public boolean inputsKnown() {
168-
return true;
173+
public final synchronized boolean inputsDiscovered() {
174+
return discoversInputs() ? inputsDiscovered : true;
169175
}
170176

177+
/**
178+
* Should be overridden by actions that do input discovery.
179+
*
180+
* <p>The value returned by each instance should be constant over the lifetime of that instance.
181+
*
182+
* <p>If this returns true, {@link #discoverInputs(ActionExecutionContext)} must also be
183+
* implemented.
184+
*/
171185
@Override
172186
public boolean discoversInputs() {
173187
return false;
174188
}
175189

190+
/**
191+
* Run input discovery on the action.
192+
*
193+
* <p>Called by Blaze if {@link #discoversInputs()} returns true. It must return the set of
194+
* input artifacts that were not known at analysis time. May also call
195+
* {@link #updateInputs(Iterable<Artifact>)}; if it doesn't, the action itself must arrange for
196+
* the newly discovered artifacts to be available during action execution, probably by keeping
197+
* state in the action instance and using a custom action execution context and for
198+
* {@code #updateInputs()} to be called during the execution of the action.
199+
*
200+
* <p>Since keeping state within an action bad, don't do that unless there is a very good reason
201+
* to do so.
202+
*/
176203
@Override
177204
public Iterable<Artifact> discoverInputs(ActionExecutionContext actionExecutionContext)
178205
throws ActionExecutionException, InterruptedException {
@@ -192,10 +219,21 @@ public Iterable<Artifact> getAllowedDerivedInputs() {
192219
"Method must be overridden for actions that may have unknown inputs.");
193220
}
194221

222+
/**
223+
* Should be called when the inputs of the action become known, that is, either during
224+
* {@link #discoverInputs(ActionExecutionContext)} or during
225+
* {@link #execute(ActionExecutionContext)}.
226+
*
227+
* <p>When an action discovers inputs, it must have been called by the time {@code #execute()}
228+
* returns. It can be called both during {@code discoverInputs} and during {@code execute()}.
229+
*
230+
* <p>In addition to being called from action implementations, it will also be called by Bazel
231+
* itself when an action is loaded from the on-disk action cache.
232+
*/
195233
@Override
196-
public void updateInputs(Iterable<Artifact> inputs) {
197-
throw new IllegalStateException(
198-
"Method must be overridden for actions that may have unknown inputs.");
234+
public final synchronized void updateInputs(Iterable<Artifact> inputs) {
235+
this.inputs = CollectionUtils.makeImmutable(inputs);
236+
inputsDiscovered = true;
199237
}
200238

201239
@Override
@@ -204,12 +242,10 @@ public Iterable<Artifact> getTools() {
204242
}
205243

206244
/**
207-
* Should only be overridden by actions that need to optionally insert inputs. Actions that
208-
* discover their inputs should use {@link #setInputs} to set the new iterable of inputs when they
209-
* know it.
245+
* Should not be overridden (it's non-final only for tests)
210246
*/
211247
@Override
212-
public Iterable<Artifact> getInputs() {
248+
public synchronized Iterable<Artifact> getInputs() {
213249
return inputs;
214250
}
215251

@@ -223,15 +259,6 @@ public RunfilesSupplier getRunfilesSupplier() {
223259
return runfilesSupplier;
224260
}
225261

226-
/**
227-
* Set the inputs of the action. May only be used by an action that {@link #discoversInputs()}.
228-
* The iterable passed in is automatically made immutable.
229-
*/
230-
protected void setInputs(Iterable<Artifact> inputs) {
231-
Preconditions.checkState(discoversInputs(), this);
232-
this.inputs = CollectionUtils.makeImmutable(inputs);
233-
}
234-
235262
@Override
236263
public ImmutableSet<Artifact> getOutputs() {
237264
return outputs;
@@ -259,7 +286,7 @@ public Iterable<Artifact> getMandatoryInputs() {
259286
@Override
260287
public String toString() {
261288
return prettyPrint() + " (" + getMnemonic() + "[" + ImmutableList.copyOf(getInputs())
262-
+ (inputsKnown() ? " -> " : ", unknown inputs -> ")
289+
+ (inputsDiscovered() ? " -> " : ", unknown inputs -> ")
263290
+ getOutputs() + "]" + ")";
264291
}
265292

‎src/main/java/com/google/devtools/build/lib/actions/Action.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ Iterable<Artifact> discoverInputsStage2(SkyFunction.Environment env)
176176
/**
177177
* Informs the action that its inputs are {@code inputs}, and that its inputs are now known. Can
178178
* only be called for actions that discover inputs. After this method is called,
179-
* {@link ActionExecutionMetadata#inputsKnown} should return true.
179+
* {@link ActionExecutionMetadata#inputsDiscovered} should return true.
180180
*/
181181
void updateInputs(Iterable<Artifact> inputs);
182182

‎src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,8 @@ public Token getTokenIfNeedToExecute(
196196
}
197197
Iterable<Artifact> actionInputs = action.getInputs();
198198
// Resolve action inputs from cache, if necessary.
199-
boolean inputsKnown = action.inputsKnown();
200-
if (!inputsKnown && resolvedCacheArtifacts != null) {
199+
boolean inputsDiscovered = action.inputsDiscovered();
200+
if (!inputsDiscovered && resolvedCacheArtifacts != null) {
201201
// The action doesn't know its inputs, but the caller has a good idea of what they are.
202202
Preconditions.checkState(action.discoversInputs(),
203203
"Actions that don't know their inputs must discover them: %s", action);
@@ -211,7 +211,7 @@ public Token getTokenIfNeedToExecute(
211211
return new Token(getKeyString(action));
212212
}
213213

214-
if (!inputsKnown) {
214+
if (!inputsDiscovered) {
215215
action.updateInputs(actionInputs);
216216
}
217217
return null;

‎src/main/java/com/google/devtools/build/lib/actions/ActionExecutionMetadata.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public interface ActionExecutionMetadata extends ActionAnalysisMetadata {
106106
* built first, as usual.
107107
*/
108108
@ThreadSafe
109-
boolean inputsKnown();
109+
boolean inputsDiscovered();
110110

111111
/**
112112
* Returns true iff inputsKnown() may ever return false.

‎src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java‎

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@
7878
import java.util.Set;
7979
import java.util.UUID;
8080
import javax.annotation.Nullable;
81-
import javax.annotation.concurrent.GuardedBy;
8281

8382
/** Action that represents some kind of C++ compilation step. */
8483
@ThreadCompatible
@@ -215,9 +214,8 @@ public Collection<Artifact> getInputsForIncludedFile(
215214
*/
216215
private final UUID actionClassId;
217216

218-
// This can be read/written from multiple threads, and so accesses should be synchronized.
219-
@GuardedBy("this")
220-
private boolean inputsKnown = false;
217+
/** Whether this action needs to discover inputs. */
218+
private final boolean discoversInputs;
221219

222220
/**
223221
* Set when the action prepares for execution. Used to preserve state between preparation and
@@ -267,8 +265,6 @@ public Collection<Artifact> getInputsForIncludedFile(
267265
* @param lipoScannables List of artifacts to include-scan when this action is a lipo action
268266
* @param additionalIncludeScannables list of additional artifacts to include-scan
269267
* @param actionClassId TODO(bazel-team): Add parameter description
270-
* @param executionRequirements out-of-band hints to be passed to the execution backend to signal
271-
* platform requirements
272268
* @param environment TODO(bazel-team): Add parameter description
273269
* @param builtinIncludeFiles List of include files that may be included even if they are not
274270
* mentioned in the source file or any of the headers included by it
@@ -338,7 +334,7 @@ protected CppCompileAction(
338334
Preconditions.checkArgument(!shouldPruneModules || shouldScanIncludes, this);
339335
this.usePic = usePic;
340336
this.useHeaderModules = useHeaderModules;
341-
this.inputsKnown = !shouldScanIncludes && !cppSemantics.needsDotdInputPruning();
337+
this.discoversInputs = shouldScanIncludes || cppSemantics.needsDotdInputPruning();
342338
this.cppCompileCommandLine =
343339
new CppCompileCommandLine(
344340
sourceFile, dotdFile, copts, coptsFilter, features, variables, actionName);
@@ -405,11 +401,6 @@ public ImmutableSet<Artifact> getMandatoryOutputs() {
405401
return super.getMandatoryOutputs();
406402
}
407403

408-
@Override
409-
public synchronized boolean inputsKnown() {
410-
return inputsKnown;
411-
}
412-
413404
/**
414405
* Returns the list of additional inputs found by dependency discovery, during action preparation,
415406
* and clears the stored list. {@link #prepare} must be called before this method is called, on
@@ -428,7 +419,7 @@ public void setResolvedInputsForTesting(ImmutableList<Artifact> resolvedInputs)
428419

429420
@Override
430421
public boolean discoversInputs() {
431-
return true;
422+
return discoversInputs;
432423
}
433424

434425
@VisibleForTesting // productionVisibility = Visibility.PRIVATE
@@ -761,7 +752,7 @@ public ExtraActionInfo.Builder getExtraActionInfo() {
761752
}
762753
info.setOutputFile(outputFile.getExecPathString());
763754
info.setSourceFile(getSourceFile().getExecPathString());
764-
if (inputsKnown()) {
755+
if (inputsDiscovered()) {
765756
info.addAllSourcesAndHeaders(Artifact.toExecPaths(getInputs()));
766757
} else {
767758
info.addSourcesAndHeaders(getSourceFile().getExecPathString());
@@ -958,11 +949,10 @@ private static boolean isDeclaredIn(
958949
*
959950
* @throws ActionExecutionException iff any errors happen during update.
960951
*/
961-
@VisibleForTesting
952+
@VisibleForTesting // productionVisibility = Visibility.PRIVATE
962953
@ThreadCompatible
963-
public final synchronized void updateActionInputs(NestedSet<Artifact> discoveredInputs)
954+
public final void updateActionInputs(NestedSet<Artifact> discoveredInputs)
964955
throws ActionExecutionException {
965-
inputsKnown = false;
966956
NestedSetBuilder<Artifact> inputs = NestedSetBuilder.stableOrder();
967957
Profiler.instance().startTask(ProfilerTask.ACTION_UPDATE, this);
968958
try {
@@ -972,12 +962,9 @@ public final synchronized void updateActionInputs(NestedSet<Artifact> discovered
972962
}
973963
inputs.addAll(context.getTransitiveCompilationPrerequisites());
974964
inputs.addTransitive(discoveredInputs);
975-
inputsKnown = true;
965+
updateInputs(inputs.build());
976966
} finally {
977967
Profiler.instance().completeTask(ProfilerTask.ACTION_UPDATE);
978-
synchronized (this) {
979-
setInputs(inputs.build());
980-
}
981968
}
982969
}
983970

@@ -1013,18 +1000,6 @@ private static CcToolchainFeatures.Variables getOverwrittenVariables(
10131000
return variableBuilder.build();
10141001
}
10151002

1016-
@Override protected void setInputs(Iterable<Artifact> inputs) {
1017-
super.setInputs(inputs);
1018-
}
1019-
1020-
@Override
1021-
public synchronized void updateInputs(Iterable<Artifact> inputs) {
1022-
inputsKnown = true;
1023-
synchronized (this) {
1024-
setInputs(inputs);
1025-
}
1026-
}
1027-
10281003
@Override
10291004
public Iterable<Artifact> getAllowedDerivedInputs() {
10301005
return getAllowedDerivedInputsMap().values();

‎src/main/java/com/google/devtools/build/lib/rules/cpp/LTOBackendAction.java‎

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import java.util.Map;
3838
import java.util.Set;
3939
import javax.annotation.Nullable;
40-
import javax.annotation.concurrent.GuardedBy;
4140

4241
/**
4342
* Action used by LTOBackendArtifacts to create an LTOBackendAction. Similar to {@link SpawnAction},
@@ -54,10 +53,6 @@
5453
* http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html.
5554
*/
5655
public final class LTOBackendAction extends SpawnAction {
57-
// This can be read/written from multiple threads, and so accesses should be synchronized.
58-
@GuardedBy("this")
59-
private boolean inputsKnown;
60-
6156
private Collection<Artifact> mandatoryInputs;
6257
private Map<PathFragment, Artifact> bitcodeFiles;
6358
private Artifact imports;
@@ -92,8 +87,6 @@ public LTOBackendAction(
9287
mnemonic,
9388
false,
9489
null);
95-
96-
inputsKnown = false;
9790
mandatoryInputs = inputs;
9891
bitcodeFiles = allBitcodeFiles;
9992
imports = importsFile;
@@ -149,11 +142,6 @@ public Iterable<Artifact> discoverInputs(ActionExecutionContext actionExecutionC
149142
return bitcodeInputSet;
150143
}
151144

152-
@Override
153-
public synchronized boolean inputsKnown() {
154-
return inputsKnown;
155-
}
156-
157145
@Override
158146
public Collection<Artifact> getMandatoryInputs() {
159147
return mandatoryInputs;
@@ -166,12 +154,6 @@ private static Iterable<Artifact> createInputs(
166154
return result;
167155
}
168156

169-
@Override
170-
public synchronized void updateInputs(Iterable<Artifact> discoveredInputs) {
171-
setInputs(discoveredInputs);
172-
inputsKnown = true;
173-
}
174-
175157
@Override
176158
public Iterable<Artifact> getAllowedDerivedInputs() {
177159
return bitcodeFiles.values();
@@ -181,10 +163,6 @@ public Iterable<Artifact> getAllowedDerivedInputs() {
181163
public void execute(ActionExecutionContext actionExecutionContext)
182164
throws ActionExecutionException, InterruptedException {
183165
super.execute(actionExecutionContext);
184-
185-
synchronized (this) {
186-
inputsKnown = true;
187-
}
188166
}
189167

190168
@Override

0 commit comments

Comments
 (0)