Skip to content

Commit 1997f09

Browse files
mattemcopybara-github
authored andcommitted
feat: add option to exit early if analysis cache is discarded
Adds `--allow_analysis_cache_discard` option that allows the build to exit early if the analysis cache would have been discarded. The flag name is of course open to bikeshedding etc. fixes #16804 Closes #16805. PiperOrigin-RevId: 552575951 Change-Id: Ia336eb3a5b7d7e41665fd0e0adf3edc03ed50f18
1 parent db579e4 commit 1997f09

File tree

11 files changed

+82
-9
lines changed

11 files changed

+82
-9
lines changed

src/main/java/com/google/devtools/build/lib/analysis/AnalysisOptions.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ public class AnalysisOptions extends OptionsBase {
3939
)
4040
public boolean discardAnalysisCache;
4141

42+
@Option(
43+
name = "allow_analysis_cache_discard",
44+
defaultValue = "true",
45+
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
46+
effectTags = {OptionEffectTag.EAGERNESS_TO_EXIT},
47+
help =
48+
"If discarding the analysis cache due to a change in the build system, setting this"
49+
+ " option to false will cause bazel to exit, rather than continuing with the build."
50+
+ " This option has no effect when 'discard_analysis_cache' is also set.")
51+
public boolean allowAnalysisCacheDiscards;
52+
4253
@Option(
4354
name = "max_config_changes_to_show",
4455
defaultValue = "3",

src/main/java/com/google/devtools/build/lib/analysis/BuildView.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,10 @@ public AnalysisResult update(
255255
}
256256

257257
skyframeBuildView.setConfiguration(
258-
eventHandler, topLevelConfig, viewOptions.maxConfigChangesToShow);
258+
eventHandler,
259+
topLevelConfig,
260+
viewOptions.maxConfigChangesToShow,
261+
viewOptions.allowAnalysisCacheDiscards);
259262

260263
eventBus.post(new MakeEnvironmentEvent(topLevelConfig.getMakeEnvironment()));
261264
eventBus.post(topLevelConfig.toBuildEvent());
@@ -510,7 +513,7 @@ private AnalysisResult createResult(
510513
ImmutableMap<Label, Target> labelToTargetMap,
511514
boolean includeExecutionPhase)
512515
throws InterruptedException {
513-
Set<Label> testsToRun = loadingResult.getTestsToRunLabels();
516+
ImmutableSet<Label> testsToRun = loadingResult.getTestsToRunLabels();
514517
Set<ConfiguredTarget> configuredTargets =
515518
Sets.newLinkedHashSet(skyframeAnalysisResult.getConfiguredTargets());
516519
ImmutableMap<AspectKey, ConfiguredAspect> aspects = skyframeAnalysisResult.getAspects();

src/main/java/com/google/devtools/build/lib/buildeventstream/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ java_library(
2828
"//src/main/java/com/google/devtools/build/lib/skyframe:build_configuration",
2929
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec",
3030
"//src/main/java/com/google/devtools/build/lib/util",
31+
"//src/main/java/com/google/devtools/build/lib/util:detailed_exit_code",
3132
"//src/main/java/com/google/devtools/build/lib/util:exit_code",
3233
"//src/main/java/com/google/devtools/build/lib/vfs",
3334
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",

src/main/java/com/google/devtools/build/lib/buildeventstream/BuildCompletingEvent.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616

1717
import com.google.common.collect.ImmutableList;
1818
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId;
19+
import com.google.devtools.build.lib.util.DetailedExitCode;
1920
import com.google.devtools.build.lib.util.ExitCode;
2021
import com.google.protobuf.util.Timestamps;
2122
import java.util.Collection;
23+
import javax.annotation.Nullable;
2224

2325
/**
2426
* Class all events completing a build inherit from.
@@ -27,18 +29,28 @@
2729
* However, subclasses do not have to implement anything.
2830
*/
2931
public abstract class BuildCompletingEvent implements BuildEvent {
32+
@Nullable private final DetailedExitCode detailedExitCode;
3033
private final ExitCode exitCode;
3134
private final long finishTimeMillis;
3235

3336
private final Collection<BuildEventId> children;
3437

3538
public BuildCompletingEvent(
3639
ExitCode exitCode, long finishTimeMillis, Collection<BuildEventId> children) {
40+
this.detailedExitCode = null;
3741
this.exitCode = exitCode;
3842
this.finishTimeMillis = finishTimeMillis;
3943
this.children = children;
4044
}
4145

46+
public BuildCompletingEvent(
47+
DetailedExitCode detailedExitCode, long finishTimeMillis, Collection<BuildEventId> children) {
48+
this.detailedExitCode = detailedExitCode;
49+
this.exitCode = detailedExitCode.getExitCode();
50+
this.finishTimeMillis = finishTimeMillis;
51+
this.children = children;
52+
}
53+
4254
public BuildCompletingEvent(ExitCode exitCode, long finishTimeMillis) {
4355
this(exitCode, finishTimeMillis, ImmutableList.of());
4456
}
@@ -65,13 +77,17 @@ public BuildEventStreamProtos.BuildEvent asStreamProto(BuildEventContext convert
6577
.setCode(exitCode.getNumericExitCode())
6678
.build();
6779

68-
BuildEventStreamProtos.BuildFinished finished =
80+
BuildEventStreamProtos.BuildFinished.Builder finished =
6981
BuildEventStreamProtos.BuildFinished.newBuilder()
7082
.setOverallSuccess(ExitCode.SUCCESS.equals(exitCode))
7183
.setExitCode(protoExitCode)
7284
.setFinishTime(Timestamps.fromMillis(finishTimeMillis))
73-
.setFinishTimeMillis(finishTimeMillis)
74-
.build();
75-
return GenericBuildEvent.protoChaining(this).setFinished(finished).build();
85+
.setFinishTimeMillis(finishTimeMillis);
86+
87+
if (detailedExitCode != null && detailedExitCode.getFailureDetail() != null) {
88+
finished.setFailureDetail(detailedExitCode.getFailureDetail());
89+
}
90+
91+
return GenericBuildEvent.protoChaining(this).setFinished(finished.build()).build();
7692
}
7793
}

src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,9 @@ message BuildFinished {
836836
google.protobuf.Timestamp finish_time = 5;
837837

838838
AnomalyReport anomaly_report = 4 [deprecated = true];
839+
840+
// Only populated if success = false, and sometimes not even then.
841+
failure_details.FailureDetail failure_detail = 6;
839842
}
840843

841844
message BuildMetrics {

src/main/java/com/google/devtools/build/lib/buildtool/buildevent/BuildCompleteEvent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public final class BuildCompleteEvent extends BuildCompletingEvent {
3232

3333
/** Construct the BuildCompleteEvent. */
3434
public BuildCompleteEvent(BuildResult result, Collection<BuildEventId> children) {
35-
super(result.getDetailedExitCode().getExitCode(), result.getStopTime(), children);
35+
super(result.getDetailedExitCode(), result.getStopTime(), children);
3636
this.result = checkNotNull(result);
3737
}
3838

src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
import com.google.devtools.build.lib.analysis.config.BuildOptions;
6767
import com.google.devtools.build.lib.analysis.config.BuildOptions.OptionsDiff;
6868
import com.google.devtools.build.lib.analysis.config.ConfigConditions;
69+
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
6970
import com.google.devtools.build.lib.analysis.config.StarlarkTransitionCache;
7071
import com.google.devtools.build.lib.analysis.test.AnalysisFailurePropagationException;
7172
import com.google.devtools.build.lib.analysis.test.CoverageActionFinishedEvent;
@@ -89,6 +90,7 @@
8990
import com.google.devtools.build.lib.packages.TargetUtils;
9091
import com.google.devtools.build.lib.profiler.Profiler;
9192
import com.google.devtools.build.lib.profiler.SilentCloseable;
93+
import com.google.devtools.build.lib.server.FailureDetails;
9294
import com.google.devtools.build.lib.skyframe.ArtifactConflictFinder.ConflictException;
9395
import com.google.devtools.build.lib.skyframe.AspectKeyCreator.AspectKey;
9496
import com.google.devtools.build.lib.skyframe.AspectKeyCreator.TopLevelAspectsKey;
@@ -279,7 +281,11 @@ private ImmutableSet<OptionDefinition> getNativeCacheInvalidatingDifferences(
279281
/** Sets the configuration. Not thread-safe. DO NOT CALL except from tests! */
280282
@VisibleForTesting
281283
public void setConfiguration(
282-
EventHandler eventHandler, BuildConfigurationValue configuration, int maxDifferencesToShow) {
284+
EventHandler eventHandler,
285+
BuildConfigurationValue configuration,
286+
int maxDifferencesToShow,
287+
boolean allowAnalysisCacheDiscards)
288+
throws InvalidConfigurationException {
283289
if (skyframeAnalysisWasDiscarded) {
284290
eventHandler.handle(
285291
Event.warn(
@@ -290,6 +296,12 @@ public void setConfiguration(
290296
} else {
291297
String diff = describeConfigurationDifference(configuration, maxDifferencesToShow);
292298
if (diff != null) {
299+
if (!allowAnalysisCacheDiscards) {
300+
String message = String.format("%s, analysis cache would have been discarded.", diff);
301+
throw new InvalidConfigurationException(
302+
message,
303+
FailureDetails.BuildConfiguration.Code.CONFIGURATION_DISCARDED_ANALYSIS_CACHE);
304+
}
293305
eventHandler.handle(
294306
Event.warn(
295307
diff

src/main/protobuf/failure_details.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ message BuildConfiguration {
608608
// possibilities in Bazel, so we go with the more straightforward
609609
// command-line error exit code 2.
610610
INVALID_OUTPUT_DIRECTORY_MNEMONIC = 11 [(metadata) = { exit_code: 2 }];
611+
CONFIGURATION_DISCARDED_ANALYSIS_CACHE = 12 [(metadata) = { exit_code: 2 }];
611612
}
612613

613614
Code code = 1;
@@ -1197,6 +1198,7 @@ message Analysis {
11971198
CONFIGURED_VALUE_CREATION_FAILED = 18 [(metadata) = { exit_code: 1 }];
11981199
INCOMPATIBLE_TARGET_REQUESTED = 19 [(metadata) = { exit_code: 1 }];
11991200
ANALYSIS_FAILURE_PROPAGATION_FAILED = 20 [(metadata) = { exit_code: 1 }];
1201+
ANALYSIS_CACHE_DISCARDED = 21 [(metadata) = { exit_code: 1 }];
12001202
}
12011203

12021204
Code code = 1;

src/test/java/com/google/devtools/build/lib/analysis/AnalysisCachingTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.google.devtools.build.lib.analysis.config.BuildOptionsView;
2626
import com.google.devtools.build.lib.analysis.config.Fragment;
2727
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
28+
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
2829
import com.google.devtools.build.lib.analysis.config.RequiresOptions;
2930
import com.google.devtools.build.lib.analysis.config.transitions.NoTransition;
3031
import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition;
@@ -1163,4 +1164,16 @@ public void cacheClearMessageAfterDiscardAnalysisCacheBuildWithRelevantOptionCha
11631164
assertDoesNotContainEvent("Build option");
11641165
assertContainsEvent("discarding analysis cache");
11651166
}
1167+
1168+
@Test
1169+
public void throwsIfAnalysisCacheIsDiscardedWhenOptionSet() throws Exception {
1170+
setupDiffResetTesting();
1171+
scratch.file("test/BUILD", "load(':lib.bzl', 'normal_lib')", "normal_lib(name='top')");
1172+
useConfiguration("--definitely_relevant=old");
1173+
update("//test:top");
1174+
useConfiguration("--noallow_analysis_cache_discard", "--definitely_relevant=new");
1175+
1176+
Throwable t = assertThrows(InvalidConfigurationException.class, () -> update("//test:top"));
1177+
assertThat(t.getMessage().contains("analysis cache would have been discarded")).isTrue();
1178+
}
11661179
}

src/test/java/com/google/devtools/build/lib/analysis/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ java_library(
8585
"//src/main/java/com/google/devtools/build/lib/analysis:config/fragment",
8686
"//src/main/java/com/google/devtools/build/lib/analysis:config/fragment_options",
8787
"//src/main/java/com/google/devtools/build/lib/analysis:config/fragment_registry",
88+
"//src/main/java/com/google/devtools/build/lib/analysis:config/invalid_configuration_exception",
8889
"//src/main/java/com/google/devtools/build/lib/analysis:config/per_label_options",
8990
"//src/main/java/com/google/devtools/build/lib/analysis:config/run_under",
9091
"//src/main/java/com/google/devtools/build/lib/analysis:config/run_under_converter",

0 commit comments

Comments
 (0)