Skip to content

Commit 1b333a2

Browse files
ulfjackCopybara-Service
authored and
Copybara-Service
committed
Fix Cpp{Compile,Link}Action environment and cache key computation
These were previously ignoring the inhertied environment, i.e., --action_env=PATH did _not_ result in the PATH variable being forwarded from the client environment. Fixes bazelbuild#5142. PiperOrigin-RevId: 196966822
1 parent 4ca4b8d commit 1b333a2

File tree

9 files changed

+89
-43
lines changed

9 files changed

+89
-43
lines changed

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

+35-10
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,31 @@ public abstract class AbstractAction implements Action, ActionApi {
106106
/**
107107
* Construct an abstract action with the specified inputs and outputs;
108108
*/
109-
protected AbstractAction(ActionOwner owner,
110-
Iterable<Artifact> inputs,
111-
Iterable<Artifact> outputs) {
112-
this(owner, ImmutableList.<Artifact>of(), inputs, EmptyRunfilesSupplier.INSTANCE, outputs);
109+
protected AbstractAction(
110+
ActionOwner owner,
111+
Iterable<Artifact> inputs,
112+
Iterable<Artifact> outputs) {
113+
this(
114+
owner,
115+
/*tools = */ImmutableList.of(),
116+
inputs,
117+
EmptyRunfilesSupplier.INSTANCE,
118+
outputs,
119+
ActionEnvironment.EMPTY);
120+
}
121+
122+
protected AbstractAction(
123+
ActionOwner owner,
124+
Iterable<Artifact> inputs,
125+
Iterable<Artifact> outputs,
126+
ActionEnvironment env) {
127+
this(
128+
owner,
129+
/*tools = */ImmutableList.of(),
130+
inputs,
131+
EmptyRunfilesSupplier.INSTANCE,
132+
outputs,
133+
env);
113134
}
114135

115136
/**
@@ -120,15 +141,21 @@ protected AbstractAction(
120141
Iterable<Artifact> tools,
121142
Iterable<Artifact> inputs,
122143
Iterable<Artifact> outputs) {
123-
this(owner, tools, inputs, EmptyRunfilesSupplier.INSTANCE, outputs);
144+
this(owner, tools, inputs, EmptyRunfilesSupplier.INSTANCE, outputs, ActionEnvironment.EMPTY);
124145
}
125146

126147
protected AbstractAction(
127148
ActionOwner owner,
128149
Iterable<Artifact> inputs,
129150
RunfilesSupplier runfilesSupplier,
130151
Iterable<Artifact> outputs) {
131-
this(owner, ImmutableList.<Artifact>of(), inputs, runfilesSupplier, outputs);
152+
this(
153+
owner,
154+
/*tools=*/ImmutableList.of(),
155+
inputs,
156+
runfilesSupplier,
157+
outputs,
158+
ActionEnvironment.EMPTY);
132159
}
133160

134161
protected AbstractAction(
@@ -148,14 +175,12 @@ protected AbstractAction(
148175
Iterable<Artifact> outputs,
149176
ActionEnvironment env) {
150177
Preconditions.checkNotNull(owner);
151-
// TODO(bazel-team): Use RuleContext.actionOwner here instead
152178
this.owner = owner;
153179
this.tools = CollectionUtils.makeImmutable(tools);
154180
this.inputs = CollectionUtils.makeImmutable(inputs);
155-
this.env = env;
181+
this.env = Preconditions.checkNotNull(env);
156182
this.outputs = ImmutableSet.copyOf(outputs);
157-
this.runfilesSupplier = Preconditions.checkNotNull(runfilesSupplier,
158-
"runfilesSupplier may not be null");
183+
this.runfilesSupplier = Preconditions.checkNotNull(runfilesSupplier);
159184
Preconditions.checkArgument(!this.outputs.isEmpty(), "action outputs may not be empty");
160185
}
161186

src/main/java/com/google/devtools/build/lib/actions/CommandAction.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ public interface CommandAction extends Action, ExecutionInfoSpecifier {
2929

3030
/**
3131
* Returns a map of command line variables to their values that constitute the environment
32-
* in which this action should be run.
32+
* in which this action should be run. This excludes any inherited environment variables, as this
33+
* method does not provide access to the client environment.
3334
*/
35+
@VisibleForTesting
3436
ImmutableMap<String, String> getEnvironment();
3537

3638
/** Returns inputs to this action, including inputs that may be pruned. */

src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java

+1
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ protected SpawnInfo getExtraActionSpawnInfo() throws CommandLineExpansionExcepti
478478
}
479479

480480
@Override
481+
@VisibleForTesting
481482
public final ImmutableMap<String, String> getEnvironment() {
482483
// TODO(ulfjack): AbstractAction should declare getEnvironment with a return value of type
483484
// ActionEnvironment to avoid developers misunderstanding the purpose of this method. That

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

+17-8
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.google.common.collect.Iterables;
2525
import com.google.common.collect.Sets;
2626
import com.google.devtools.build.lib.actions.AbstractAction;
27+
import com.google.devtools.build.lib.actions.ActionEnvironment;
2728
import com.google.devtools.build.lib.actions.ActionExecutionContext;
2829
import com.google.devtools.build.lib.actions.ActionExecutionException;
2930
import com.google.devtools.build.lib.actions.ActionKeyContext;
@@ -155,7 +156,6 @@ public class CppCompileAction extends AbstractAction
155156
*/
156157
public static final String CLIF_MATCH = "clif-match";
157158

158-
private final ImmutableMap<String, String> localShellEnvironment;
159159
protected final Artifact outputFile;
160160
private final Artifact sourceFile;
161161
private final Artifact optionalSourceFile;
@@ -278,7 +278,7 @@ public class CppCompileAction extends AbstractAction
278278
@Nullable Artifact dwoFile,
279279
@Nullable Artifact ltoIndexingFile,
280280
Artifact optionalSourceFile,
281-
ImmutableMap<String, String> localShellEnvironment,
281+
ActionEnvironment env,
282282
CcCompilationContext ccCompilationContext,
283283
CoptsFilter coptsFilter,
284284
Iterable<IncludeScannable> lipoScannables,
@@ -298,7 +298,7 @@ public class CppCompileAction extends AbstractAction
298298
gcnoFile,
299299
dwoFile,
300300
ltoIndexingFile),
301-
localShellEnvironment,
301+
env,
302302
Preconditions.checkNotNull(outputFile),
303303
sourceFile,
304304
optionalSourceFile,
@@ -346,7 +346,7 @@ public class CppCompileAction extends AbstractAction
346346
ActionOwner owner,
347347
NestedSet<Artifact> inputs,
348348
ImmutableSet<Artifact> outputs,
349-
ImmutableMap<String, String> localShellEnvironment,
349+
ActionEnvironment env,
350350
Artifact outputFile,
351351
Artifact sourceFile,
352352
Artifact optionalSourceFile,
@@ -377,8 +377,7 @@ public class CppCompileAction extends AbstractAction
377377
boolean needsIncludeValidation,
378378
IncludeProcessing includeProcessing,
379379
@Nullable Artifact grepIncludes) {
380-
super(owner, inputs, outputs);
381-
this.localShellEnvironment = localShellEnvironment;
380+
super(owner, inputs, outputs, env);
382381
this.outputFile = outputFile;
383382
this.sourceFile = sourceFile;
384383
this.optionalSourceFile = optionalSourceFile;
@@ -746,8 +745,15 @@ public ImmutableCollection<String> getDefines() {
746745
}
747746

748747
@Override
748+
@VisibleForTesting
749749
public ImmutableMap<String, String> getEnvironment() {
750-
Map<String, String> environment = new LinkedHashMap<>(localShellEnvironment);
750+
return getEnvironment(ImmutableMap.of());
751+
}
752+
753+
public ImmutableMap<String, String> getEnvironment(Map<String, String> clientEnv) {
754+
Map<String, String> environment = new LinkedHashMap<>(env.size());
755+
env.resolve(environment, clientEnv);
756+
751757
if (!getExecutionInfo().containsKey(ExecutionRequirements.REQUIRES_DARWIN)) {
752758
// Linux: this prevents gcc/clang from writing the unpredictable (and often irrelevant) value
753759
// of getcwd() into the debug info. Not applicable to Darwin or Windows, which have no /proc.
@@ -786,6 +792,7 @@ public ExtraActionInfo.Builder getExtraActionInfo(ActionKeyContext actionKeyCont
786792
info.addAllSourcesAndHeaders(
787793
Artifact.toExecPaths(ccCompilationContext.getDeclaredIncludeSrcs()));
788794
}
795+
// TODO(ulfjack): Extra actions currently ignore the client environment.
789796
for (Map.Entry<String, String> envVariable : getEnvironment().entrySet()) {
790797
info.addVariable(
791798
EnvironmentVariable.newBuilder()
@@ -1105,7 +1112,9 @@ public ResourceSet estimateResourceConsumptionLocal() {
11051112
@Override
11061113
public void computeKey(ActionKeyContext actionKeyContext, Fingerprint fp) {
11071114
fp.addUUID(actionClassId);
1108-
fp.addStringMap(getEnvironment());
1115+
fp.addStringMap(env.getFixedEnv());
1116+
fp.addStrings(env.getInheritedEnv());
1117+
fp.addStringMap(compileCommandLine.getEnvironment());
11091118
fp.addStringMap(executionInfo);
11101119

11111120
// For the argv part of the cache key, ignore all compiler flags that explicitly denote module

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

+16-5
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414

1515
package com.google.devtools.build.lib.rules.cpp;
1616

17+
import com.google.common.annotations.VisibleForTesting;
1718
import com.google.common.base.Functions;
1819
import com.google.common.base.Preconditions;
1920
import com.google.common.base.Predicates;
2021
import com.google.common.collect.ImmutableList;
2122
import com.google.common.collect.ImmutableMap;
2223
import com.google.common.collect.ImmutableSet;
2324
import com.google.common.collect.Iterables;
25+
import com.google.devtools.build.lib.actions.ActionEnvironment;
2426
import com.google.devtools.build.lib.actions.ActionOwner;
2527
import com.google.devtools.build.lib.actions.Artifact;
2628
import com.google.devtools.build.lib.analysis.RuleContext;
@@ -78,7 +80,7 @@ public class CppCompileActionBuilder {
7880
private CppSemantics cppSemantics;
7981
private CcToolchainProvider ccToolchain;
8082
@Nullable private final Artifact grepIncludes;
81-
private final ImmutableMap<String, String> localShellEnvironment;
83+
private ActionEnvironment env;
8284
private final boolean codeCoverageEnabled;
8385
@Nullable private String actionName;
8486
private ImmutableList<Artifact> builtinIncludeFiles;
@@ -122,7 +124,7 @@ private CppCompileActionBuilder(
122124
this.mandatoryInputsBuilder = NestedSetBuilder.stableOrder();
123125
this.additionalIncludeScanningRoots = new ImmutableList.Builder<>();
124126
this.allowUsingHeaderModules = true;
125-
this.localShellEnvironment = configuration.getLocalShellEnvironment();
127+
this.env = configuration.getActionEnvironment();
126128
this.codeCoverageEnabled = configuration.isCodeCoverageEnabled();
127129
this.ccToolchain = ccToolchain;
128130
this.grepIncludes = grepIncludes;
@@ -159,7 +161,7 @@ public CppCompileActionBuilder(CppCompileActionBuilder other) {
159161
this.lipoScannableMap = other.lipoScannableMap;
160162
this.shouldScanIncludes = other.shouldScanIncludes;
161163
this.executionInfo = new LinkedHashMap<>(other.executionInfo);
162-
this.localShellEnvironment = other.localShellEnvironment;
164+
this.env = other.env;
163165
this.codeCoverageEnabled = other.codeCoverageEnabled;
164166
this.cppSemantics = other.cppSemantics;
165167
this.ccToolchain = other.ccToolchain;
@@ -378,7 +380,7 @@ public CppCompileAction buildAndVerify(Consumer<String> errorCollector) {
378380
outputFile,
379381
tempOutputFile,
380382
dotdFile,
381-
localShellEnvironment,
383+
env,
382384
ccCompilationContext,
383385
coptsFilter,
384386
getLipoScannables(realMandatoryInputs),
@@ -409,7 +411,7 @@ public CppCompileAction buildAndVerify(Consumer<String> errorCollector) {
409411
dwoFile,
410412
ltoIndexingFile,
411413
optionalSourceFile,
412-
localShellEnvironment,
414+
env,
413415
ccCompilationContext,
414416
coptsFilter,
415417
getLipoScannables(realMandatoryInputs),
@@ -719,4 +721,13 @@ public PathFragment getRealOutputFilePath() {
719721
return getOutputFile().getExecPath();
720722
}
721723
}
724+
725+
/**
726+
* Do not use! This method is only intended for testing.
727+
*/
728+
@VisibleForTesting
729+
public CppCompileActionBuilder setActionEnvironment(ActionEnvironment env) {
730+
this.env = env;
731+
return this;
732+
}
722733
}

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

+12-14
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
import com.google.common.collect.ImmutableMap;
2323
import com.google.common.collect.ImmutableSet;
2424
import com.google.common.collect.Iterables;
25+
import com.google.common.collect.Maps;
2526
import com.google.devtools.build.lib.actions.AbstractAction;
27+
import com.google.devtools.build.lib.actions.ActionEnvironment;
2628
import com.google.devtools.build.lib.actions.ActionExecutionContext;
2729
import com.google.devtools.build.lib.actions.ActionExecutionException;
2830
import com.google.devtools.build.lib.actions.ActionKeyContext;
@@ -63,6 +65,7 @@
6365
import java.io.IOException;
6466
import java.util.LinkedHashMap;
6567
import java.util.List;
68+
import java.util.Map;
6669
import javax.annotation.Nullable;
6770

6871
/** Action that represents a linking step. */
@@ -107,8 +110,6 @@ public Artifact create(RuleContext ruleContext, BuildConfiguration configuration
107110
private final LibraryToLink outputLibrary;
108111
private final Artifact linkOutput;
109112
private final LibraryToLink interfaceOutputLibrary;
110-
private final ImmutableSet<String> clientEnvironmentVariables;
111-
private final ImmutableMap<String, String> actionEnv;
112113
private final ImmutableMap<String, String> toolchainEnv;
113114
private final ImmutableSet<String> executionRequirements;
114115
private final ImmutableList<Artifact> linkstampObjects;
@@ -164,14 +165,13 @@ public Artifact create(RuleContext ruleContext, BuildConfiguration configuration
164165
boolean isLtoIndexing,
165166
ImmutableList<Artifact> linkstampObjects,
166167
LinkCommandLine linkCommandLine,
167-
ImmutableSet<String> clientEnvironmentVariables,
168-
ImmutableMap<String, String> actionEnv,
168+
ActionEnvironment env,
169169
ImmutableMap<String, String> toolchainEnv,
170170
ImmutableSet<String> executionRequirements,
171171
PathFragment ldExecutable,
172172
String hostSystemName,
173173
String targetCpu) {
174-
super(owner, inputs, outputs);
174+
super(owner, inputs, outputs, env);
175175
if (mnemonic == null) {
176176
this.mnemonic = (isLtoIndexing) ? "CppLTOIndexing" : "CppLink";
177177
} else {
@@ -186,8 +186,6 @@ public Artifact create(RuleContext ruleContext, BuildConfiguration configuration
186186
this.isLtoIndexing = isLtoIndexing;
187187
this.linkstampObjects = linkstampObjects;
188188
this.linkCommandLine = linkCommandLine;
189-
this.clientEnvironmentVariables = clientEnvironmentVariables;
190-
this.actionEnv = actionEnv;
191189
this.toolchainEnv = toolchainEnv;
192190
this.executionRequirements = executionRequirements;
193191
this.ldExecutable = ldExecutable;
@@ -211,15 +209,15 @@ public Iterable<Artifact> getPossibleInputsForTesting() {
211209
}
212210

213211
@Override
214-
public Iterable<String> getClientEnvironmentVariables() {
215-
return clientEnvironmentVariables;
212+
@VisibleForTesting
213+
public ImmutableMap<String, String> getEnvironment() {
214+
return getEnvironment(ImmutableMap.of());
216215
}
217216

218-
@Override
219-
public ImmutableMap<String, String> getEnvironment() {
220-
LinkedHashMap<String, String> result = new LinkedHashMap<>();
217+
public ImmutableMap<String, String> getEnvironment(Map<String, String> clientEnv) {
218+
LinkedHashMap<String, String> result = Maps.newLinkedHashMapWithExpectedSize(env.size());
219+
env.resolve(result, clientEnv);
221220

222-
result.putAll(actionEnv);
223221
result.putAll(toolchainEnv);
224222

225223
if (!executionRequirements.contains(ExecutionRequirements.REQUIRES_DARWIN)) {
@@ -313,7 +311,7 @@ public ActionResult execute(ActionExecutionContext actionExecutionContext)
313311
new SimpleSpawn(
314312
this,
315313
ImmutableList.copyOf(getCommandLine(actionExecutionContext.getArtifactExpander())),
316-
getEnvironment(),
314+
getEnvironment(actionExecutionContext.getClientEnv()),
317315
getExecutionInfo(),
318316
ImmutableList.copyOf(getMandatoryInputs()),
319317
getOutputs().asList(),

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -1204,8 +1204,7 @@ public CppLinkAction build() throws InterruptedException {
12041204
.map(Linkstamp::getArtifact)
12051205
.collect(ImmutableList.toImmutableList()),
12061206
linkCommandLine,
1207-
configuration.getVariableShellEnvironment(),
1208-
configuration.getLocalShellEnvironment(),
1207+
configuration.getActionEnvironment(),
12091208
toolchainEnv,
12101209
executionRequirements.build(),
12111210
toolchain.getToolPathFragment(Tool.LD),

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.google.common.base.Preconditions;
2121
import com.google.common.collect.ImmutableList;
2222
import com.google.common.collect.ImmutableMap;
23+
import com.google.devtools.build.lib.actions.ActionEnvironment;
2324
import com.google.devtools.build.lib.actions.ActionExecutionContext;
2425
import com.google.devtools.build.lib.actions.ActionExecutionException;
2526
import com.google.devtools.build.lib.actions.ActionOwner;
@@ -73,7 +74,7 @@ public class FakeCppCompileAction extends CppCompileAction {
7374
Artifact outputFile,
7475
PathFragment tempOutputFile,
7576
DotdFile dotdFile,
76-
ImmutableMap<String, String> localShellEnvironment,
77+
ActionEnvironment env,
7778
CcCompilationContext ccCompilationContext,
7879
CoptsFilter nocopts,
7980
Iterable<IncludeScannable> lipoScannables,
@@ -102,7 +103,7 @@ public class FakeCppCompileAction extends CppCompileAction {
102103
/* dwoFile=*/ null,
103104
/* ltoIndexingFile=*/ null,
104105
/* optionalSourceFile=*/ null,
105-
localShellEnvironment,
106+
env,
106107
// We only allow inclusion of header files explicitly declared in
107108
// "srcs", so we only use declaredIncludeSrcs, not declaredIncludeDirs.
108109
// (Disallowing use of undeclared headers for cc_fake_binary is needed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public CppCompileActionResult execWithReply(
5252
new SimpleSpawn(
5353
action,
5454
ImmutableList.copyOf(action.getArguments()),
55-
ImmutableMap.copyOf(action.getEnvironment()),
55+
ImmutableMap.copyOf(action.getEnvironment(actionExecutionContext.getClientEnv())),
5656
ImmutableMap.copyOf(action.getExecutionInfo()),
5757
EmptyRunfilesSupplier.INSTANCE,
5858
ImmutableMap.of(),

0 commit comments

Comments
 (0)