| // Copyright 2014 The Bazel Authors. All rights reserved. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package com.google.devtools.build.lib.exec; | |
| import com.google.common.collect.ImmutableMap; | |
| import com.google.common.collect.Iterables; | |
| import com.google.devtools.build.lib.actions.ActionExecutionContext.ShowSubcommands; | |
| import com.google.devtools.build.lib.actions.LocalHostCapacity; | |
| import com.google.devtools.build.lib.actions.ResourceSet; | |
| import com.google.devtools.build.lib.analysis.config.CoreOptionConverters.LabelConverter; | |
| import com.google.devtools.build.lib.analysis.config.PerLabelOptions; | |
| import com.google.devtools.build.lib.cmdline.Label; | |
| import com.google.devtools.build.lib.util.OptionsUtils; | |
| import com.google.devtools.build.lib.util.RegexFilter; | |
| import com.google.devtools.build.lib.util.ResourceConverter; | |
| import com.google.devtools.build.lib.vfs.PathFragment; | |
| import com.google.devtools.common.options.BoolOrEnumConverter; | |
| import com.google.devtools.common.options.BooleanStyleOption; | |
| import com.google.devtools.common.options.Converter; | |
| import com.google.devtools.common.options.Converters; | |
| import com.google.devtools.common.options.Converters.AssignmentToListOfValuesConverter; | |
| import com.google.devtools.common.options.Converters.CommaSeparatedNonEmptyOptionListConverter; | |
| import com.google.devtools.common.options.EnumConverter; | |
| import com.google.devtools.common.options.Option; | |
| import com.google.devtools.common.options.OptionDocumentationCategory; | |
| import com.google.devtools.common.options.OptionEffectTag; | |
| import com.google.devtools.common.options.OptionsBase; | |
| import com.google.devtools.common.options.OptionsClass; | |
| import com.google.devtools.common.options.OptionsParsingException; | |
| import java.time.Duration; | |
| import java.util.Collections; | |
| import java.util.List; | |
| import java.util.Map; | |
| import java.util.Objects; | |
| import javax.annotation.Nullable; | |
| /** | |
| * Options affecting the execution phase of a build. | |
| * | |
| * <p>These options are interpreted by the BuildTool to choose an Executor to be used for the build. | |
| * | |
| * <p>Note: from the user's point of view, the characteristic function of this set of options is | |
| * indistinguishable from that of the BuildRequestOptions: they are all per-request. The difference | |
| * is only apparent in the implementation: these options are used only by the lib.exec machinery, | |
| * which affects how C++ and Java compilation occur. (The BuildRequestOptions contain a mixture of | |
| * "semantic" options affecting the choice of targets to build, and "non-semantic" options affecting | |
| * the lib.actions machinery.) Ideally, the user would be unaware of the difference. For now, the | |
| * usage strings are identical modulo "part 1", "part 2". | |
| */ | |
| @OptionsClass | |
| public abstract class ExecutionOptions extends OptionsBase { | |
| @Option( | |
| name = "spawn_strategy", | |
| defaultValue = "", | |
| converter = CommaSeparatedNonEmptyOptionListConverter.class, | |
| documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| """ | |
| Specify how spawn actions are executed by default. Accepts a comma-separated list of | |
| strategies from highest to lowest priority. For each action Bazel picks the | |
| strategy with the highest priority that can execute the action. The default | |
| value is `remote,worker,sandboxed,local`. | |
| See [Automatic execution strategy selection in Bazel 0.27] for details. | |
| [Automatic execution strategy selection in Bazel 0.27]: https://blog.bazel.build/2019/06/19/list-strategy.html | |
| """) | |
| public abstract List<String> getSpawnStrategy(); | |
| @Option( | |
| name = "genrule_strategy", | |
| defaultValue = "", | |
| converter = CommaSeparatedNonEmptyOptionListConverter.class, | |
| documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| """ | |
| Specify how to execute genrules. This flag will be phased out. Instead, use | |
| `--spawn_strategy=<value>` to control all actions or `--strategy=Genrule=<value>` | |
| to control genrules only. | |
| """) | |
| public abstract List<String> getGenruleStrategy(); | |
| @Option( | |
| name = "strategy", | |
| allowMultiple = true, | |
| converter = Converters.StringToStringListConverter.class, | |
| defaultValue = "null", | |
| documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| """ | |
| Specify how to distribute compilation of other spawn actions. Accepts a comma-separated | |
| list of strategies from highest to lowest priority. For each action Bazel picks | |
| the strategy with the highest priority that can execute the action. The default | |
| value is `remote,worker,sandboxed,local`. This flag overrides the values set | |
| by `--spawn_strategy` (and `--genrule_strategy` if used with mnemonic Genrule). | |
| See [Automatic execution strategy selection in Bazel 0.27] for details. | |
| [Automatic execution strategy selection in Bazel 0.27]: https://blog.bazel.build/2019/06/19/list-strategy.html | |
| """) | |
| public abstract List<Map.Entry<String, List<String>>> getStrategy(); | |
| @Option( | |
| name = "strategy_regexp", | |
| allowMultiple = true, | |
| converter = RegexFilterAssignmentConverter.class, | |
| documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| defaultValue = "null", | |
| help = | |
| """ | |
| Override which spawn strategy should be used to execute spawn actions that have | |
| descriptions matching a certain `regex_filter`. See `--per_file_copt` for details on | |
| `regex_filter` matching. | |
| The last `regex_filter` that matches the description is used. | |
| This option overrides other flags for specifying strategy. e.g. | |
| - `--strategy_regexp=//foo.*\\.cc,-//foo/bar=local` means to run actions | |
| using local strategy if their descriptions match //foo.*.cc but not //foo/bar. | |
| - `--strategy_regexp=Compiling.*/bar=local --strategy_regexp=Compiling=sandboxed` | |
| will run `Compiling //foo/bar/baz` with the `local` strategy, but reversing the order | |
| would run it with the `sandboxed` strategy. | |
| """) | |
| public abstract List<Map.Entry<RegexFilter, List<String>>> getStrategyByRegexp(); | |
| @Option( | |
| name = "allowed_strategies_by_exec_platform", | |
| allowMultiple = true, | |
| converter = LabelToStringListConverter.class, | |
| defaultValue = "null", | |
| documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| """ | |
| Filters spawn strategies by the execution platform without affecting order. | |
| For example: | |
| ``` | |
| common --spawn_strategy=remote,sandboxed,worker,local | |
| common --strategy=Genrule=local | |
| common --allowed_strategies_by_exec_platform=@platforms//host:host=local,sandboxed,worker | |
| common --allowed_strategies_by_exec_platform=//:linux_amd64=remote | |
| ``` | |
| With the above options; | |
| - Actions configured for the host platform will be given `remote,sandboxed,worker`. | |
| - Actions configured for the `//:linux_amd64` platform will be given `remote`. | |
| - Actions configured for the `//:linux_amd64` platform with mnemonic `Genrule` will be | |
| given no strategies and fail to spawn. | |
| """) | |
| public abstract List<Map.Entry<Label, List<String>>> getAllowedStrategiesByExecPlatform(); | |
| @Option( | |
| name = "materialize_param_files", | |
| defaultValue = "false", | |
| documentationCategory = OptionDocumentationCategory.LOGGING, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| """ | |
| Writes intermediate parameter files to output tree even when using remote action | |
| execution or caching. Useful when debugging actions. This is implied by | |
| `--subcommands` and `--verbose_failures`. | |
| """) | |
| public abstract boolean getMaterializeParamFiles(); | |
| @Option( | |
| name = "experimental_materialize_param_files_directly", | |
| defaultValue = "false", | |
| documentationCategory = OptionDocumentationCategory.LOGGING, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = "If materializing param files, do so with direct writes to disk.") | |
| public abstract boolean getMaterializeParamFilesDirectly(); | |
| public final boolean shouldMaterializeParamFiles() { | |
| // Implied by --subcommands and --verbose_failures | |
| return getMaterializeParamFiles() | |
| || getShowSubcommands() != ShowSubcommands.FALSE | |
| || getVerboseFailures(); | |
| } | |
| @Option( | |
| name = "verbose_failures", | |
| defaultValue = "false", | |
| documentationCategory = OptionDocumentationCategory.LOGGING, | |
| effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, | |
| help = "If a command fails, print out the full command line.") | |
| public abstract boolean getVerboseFailures(); | |
| @Option( | |
| name = "subcommands", | |
| abbrev = 's', | |
| defaultValue = "false", | |
| converter = ShowSubcommandsConverter.class, | |
| documentationCategory = OptionDocumentationCategory.LOGGING, | |
| effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, | |
| help = | |
| """ | |
| Display the subcommands executed during a build. | |
| Related flags: `--execution_log_json_file`, `--execution_log_binary_file` (for logging | |
| subcommands to a file in a tool-friendly format). | |
| """) | |
| public abstract ShowSubcommands getShowSubcommands(); | |
| @Option( | |
| name = "expand_param_files", | |
| defaultValue = "false", | |
| documentationCategory = OptionDocumentationCategory.LOGGING, | |
| effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, | |
| help = | |
| """ | |
| When displaying subcommands (`--subcommands`), printing the command line of a failed | |
| action (`--verbose_failures`) or writing the execution log | |
| (`--execution_log_{compact,binary,json}_file`), expand the contents of param files. | |
| When enabled, param file references like `@path/to/param_file` are replaced with | |
| the actual arguments they contain. Spawns are still executed with param files, | |
| and the execution log still records them as inputs. | |
| """) | |
| public abstract boolean getExpandParamFiles(); | |
| @Option( | |
| name = "check_up_to_date", | |
| defaultValue = "false", | |
| documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| "Don't perform the build, just check if it is up-to-date. If all targets are " | |
| + "up-to-date, the build completes successfully. If any step needs to be executed " | |
| + "an error is reported and the build fails.") | |
| public abstract boolean getCheckUpToDate(); | |
| @Option( | |
| name = "check_tests_up_to_date", | |
| defaultValue = "false", | |
| implicitRequirements = {"--check_up_to_date"}, | |
| documentationCategory = OptionDocumentationCategory.TESTING, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| """ | |
| Don't run tests, just check if they are up-to-date. If all tests results are | |
| up-to-date, the testing completes successfully. If any test needs to be built or | |
| executed, an error is reported and the testing fails. This option implies | |
| `--check_up_to_date` behavior. | |
| """) | |
| public abstract boolean getTestCheckUpToDate(); | |
| @Option( | |
| name = "test_strategy", | |
| defaultValue = "", | |
| documentationCategory = OptionDocumentationCategory.TESTING, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = "Specifies which strategy to use when running tests.") | |
| public abstract String getTestStrategy(); | |
| @Option( | |
| name = "test_keep_going", | |
| defaultValue = "true", | |
| documentationCategory = OptionDocumentationCategory.TESTING, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| "When disabled, any non-passing test will cause the entire build to stop. By default " | |
| + "all tests are run, even if some do not pass.") | |
| public abstract boolean getTestKeepGoing(); | |
| @Option( | |
| name = "flaky_test_attempts", | |
| allowMultiple = true, | |
| defaultValue = "default", | |
| converter = TestAttemptsConverter.class, | |
| documentationCategory = OptionDocumentationCategory.TESTING, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| """ | |
| Each test will be retried up to the specified number of times in case of any test | |
| failure. Tests that required more than one attempt to pass are marked as 'FLAKY' | |
| in the test summary. | |
| Normally the value specified is just an integer or the string `default`. | |
| - If an integer, then all tests will be run up to `N` times. | |
| - If `default`, then only a single test attempt will be made for regular tests and | |
| three for tests marked explicitly as flaky by their rule (`flaky=1` attribute). | |
| Alternate syntax: `regex_filter@flaky_test_attempts`. Where `flaky_test_attempts` is | |
| as above and `regex_filter` stands for a list of include and exclude regular | |
| expression patterns (also see `--runs_per_test`).\\ | |
| Example: `--flaky_test_attempts=//foo/.*,-//foo/bar/.*@3` deflakes all tests in `//foo/` | |
| except those under `//foo/bar` three times. | |
| This option can be passed multiple times. The most recently passed argument that matches | |
| takes precedence. If nothing matches, behavior is as if `default` above. | |
| """) | |
| public abstract List<PerLabelOptions> getTestAttempts(); | |
| @Option( | |
| name = "test_tmpdir", | |
| defaultValue = "null", | |
| converter = OptionsUtils.EmptyToNullPathFragmentConverter.class, | |
| documentationCategory = OptionDocumentationCategory.TESTING, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| help = "Specifies the base temporary directory for 'bazel test' to use.") | |
| public abstract PathFragment getTestTmpDir(); | |
| @Option( | |
| name = "test_output", | |
| defaultValue = "summary", | |
| converter = TestOutputFormat.Converter.class, | |
| documentationCategory = OptionDocumentationCategory.LOGGING, | |
| effectTags = { | |
| OptionEffectTag.TEST_RUNNER, | |
| OptionEffectTag.TERMINAL_OUTPUT, | |
| OptionEffectTag.EXECUTION | |
| }, | |
| help = | |
| """ | |
| Specifies desired output mode. Not to be confused with `--test_summary` which controls | |
| the test summary printed on command completion. | |
| Valid values are; | |
| - `summary` (default) to print summaries for failed tests, | |
| - `errors` to also print test logs for failed tests, | |
| - `all` to print summaries and logs for all tests and | |
| - `streamed` to output logs for all tests in real time (this will force tests to be | |
| executed locally one at a time via `--test_strategy=exclusive`, disabling parallel | |
| execution and sharding. For parallel execution of multiple tests, use `errors` or | |
| `all`). | |
| """) | |
| public abstract TestOutputFormat getTestOutput(); | |
| public abstract void setTestOutput(TestOutputFormat value); | |
| @Option( | |
| name = "max_test_output_bytes", | |
| defaultValue = "-1", | |
| documentationCategory = OptionDocumentationCategory.LOGGING, | |
| effectTags = { | |
| OptionEffectTag.TEST_RUNNER, | |
| OptionEffectTag.TERMINAL_OUTPUT, | |
| OptionEffectTag.EXECUTION | |
| }, | |
| help = | |
| """ | |
| Specifies maximum per-test-log size that can be emitted when `--test_output` is `errors` | |
| or `all`. Useful for avoiding overwhelming the output with excessively noisy test | |
| output. The test header is included in the log size. Negative values imply no | |
| limit. Output is all or nothing. | |
| """) | |
| public abstract int getMaxTestOutputBytes(); | |
| @Option( | |
| name = "test_summary", | |
| defaultValue = "short", | |
| converter = TestSummaryFormat.Converter.class, | |
| documentationCategory = OptionDocumentationCategory.LOGGING, | |
| effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, | |
| help = | |
| """ | |
| Specifies the desired format of the test summary. Valid values are; | |
| - `short` to list all tests that ran to completion. | |
| - `short_uncached` to list tests that ran to completion, omitting cached tests. | |
| - `terse` to list only failed and flaky tests. | |
| - `detailed` to list tests that ran to completion and their test cases. | |
| - `detailed_uncached` to list tests that ran to completion and their test cases, | |
| omitting cached tests. | |
| - `testcase` to print summary in test case resolution without detailed information about | |
| failed test cases. | |
| - `none` to omit the summary. | |
| """) | |
| public abstract TestSummaryFormat getTestSummary(); | |
| public abstract void setTestSummary(TestSummaryFormat value); | |
| @Option( | |
| name = "local_resources", | |
| defaultValue = "null", | |
| documentationCategory = OptionDocumentationCategory.BUILD_TIME_OPTIMIZATION, | |
| effectTags = {OptionEffectTag.HOST_MACHINE_RESOURCE_OPTIMIZATIONS}, | |
| allowMultiple = true, | |
| help = | |
| "Set the number of resources available to Bazel. " | |
| + "Takes in an assignment to a float or `" | |
| + ResourceConverter.HOST_RAM_KEYWORD | |
| + "`/`" | |
| + ResourceConverter.HOST_CPUS_KEYWORD | |
| + "`, optionally followed by `[-|*]<float>` (eg. `memory=" | |
| + ResourceConverter.HOST_RAM_KEYWORD | |
| + "*.5` to use half the available RAM). " | |
| + """ | |
| Can be used multiple times to specify multiple types of resources. Bazel will limit | |
| concurrently running actions based on the available resources and the resources required. | |
| Tests can declare the amount of resources they need by using a tag of the | |
| `resources:<resource name>:<amount>` format. | |
| """, | |
| converter = ResourceConverter.AssignmentConverter.class) | |
| public abstract List<Map.Entry<String, Double>> getLocalResourcesFields(); | |
| public final ImmutableMap<String, Double> getLocalResources() { | |
| ImmutableMap.Builder<String, Double> resources = ImmutableMap.builder(); | |
| return resources | |
| .put(ResourceSet.CPU, LocalHostCapacity.getLocalHostCapacity().getCpuUsage()) | |
| .put(ResourceSet.MEMORY, .67 * LocalHostCapacity.getLocalHostCapacity().getMemoryMb()) | |
| .putAll(getLocalResourcesFields()) | |
| .buildKeepingLast(); | |
| } | |
| @Option( | |
| name = "experimental_cpu_load_scheduling", | |
| defaultValue = "false", | |
| documentationCategory = OptionDocumentationCategory.BUILD_TIME_OPTIMIZATION, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| """ | |
| Enables the experimental local execution scheduling based on CPU load, not estimation of | |
| actions one by one. Experimental scheduling have showed the large benefit on a | |
| large local builds on a powerful machines with the large number of cores. | |
| Recommended to use with `--local_resources=cpu=HOST_CPUS`. | |
| """) | |
| public abstract boolean getExperimentalCpuLoadScheduling(); | |
| @Option( | |
| name = "experimental_cpu_load_scheduling_window_size", | |
| defaultValue = "5000ms", | |
| documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| """ | |
| The size of window during experimental scheduling of action based on CPU load. Make | |
| sense to define only when flag `--experimental_cpu_load_scheduling` is enabled. | |
| """) | |
| public abstract Duration getExperimentalCpuLoadSchedulingWindowSize(); | |
| @Option( | |
| name = "experimental_memory_load_scheduling", | |
| defaultValue = "false", | |
| documentationCategory = OptionDocumentationCategory.BUILD_TIME_OPTIMIZATION, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| "Enables the experimental local execution scheduling based on memory load, not estimation" | |
| + " of actions one by one.") | |
| public abstract boolean getExperimentalMemoryLoadScheduling(); | |
| @Option( | |
| name = "local_test_jobs", | |
| defaultValue = "auto", | |
| documentationCategory = OptionDocumentationCategory.TESTING, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| "The max number of local test jobs to run concurrently. " | |
| + "Takes " | |
| + ResourceConverter.FLAG_SYNTAX | |
| + ". 0 means local resources will limit the number of local test jobs to run " | |
| + "concurrently instead. Setting this greater than the value for `--jobs` " | |
| + "is ineffectual.", | |
| converter = LocalTestJobsConverter.class) | |
| public abstract int getLocalTestJobs(); | |
| public final boolean usingLocalTestJobs() { | |
| return getLocalTestJobs() != 0; | |
| } | |
| @Option( | |
| name = "cache_computed_file_digests", | |
| defaultValue = "50000", | |
| converter = Converters.NonNegativeIntegerConverter.class, | |
| documentationCategory = OptionDocumentationCategory.BUILD_TIME_OPTIMIZATION, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| help = | |
| "If greater than 0, configures Bazel to cache file digests in memory based on their " | |
| + "metadata instead of recomputing the digests from disk every time they are needed. " | |
| + "Setting this to 0 ensures correctness because not all file changes can be noted " | |
| + "from file metadata. When not 0, the number indicates the size of the cache as the " | |
| + "number of file digests to be cached.") | |
| public abstract int getCacheSizeForComputedFileDigests(); | |
| @Option( | |
| name = "experimental_enable_critical_path_profiling", | |
| defaultValue = "true", | |
| documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| help = | |
| "If set (the default), critical path profiling is enabled for the execution phase. This" | |
| + " has a slight overhead in RAM and CPU, and may prevent Bazel from making certain" | |
| + " aggressive RAM optimizations in some cases.") | |
| public abstract boolean getEnableCriticalPathProfiling(); | |
| @Option( | |
| name = "experimental_stats_summary", | |
| documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, | |
| effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, | |
| defaultValue = "false", | |
| help = "Enable a modernized summary of the build stats.") | |
| public abstract boolean getStatsSummary(); | |
| @Option( | |
| name = "execution_log_binary_file", | |
| defaultValue = "null", | |
| documentationCategory = OptionDocumentationCategory.LOGGING, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| converter = ExecutionLogFileConverter.class, | |
| help = | |
| """ | |
| Log the executed spawns into this file as length-delimited `SpawnExec` protos, according | |
| to [`src/main/protobuf/spawn.proto`]. Prefer `--execution_log_compact_file`, which is | |
| significantly smaller and cheaper to produce. | |
| The flag accepts boolean and string values. If string, it represents a local path. If | |
| `true`, then `--experimental_stream_log_file_uploads` must be set, whereby it will stream | |
| the execution log to remote storage. If `false`, then logging to the execution log is | |
| disabled. | |
| Related flags: | |
| - `--execution_log_compact_file` (compact format; mutually exclusive) | |
| - `--execution_log_json_file` (text JSON format; mutually exclusive) | |
| - `--execution_log_sort` (whether to sort the execution log) | |
| - `--subcommands` (for displaying subcommands in terminal output) | |
| [`src/main/protobuf/spawn.proto`]: https://github.com/bazelbuild/bazel/blob/master/src/main/protobuf/spawn.proto | |
| """) | |
| public abstract PathFragment getExecutionLogBinaryFile(); | |
| @Option( | |
| name = "execution_log_json_file", | |
| defaultValue = "null", | |
| documentationCategory = OptionDocumentationCategory.LOGGING, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| converter = ExecutionLogFileConverter.class, | |
| help = | |
| """ | |
| Log the executed spawns into this file as newline-delimited JSON representations of | |
| `SpawnExec` protos, according to [`src/main/protobuf/spawn.proto`]. Prefer | |
| `--execution_log_compact_file`, which is significantly smaller and cheaper to | |
| produce. | |
| The flag accepts boolean and string values. If string, it represents a local path. If | |
| `true`, then `--experimental_stream_log_file_uploads` must be set, whereby it will stream | |
| the execution log to remote storage. If `false`, then logging to the execution log is | |
| disabled. | |
| Related flags: | |
| - `--execution_log_compact_file` (compact format; mutually exclusive) | |
| - `--execution_log_binary_file` (binary protobuf format; mutually exclusive) | |
| - `--execution_log_sort` (whether to sort the execution log) | |
| - `--subcommands` (for displaying subcommands in terminal output) | |
| [`src/main/protobuf/spawn.proto`]: https://github.com/bazelbuild/bazel/blob/master/src/main/protobuf/spawn.proto | |
| """) | |
| public abstract PathFragment getExecutionLogJsonFile(); | |
| @Option( | |
| name = "execution_log_compact_file", | |
| oldName = "experimental_execution_log_compact_file", | |
| defaultValue = "null", | |
| documentationCategory = OptionDocumentationCategory.LOGGING, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| converter = ExecutionLogFileConverter.class, | |
| help = | |
| """ | |
| Log the executed spawns into this file as length-delimited `ExecLogEntry` protos, | |
| according to [`src/main/protobuf/spawn.proto`]. The entire file is zstd compressed. | |
| The flag accepts boolean and string values. If string, it represents a local path. If | |
| `true`, then `--experimental_stream_log_file_uploads` must be set, whereby it will stream | |
| the execution log to remote storage. If `false`, then logging to the execution log is | |
| disabled. | |
| Related flags: | |
| - `--execution_log_binary_file` (binary protobuf format; mutually exclusive) | |
| - `--execution_log_json_file` (text JSON format; mutually exclusive) | |
| - `--subcommands` (for displaying subcommands in terminal output) | |
| [`src/main/protobuf/spawn.proto`]: https://github.com/bazelbuild/bazel/blob/master/src/main/protobuf/spawn.proto | |
| """) | |
| public abstract PathFragment getExecutionLogCompactFile(); | |
| @Option( | |
| name = "execution_log_sort", | |
| defaultValue = "true", | |
| documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| help = | |
| "Whether to sort the execution log, making it easier to compare logs across invocations." | |
| + " Set to false to avoid potentially significant CPU and memory usage at the end of" | |
| + " the invocation, at the cost of producing the log in nondeterministic execution" | |
| + " order. Only applies to the binary and JSON formats; the compact format is never" | |
| + " sorted.") | |
| public abstract boolean getExecutionLogSort(); | |
| @Option( | |
| name = "execution_log_mnemonic_filter", | |
| defaultValue = ".*", | |
| converter = RegexFilter.RegexFilterConverter.class, | |
| documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | |
| effectTags = {OptionEffectTag.UNKNOWN}, | |
| help = | |
| "Filter the execution log by mnemonic. Only spawns with a matching mnemonic will be" | |
| + " logged. Supports a comma-separated list of regexes, with optional '-' prefix" | |
| + " for exclusions. The default is to log every spawn.") | |
| public abstract RegexFilter getExecutionLogMnemonicFilter(); | |
| @Option( | |
| // TODO: when this flag is moved to non-experimental, rename it to a more general name | |
| // to reflect the new logic - it's not only about cache evictions. | |
| name = "experimental_remote_cache_eviction_retries", | |
| defaultValue = "5", | |
| documentationCategory = OptionDocumentationCategory.REMOTE, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| "The maximum number of attempts to retry if the build encountered a transient remote" | |
| + " cache error that would otherwise fail the build. Applies for example when" | |
| + " artifacts are evicted from the remote cache, or in certain cache failure" | |
| + " conditions. A new invocation id will be generated for each attempt.") | |
| public abstract int getRemoteRetryOnTransientCacheError(); | |
| @Option( | |
| name = "allow_one_action_on_resource_unavailable", | |
| defaultValue = "true", // TODO: b/405364605 - Flip internally and change the default to false. | |
| documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, | |
| effectTags = {OptionEffectTag.EXECUTION}, | |
| help = | |
| "If set, allow at least one action to run even if the resource is not enough or" | |
| + " unavailable.") | |
| public abstract boolean getAllowOneActionOnResourceUnavailable(); | |
| /** | |
| * Accepts a filesystem path, or boolean-like values selecting a default location or disabling the | |
| * log. | |
| */ | |
| public static final class ExecutionLogFileConverter extends Converter.Contextless<PathFragment> | |
| implements BooleanStyleOption { | |
| private static final Converters.BooleanConverter BOOLEAN_CONVERTER = | |
| new Converters.BooleanConverter(); | |
| @Override | |
| @Nullable | |
| public PathFragment convert(String input) { | |
| if (input.isEmpty()) { | |
| return PathFragment.EMPTY_FRAGMENT; | |
| } | |
| try { | |
| return BOOLEAN_CONVERTER.convert(input) ? PathFragment.EMPTY_FRAGMENT : null; | |
| } catch (OptionsParsingException e) { | |
| return new OptionsUtils.PathFragmentConverter().convert(input); | |
| } | |
| } | |
| @Override | |
| public String getTypeDescription() { | |
| return "a path, or a boolean to use the default execution log location"; | |
| } | |
| } | |
| /** An enum for specifying different formats of test output. */ | |
| public enum TestOutputFormat { | |
| /** | |
| * Provide summary output only. NOTE: Functionally this is `NONE`, as `--test_summary` controls | |
| * the summary output. | |
| */ | |
| SUMMARY, | |
| /** Print output from failed tests to the stderr after the test failure. */ | |
| ERRORS, | |
| /** Print output from all tests to the stderr after the test completion. */ | |
| ALL, | |
| /** | |
| * Stream output from tests as they run. Forces tests to be executed sequentially and locally. | |
| */ | |
| STREAMED; | |
| /** Converts to {@link TestOutputFormat}. */ | |
| public static class Converter extends EnumConverter<TestOutputFormat> { | |
| public Converter() { | |
| super(TestOutputFormat.class, "test output"); | |
| } | |
| } | |
| } | |
| /** An enum for specifying different formatting styles of test summaries. */ | |
| public enum TestSummaryFormat { | |
| /** Show all tests that can to completion, but not individual test cases. */ | |
| SHORT, | |
| /** Like "SHORT", but do not show tests that were cached. */ | |
| SHORT_UNCACHED, | |
| /** Like "SHORT", but even shorter: Only failed and flaky tests. */ | |
| TERSE, | |
| /** | |
| * Show all tests (including tests that failed to build), their test cases, and a summary of all | |
| * test cases (passed, skipped, failing). | |
| */ | |
| DETAILED, | |
| /** Like "DETAILED", but only for tests that were not cached. */ | |
| DETAILED_UNCACHED, | |
| /** Do not print summary. */ | |
| NONE, | |
| /** Summarize all test cases (passed, skipped, failing). */ | |
| TESTCASE; | |
| /** Converts to {@link TestSummaryFormat}. */ | |
| public static class Converter extends EnumConverter<TestSummaryFormat> { | |
| public Converter() { | |
| super(TestSummaryFormat.class, "test summary"); | |
| } | |
| } | |
| } | |
| /** Converter for the --flaky_test_attempts option. */ | |
| public static class TestAttemptsConverter extends PerLabelOptions.PerLabelOptionsConverter { | |
| private static final int MIN_VALUE = 1; | |
| private static final int MAX_VALUE = 10; | |
| private void validateInput(String input) throws OptionsParsingException { | |
| if (!Objects.equals(input, "default")) { | |
| int value = Integer.parseInt(input); | |
| if (value < MIN_VALUE) { | |
| throw new OptionsParsingException("'" + input + "' should be >= " + MIN_VALUE); | |
| } else if (value > MAX_VALUE) { | |
| throw new OptionsParsingException("'" + input + "' should be <= " + MAX_VALUE); | |
| } | |
| } | |
| } | |
| @Override | |
| public PerLabelOptions convert(String input) throws OptionsParsingException { | |
| try { | |
| return parseAsInteger(input); | |
| } catch (NumberFormatException ignored) { | |
| return parseAsRegex(input); | |
| } | |
| } | |
| private PerLabelOptions parseAsInteger(String input) | |
| throws NumberFormatException, OptionsParsingException { | |
| validateInput(input); | |
| RegexFilter catchAll = | |
| new RegexFilter(Collections.singletonList(".*"), Collections.<String>emptyList()); | |
| return new PerLabelOptions(catchAll, Collections.singletonList(input)); | |
| } | |
| private PerLabelOptions parseAsRegex(String input) throws OptionsParsingException { | |
| PerLabelOptions testRegexps = super.convert(input); | |
| if (testRegexps.getOptions().size() != 1) { | |
| throw new OptionsParsingException("'" + input + "' has multiple runs for a single pattern"); | |
| } | |
| String runsPerTest = Iterables.getOnlyElement(testRegexps.getOptions()); | |
| try { | |
| // Run this in order to catch errors. | |
| validateInput(runsPerTest); | |
| } catch (NumberFormatException e) { | |
| throw new OptionsParsingException("'" + input + "' has a non-numeric value", e); | |
| } | |
| return testRegexps; | |
| } | |
| @Override | |
| public String getTypeDescription() { | |
| return "a positive integer, the string \"default\", or test_regex@attempts. " | |
| + "This flag may be passed more than once"; | |
| } | |
| } | |
| /** Converter for --local_test_jobs, which takes {@value FLAG_SYNTAX} */ | |
| public static class LocalTestJobsConverter extends ResourceConverter.IntegerConverter { | |
| public LocalTestJobsConverter() throws OptionsParsingException { | |
| super(/* auto= */ () -> 0, /* minValue= */ 0, /* maxValue= */ Integer.MAX_VALUE); | |
| } | |
| } | |
| /** Converter for --subcommands */ | |
| public static class ShowSubcommandsConverter extends BoolOrEnumConverter<ShowSubcommands> { | |
| public ShowSubcommandsConverter() { | |
| super( | |
| ShowSubcommands.class, "subcommand option", ShowSubcommands.TRUE, ShowSubcommands.FALSE); | |
| } | |
| } | |
| /** Converter for options that take a label-to-string-list assignment. */ | |
| protected static class LabelToStringListConverter | |
| extends AssignmentToListOfValuesConverter<Label, String> { | |
| LabelToStringListConverter() { | |
| super(new LabelConverter(), new Converters.StringConverter(), AllowEmptyKeys.NO); | |
| } | |
| @Override | |
| public String getTypeDescription() { | |
| return "a '<Label>=value[,value]' assignment"; | |
| } | |
| } | |
| } |