Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2014 The Bazel Authors. All rights reserved. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 2 | // |
| 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 | package com.google.devtools.build.lib.exec; |
| 15 | |
steinman | 13a628a | 2019-01-09 08:39:32 -0800 | [diff] [blame] | 16 | import com.google.common.collect.ImmutableMap; |
jcater | 2dd46e6 | 2018-02-20 14:00:33 -0800 | [diff] [blame] | 17 | import com.google.common.collect.Iterables; |
tomlu | b5a727a | 2019-08-03 23:06:35 -0700 | [diff] [blame] | 18 | import com.google.devtools.build.lib.actions.ActionExecutionContext; |
ahumesky | be31bb8 | 2018-07-26 13:37:45 -0700 | [diff] [blame] | 19 | import com.google.devtools.build.lib.actions.ActionExecutionContext.ShowSubcommands; |
steinman | 13a628a | 2019-01-09 08:39:32 -0800 | [diff] [blame] | 20 | import com.google.devtools.build.lib.actions.LocalHostCapacity; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 21 | import com.google.devtools.build.lib.actions.ResourceSet; |
jcater | 2dd46e6 | 2018-02-20 14:00:33 -0800 | [diff] [blame] | 22 | import com.google.devtools.build.lib.analysis.config.PerLabelOptions; |
janakr | b77bf3c | 2020-05-19 14:23:57 -0700 | [diff] [blame] | 23 | import com.google.devtools.build.lib.cmdline.Label; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 24 | import com.google.devtools.build.lib.util.OptionsUtils; |
jcater | 2dd46e6 | 2018-02-20 14:00:33 -0800 | [diff] [blame] | 25 | import com.google.devtools.build.lib.util.RegexFilter; |
Googler | 7859ff2 | 2018-12-21 10:12:48 -0800 | [diff] [blame] | 26 | import com.google.devtools.build.lib.util.ResourceConverter; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 27 | import com.google.devtools.build.lib.vfs.PathFragment; |
ahumesky | be31bb8 | 2018-07-26 13:37:45 -0700 | [diff] [blame] | 28 | import com.google.devtools.common.options.BoolOrEnumConverter; |
schmitt | 61e8013 | 2019-11-01 11:38:55 -0700 | [diff] [blame] | 29 | import com.google.devtools.common.options.Converters; |
philwo | 207ac6e | 2019-02-20 12:44:06 -0800 | [diff] [blame] | 30 | import com.google.devtools.common.options.Converters.CommaSeparatedNonEmptyOptionListConverter; |
jcater | d990df5 | 2020-04-07 04:38:15 -0700 | [diff] [blame] | 31 | import com.google.devtools.common.options.EnumConverter; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 32 | import com.google.devtools.common.options.Option; |
ccalvarin | 3bc1547 | 2017-06-27 17:58:35 +0200 | [diff] [blame] | 33 | import com.google.devtools.common.options.OptionDocumentationCategory; |
ccalvarin | c82a197 | 2017-07-17 21:13:39 +0200 | [diff] [blame] | 34 | import com.google.devtools.common.options.OptionEffectTag; |
philwo | 849113c | 2019-02-20 15:09:30 -0800 | [diff] [blame] | 35 | import com.google.devtools.common.options.OptionMetadataTag; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 36 | import com.google.devtools.common.options.Options; |
| 37 | import com.google.devtools.common.options.OptionsBase; |
jcater | 2dd46e6 | 2018-02-20 14:00:33 -0800 | [diff] [blame] | 38 | import com.google.devtools.common.options.OptionsParsingException; |
jcater | 2dd46e6 | 2018-02-20 14:00:33 -0800 | [diff] [blame] | 39 | import java.util.Collections; |
| 40 | import java.util.List; |
philwo | 784557b | 2019-01-04 05:33:12 -0800 | [diff] [blame] | 41 | import java.util.Map; |
janakr | b77bf3c | 2020-05-19 14:23:57 -0700 | [diff] [blame] | 42 | import java.util.function.Predicate; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 43 | |
| 44 | /** |
| 45 | * Options affecting the execution phase of a build. |
| 46 | * |
Googler | c023bc2 | 2015-03-20 16:26:08 +0000 | [diff] [blame] | 47 | * These options are interpreted by the BuildTool to choose an Executor to |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 48 | * be used for the build. |
| 49 | * |
Googler | c023bc2 | 2015-03-20 16:26:08 +0000 | [diff] [blame] | 50 | * Note: from the user's point of view, the characteristic function of this |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 51 | * set of options is indistinguishable from that of the BuildRequestOptions: |
| 52 | * they are all per-request. The difference is only apparent in the |
| 53 | * implementation: these options are used only by the lib.exec machinery, which |
| 54 | * affects how C++ and Java compilation occur. (The BuildRequestOptions |
| 55 | * contain a mixture of "semantic" options affecting the choice of targets to |
| 56 | * build, and "non-semantic" options affecting the lib.actions machinery.) |
| 57 | * Ideally, the user would be unaware of the difference. For now, the usage |
| 58 | * strings are identical modulo "part 1", "part 2". |
| 59 | */ |
| 60 | public class ExecutionOptions extends OptionsBase { |
| 61 | |
| 62 | public static final ExecutionOptions DEFAULTS = Options.getDefaults(ExecutionOptions.class); |
| 63 | |
ccalvarin | 2eaa02e | 2017-04-17 23:37:46 +0200 | [diff] [blame] | 64 | @Option( |
philwo | 784557b | 2019-01-04 05:33:12 -0800 | [diff] [blame] | 65 | name = "spawn_strategy", |
| 66 | defaultValue = "", |
philwo | 207ac6e | 2019-02-20 12:44:06 -0800 | [diff] [blame] | 67 | converter = CommaSeparatedNonEmptyOptionListConverter.class, |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 68 | documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, |
| 69 | effectTags = {OptionEffectTag.EXECUTION}, |
philwo | 784557b | 2019-01-04 05:33:12 -0800 | [diff] [blame] | 70 | help = |
ishikhman | 21c313c | 2019-09-26 07:14:09 -0700 | [diff] [blame] | 71 | "Specify how spawn actions are executed by default. Accepts a comma-separated list of" |
| 72 | + " strategies from highest to lowest priority. For each action Bazel picks the" |
| 73 | + " strategy with the highest priority that can execute the action. The default" |
wyv | fe1c9cc | 2020-05-19 04:46:43 -0700 | [diff] [blame] | 74 | + " value is \"remote,worker,sandboxed,local\". See" |
ishikhman | 21c313c | 2019-09-26 07:14:09 -0700 | [diff] [blame] | 75 | + " https://blog.bazel.build/2019/06/19/list-strategy.html for details.") |
philwo | 207ac6e | 2019-02-20 12:44:06 -0800 | [diff] [blame] | 76 | public List<String> spawnStrategy; |
philwo | 784557b | 2019-01-04 05:33:12 -0800 | [diff] [blame] | 77 | |
| 78 | @Option( |
| 79 | name = "genrule_strategy", |
| 80 | defaultValue = "", |
philwo | 849113c | 2019-02-20 15:09:30 -0800 | [diff] [blame] | 81 | converter = CommaSeparatedNonEmptyOptionListConverter.class, |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 82 | documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, |
| 83 | effectTags = {OptionEffectTag.EXECUTION}, |
philwo | 784557b | 2019-01-04 05:33:12 -0800 | [diff] [blame] | 84 | help = |
| 85 | "Specify how to execute genrules. This flag will be phased out. Instead, use " |
| 86 | + "--spawn_strategy=<value> to control all actions or --strategy=Genrule=<value> " |
| 87 | + "to control genrules only.") |
philwo | 207ac6e | 2019-02-20 12:44:06 -0800 | [diff] [blame] | 88 | public List<String> genruleStrategy; |
philwo | 784557b | 2019-01-04 05:33:12 -0800 | [diff] [blame] | 89 | |
| 90 | @Option( |
| 91 | name = "strategy", |
| 92 | allowMultiple = true, |
schmitt | 61e8013 | 2019-11-01 11:38:55 -0700 | [diff] [blame] | 93 | converter = Converters.StringToStringListConverter.class, |
Googler | ea0c110 | 2020-03-27 09:30:59 -0700 | [diff] [blame] | 94 | defaultValue = "null", |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 95 | documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, |
| 96 | effectTags = {OptionEffectTag.EXECUTION}, |
philwo | 784557b | 2019-01-04 05:33:12 -0800 | [diff] [blame] | 97 | help = |
ishikhman | 21c313c | 2019-09-26 07:14:09 -0700 | [diff] [blame] | 98 | "Specify how to distribute compilation of other spawn actions. Accepts a comma-separated" |
| 99 | + " list of strategies from highest to lowest priority. For each action Bazel picks" |
| 100 | + " the strategy with the highest priority that can execute the action. The default" |
wyv | fe1c9cc | 2020-05-19 04:46:43 -0700 | [diff] [blame] | 101 | + " value is \"remote,worker,sandboxed,local\". See" |
ishikhman | 21c313c | 2019-09-26 07:14:09 -0700 | [diff] [blame] | 102 | + " https://blog.bazel.build/2019/06/19/list-strategy.html for details.") |
philwo | 207ac6e | 2019-02-20 12:44:06 -0800 | [diff] [blame] | 103 | public List<Map.Entry<String, List<String>>> strategy; |
philwo | 784557b | 2019-01-04 05:33:12 -0800 | [diff] [blame] | 104 | |
| 105 | @Option( |
| 106 | name = "strategy_regexp", |
| 107 | allowMultiple = true, |
| 108 | converter = RegexFilterAssignmentConverter.class, |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 109 | documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, |
| 110 | effectTags = {OptionEffectTag.EXECUTION}, |
Googler | ea0c110 | 2020-03-27 09:30:59 -0700 | [diff] [blame] | 111 | defaultValue = "null", |
philwo | 784557b | 2019-01-04 05:33:12 -0800 | [diff] [blame] | 112 | help = |
| 113 | "Override which spawn strategy should be used to execute spawn actions that have " |
| 114 | + "descriptions matching a certain regex_filter. See --per_file_copt for details on" |
| 115 | + "regex_filter matching. " |
| 116 | + "The first regex_filter that matches the description is used. " |
| 117 | + "This option overrides other flags for specifying strategy. " |
| 118 | + "Example: --strategy_regexp=//foo.*\\.cc,-//foo/bar=local means to run actions " |
| 119 | + "using local strategy if their descriptions match //foo.*.cc but not //foo/bar. " |
| 120 | + "Example: --strategy_regexp='Compiling.*/bar=local " |
| 121 | + " --strategy_regexp=Compiling=sandboxed will run 'Compiling //foo/bar/baz' with " |
| 122 | + "the 'local' strategy, but reversing the order would run it with 'sandboxed'. ") |
philwo | 207ac6e | 2019-02-20 12:44:06 -0800 | [diff] [blame] | 123 | public List<Map.Entry<RegexFilter, List<String>>> strategyByRegexp; |
philwo | 784557b | 2019-01-04 05:33:12 -0800 | [diff] [blame] | 124 | |
| 125 | @Option( |
tomlu | 09fe062 | 2018-06-19 12:55:39 -0700 | [diff] [blame] | 126 | name = "materialize_param_files", |
| 127 | defaultValue = "false", |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 128 | documentationCategory = OptionDocumentationCategory.LOGGING, |
| 129 | effectTags = {OptionEffectTag.EXECUTION}, |
tomlu | 09fe062 | 2018-06-19 12:55:39 -0700 | [diff] [blame] | 130 | help = |
janakr | b77bf3c | 2020-05-19 14:23:57 -0700 | [diff] [blame] | 131 | "Writes intermediate parameter files to output tree even when using remote action" |
| 132 | + " execution. Useful when debugging actions. This is implied by --subcommands," |
| 133 | + " --verbose_failures, and --experimental_verbose_failures_filter.") |
tomlu | 09fe062 | 2018-06-19 12:55:39 -0700 | [diff] [blame] | 134 | public boolean materializeParamFiles; |
| 135 | |
felly | 52e607b | 2019-11-20 13:24:05 -0800 | [diff] [blame] | 136 | @Option( |
| 137 | name = "experimental_materialize_param_files_directly", |
| 138 | defaultValue = "false", |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 139 | documentationCategory = OptionDocumentationCategory.LOGGING, |
| 140 | effectTags = {OptionEffectTag.EXECUTION}, |
felly | 52e607b | 2019-11-20 13:24:05 -0800 | [diff] [blame] | 141 | help = "If materializing param files, do so with direct writes to disk.") |
| 142 | public boolean materializeParamFilesDirectly; |
| 143 | |
tomlu | b5a727a | 2019-08-03 23:06:35 -0700 | [diff] [blame] | 144 | public boolean shouldMaterializeParamFiles() { |
janakr | b77bf3c | 2020-05-19 14:23:57 -0700 | [diff] [blame] | 145 | // Implied by --subcommands and verbose_failures |
cushon | 25ef675 | 2020-02-25 11:02:33 -0800 | [diff] [blame] | 146 | return materializeParamFiles |
| 147 | || showSubcommands != ActionExecutionContext.ShowSubcommands.FALSE |
janakr | b77bf3c | 2020-05-19 14:23:57 -0700 | [diff] [blame] | 148 | // Conservatively materialize params files if any failures may be verbose. |
| 149 | // TODO(janakr): Could try to thread action label through to here and only materialize for |
| 150 | // those actions, but seems pretty gnarly. |
| 151 | || hasSomeVerboseFailures(); |
tomlu | b5a727a | 2019-08-03 23:06:35 -0700 | [diff] [blame] | 152 | } |
| 153 | |
tomlu | 09fe062 | 2018-06-19 12:55:39 -0700 | [diff] [blame] | 154 | @Option( |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 155 | name = "verbose_failures", |
| 156 | defaultValue = "false", |
| 157 | documentationCategory = OptionDocumentationCategory.LOGGING, |
| 158 | effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, |
janakr | b77bf3c | 2020-05-19 14:23:57 -0700 | [diff] [blame] | 159 | help = "If any command fails, print out the full command line.") |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 160 | public boolean verboseFailures; |
| 161 | |
ccalvarin | 2eaa02e | 2017-04-17 23:37:46 +0200 | [diff] [blame] | 162 | @Option( |
janakr | b77bf3c | 2020-05-19 14:23:57 -0700 | [diff] [blame] | 163 | name = "experimental_verbose_failures_filter", |
| 164 | defaultValue = "null", |
| 165 | converter = RegexFilter.RegexFilterConverter.class, |
| 166 | documentationCategory = OptionDocumentationCategory.LOGGING, |
| 167 | effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, |
| 168 | help = |
| 169 | "If a command fails, print out the full command line if its label matches the given" |
| 170 | + " regex filter.") |
| 171 | public RegexFilter verboseFailuresFilter; |
| 172 | |
| 173 | public boolean hasSomeVerboseFailures() { |
| 174 | return verboseFailures || verboseFailuresFilter != null; |
| 175 | } |
| 176 | |
| 177 | public Predicate<Label> getVerboseFailuresPredicate() { |
| 178 | return verboseFailures |
| 179 | ? l -> true |
| 180 | : verboseFailuresFilter == null |
| 181 | ? l -> false |
| 182 | : l -> l == null || verboseFailuresFilter.isIncluded(l.getCanonicalForm()); |
| 183 | } |
| 184 | |
| 185 | @Option( |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 186 | name = "subcommands", |
| 187 | abbrev = 's', |
| 188 | defaultValue = "false", |
| 189 | converter = ShowSubcommandsConverter.class, |
| 190 | documentationCategory = OptionDocumentationCategory.LOGGING, |
| 191 | effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, |
| 192 | help = "Display the subcommands executed during a build.") |
ahumesky | be31bb8 | 2018-07-26 13:37:45 -0700 | [diff] [blame] | 193 | public ShowSubcommands showSubcommands; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 194 | |
ccalvarin | 2eaa02e | 2017-04-17 23:37:46 +0200 | [diff] [blame] | 195 | @Option( |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 196 | name = "check_up_to_date", |
| 197 | defaultValue = "false", |
| 198 | documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, |
| 199 | effectTags = {OptionEffectTag.EXECUTION}, |
| 200 | help = |
| 201 | "Don't perform the build, just check if it is up-to-date. If all targets are " |
| 202 | + "up-to-date, the build completes successfully. If any step needs to be executed " |
| 203 | + "an error is reported and the build fails.") |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 204 | public boolean checkUpToDate; |
| 205 | |
ccalvarin | 2eaa02e | 2017-04-17 23:37:46 +0200 | [diff] [blame] | 206 | @Option( |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 207 | name = "check_tests_up_to_date", |
| 208 | defaultValue = "false", |
| 209 | implicitRequirements = {"--check_up_to_date"}, |
| 210 | documentationCategory = OptionDocumentationCategory.TESTING, |
| 211 | effectTags = {OptionEffectTag.EXECUTION}, |
| 212 | help = |
| 213 | "Don't run tests, just check if they are up-to-date. If all tests results are " |
| 214 | + "up-to-date, the testing completes successfully. If any test needs to be built or " |
| 215 | + "executed, an error is reported and the testing fails. This option implies " |
| 216 | + "--check_up_to_date behavior.") |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 217 | public boolean testCheckUpToDate; |
| 218 | |
ccalvarin | 2eaa02e | 2017-04-17 23:37:46 +0200 | [diff] [blame] | 219 | @Option( |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 220 | name = "test_strategy", |
| 221 | defaultValue = "", |
| 222 | documentationCategory = OptionDocumentationCategory.TESTING, |
| 223 | effectTags = {OptionEffectTag.EXECUTION}, |
| 224 | help = "Specifies which strategy to use when running tests.") |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 225 | public String testStrategy; |
| 226 | |
ccalvarin | 2eaa02e | 2017-04-17 23:37:46 +0200 | [diff] [blame] | 227 | @Option( |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 228 | name = "test_keep_going", |
| 229 | defaultValue = "true", |
| 230 | documentationCategory = OptionDocumentationCategory.TESTING, |
| 231 | effectTags = {OptionEffectTag.EXECUTION}, |
| 232 | help = |
| 233 | "When disabled, any non-passing test will cause the entire build to stop. By default " |
| 234 | + "all tests are run, even if some do not pass.") |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 235 | public boolean testKeepGoing; |
| 236 | |
ccalvarin | 2eaa02e | 2017-04-17 23:37:46 +0200 | [diff] [blame] | 237 | @Option( |
twigg | 70ecdf0 | 2020-04-09 08:30:54 -0700 | [diff] [blame] | 238 | name = "flaky_test_attempts", |
| 239 | allowMultiple = true, |
| 240 | defaultValue = "default", |
| 241 | converter = TestAttemptsConverter.class, |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 242 | documentationCategory = OptionDocumentationCategory.TESTING, |
| 243 | effectTags = {OptionEffectTag.EXECUTION}, |
twigg | 70ecdf0 | 2020-04-09 08:30:54 -0700 | [diff] [blame] | 244 | help = |
| 245 | "Each test will be retried up to the specified number of times in case of any test" |
| 246 | + " failure. Tests that required more than one attempt to pass are marked as 'FLAKY'" |
| 247 | + " in the test summary. Normally the value specified is just an integer or the" |
| 248 | + " string 'default'. If an integer, then all tests will be run up to N times. If" |
| 249 | + " 'default', then only a single test attempt will be made for regular tests and" |
| 250 | + " three for tests marked explicitly as flaky by their rule (flaky=1 attribute)." |
| 251 | + " Alternate syntax: regex_filter@flaky_test_attempts. Where flaky_test_attempts is" |
| 252 | + " as above and regex_filter stands for a list of include and exclude regular" |
| 253 | + " expression patterns (Also see --runs_per_test). Example:" |
| 254 | + " --flaky_test_attempts=//foo/.*,-//foo/bar/.*@3 deflakes all tests in //foo/" |
| 255 | + " except those under foo/bar three times. This option can be passed multiple" |
| 256 | + " times. The most recently passed argument that matches takes precedence. If" |
| 257 | + " nothing matches, behavior is as if 'default' above.") |
jcater | 2dd46e6 | 2018-02-20 14:00:33 -0800 | [diff] [blame] | 258 | public List<PerLabelOptions> testAttempts; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 259 | |
ccalvarin | 2eaa02e | 2017-04-17 23:37:46 +0200 | [diff] [blame] | 260 | @Option( |
Dan Fabulich | 1d35ca0 | 2018-07-05 16:08:06 -0700 | [diff] [blame] | 261 | name = "test_tmpdir", |
| 262 | defaultValue = "null", |
| 263 | converter = OptionsUtils.PathFragmentConverter.class, |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 264 | documentationCategory = OptionDocumentationCategory.TESTING, |
Dan Fabulich | 1d35ca0 | 2018-07-05 16:08:06 -0700 | [diff] [blame] | 265 | effectTags = {OptionEffectTag.UNKNOWN}, |
| 266 | help = "Specifies the base temporary directory for 'bazel test' to use.") |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 267 | public PathFragment testTmpDir; |
| 268 | |
ccalvarin | 2eaa02e | 2017-04-17 23:37:46 +0200 | [diff] [blame] | 269 | @Option( |
jcater | d990df5 | 2020-04-07 04:38:15 -0700 | [diff] [blame] | 270 | name = "test_output", |
| 271 | defaultValue = "summary", |
| 272 | converter = TestOutputFormat.Converter.class, |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 273 | documentationCategory = OptionDocumentationCategory.LOGGING, |
| 274 | effectTags = { |
| 275 | OptionEffectTag.TEST_RUNNER, |
| 276 | OptionEffectTag.TERMINAL_OUTPUT, |
| 277 | OptionEffectTag.EXECUTION |
| 278 | }, |
jcater | d990df5 | 2020-04-07 04:38:15 -0700 | [diff] [blame] | 279 | help = |
| 280 | "Specifies desired output mode. Valid values are 'summary' to output only test status " |
| 281 | + "summary, 'errors' to also print test logs for failed tests, 'all' to print logs " |
| 282 | + "for all tests and 'streamed' to output logs for all tests in real time " |
| 283 | + "(this will force tests to be executed locally one at a time regardless of " |
| 284 | + "--test_strategy value).") |
| 285 | public TestOutputFormat testOutput; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 286 | |
ccalvarin | 2eaa02e | 2017-04-17 23:37:46 +0200 | [diff] [blame] | 287 | @Option( |
jcater | d990df5 | 2020-04-07 04:38:15 -0700 | [diff] [blame] | 288 | name = "test_summary", |
| 289 | defaultValue = "short", |
| 290 | converter = TestSummaryFormat.Converter.class, |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 291 | documentationCategory = OptionDocumentationCategory.LOGGING, |
| 292 | effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, |
jcater | d990df5 | 2020-04-07 04:38:15 -0700 | [diff] [blame] | 293 | help = |
| 294 | "Specifies the desired format ot the test summary. Valid values are 'short' to print " |
| 295 | + "information only about tests executed, 'terse', to print information only about " |
| 296 | + "unsuccessful tests that were run, 'detailed' to print detailed information about " |
| 297 | + "failed test cases, and 'none' to omit the summary.") |
| 298 | public TestSummaryFormat testSummary; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 299 | |
ccalvarin | 2eaa02e | 2017-04-17 23:37:46 +0200 | [diff] [blame] | 300 | @Option( |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 301 | name = "resource_autosense", |
| 302 | defaultValue = "false", |
| 303 | documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, |
| 304 | effectTags = {OptionEffectTag.UNKNOWN}, |
| 305 | help = "This flag has no effect, and is deprecated") |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 306 | public boolean useResourceAutoSense; |
| 307 | |
ccalvarin | 2eaa02e | 2017-04-17 23:37:46 +0200 | [diff] [blame] | 308 | @Option( |
Dan Fabulich | 1d35ca0 | 2018-07-05 16:08:06 -0700 | [diff] [blame] | 309 | name = "local_resources", |
| 310 | defaultValue = "null", |
| 311 | documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, |
| 312 | effectTags = {OptionEffectTag.UNKNOWN}, |
| 313 | help = |
steinman | c9dca48 | 2020-02-13 12:05:06 -0800 | [diff] [blame] | 314 | "Deprecated by '--incompatible_remove_local_resources'. Please use " |
| 315 | + "'--local_ram_resources' and '--local_cpu_resources'", |
| 316 | deprecationWarning = |
steinman | 7f530c8 | 2020-04-15 14:13:42 -0700 | [diff] [blame] | 317 | "--local_resources is deprecated. Please use" |
steinman | c9dca48 | 2020-02-13 12:05:06 -0800 | [diff] [blame] | 318 | + " --local_ram_resources and --local_cpu_resources instead.", |
Dan Fabulich | 1d35ca0 | 2018-07-05 16:08:06 -0700 | [diff] [blame] | 319 | converter = ResourceSet.ResourceSetConverter.class) |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 320 | public ResourceSet availableResources; |
Mark Schaller | dffb6ee | 2015-02-25 20:01:01 +0000 | [diff] [blame] | 321 | |
ccalvarin | 2eaa02e | 2017-04-17 23:37:46 +0200 | [diff] [blame] | 322 | @Option( |
steinman | 3501b21 | 2019-03-25 12:36:43 -0700 | [diff] [blame] | 323 | name = "incompatible_remove_local_resources", |
steinman | 765d3c1 | 2020-03-03 08:44:37 -0800 | [diff] [blame] | 324 | defaultValue = "true", |
steinman | 3501b21 | 2019-03-25 12:36:43 -0700 | [diff] [blame] | 325 | documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, |
| 326 | effectTags = {OptionEffectTag.EXECUTION}, |
| 327 | metadataTags = { |
| 328 | OptionMetadataTag.INCOMPATIBLE_CHANGE, |
| 329 | OptionMetadataTag.TRIGGERED_BY_ALL_INCOMPATIBLE_CHANGES |
| 330 | }, |
| 331 | help = |
| 332 | "Deprecate local_resources in favor of --local_ram_resources and " |
| 333 | + "--local_cpu_resources.") |
| 334 | public boolean removeLocalResources; |
| 335 | |
| 336 | @Option( |
steinman | 13a628a | 2019-01-09 08:39:32 -0800 | [diff] [blame] | 337 | name = "local_cpu_resources", |
| 338 | defaultValue = "HOST_CPUS", |
| 339 | documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, |
| 340 | effectTags = {OptionEffectTag.UNKNOWN}, |
| 341 | help = |
| 342 | "Explicitly set the number of local CPU threads available to Bazel. Takes " |
| 343 | + "an integer, or \"HOST_CPUS\", optionally followed by [-|*]<float> " |
| 344 | + "(eg. HOST_CPUS*.5 to use half the available CPU cores)." |
| 345 | + "By default, (\"HOST_CPUS\"), Bazel will query system configuration to estimate " |
| 346 | + "number of CPU cores available for the locally executed build actions. " |
| 347 | + "Note: This is a no-op if --local_resources is set.", |
| 348 | converter = CpuResourceConverter.class) |
| 349 | public float localCpuResources; |
| 350 | |
| 351 | @Option( |
| 352 | name = "local_ram_resources", |
| 353 | defaultValue = "HOST_RAM*.67", |
| 354 | documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, |
| 355 | effectTags = {OptionEffectTag.UNKNOWN}, |
| 356 | help = |
| 357 | "Explicitly set the amount of local host RAM (in MB) available to Bazel. Takes " |
| 358 | + "an integer, or \"HOST_RAM\", optionally followed by [-|*]<float> " |
| 359 | + "(eg. HOST_RAM*.5 to use half the available RAM)." |
| 360 | + "By default, (\"HOST_RAM*.67\"), Bazel will query system configuration to estimate " |
| 361 | + "amount of RAM available for the locally executed build actions and will use 67% " |
| 362 | + "of available RAM. " |
steinman | 7f530c8 | 2020-04-15 14:13:42 -0700 | [diff] [blame] | 363 | + "Note: This is a no-op if --local_resources is set.", |
steinman | 13a628a | 2019-01-09 08:39:32 -0800 | [diff] [blame] | 364 | converter = RamResourceConverter.class) |
| 365 | public float localRamResources; |
| 366 | |
| 367 | @Option( |
Josh Pieper | 7f3bddd | 2018-05-04 00:39:37 -0700 | [diff] [blame] | 368 | name = "experimental_local_memory_estimate", |
| 369 | defaultValue = "false", |
| 370 | documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, |
| 371 | effectTags = {OptionEffectTag.UNKNOWN}, |
| 372 | help = |
| 373 | "Estimate the actual memory available online. " |
| 374 | + "By default, Blaze assumes most actions use a fixed amount of memory, and counts " |
| 375 | + "that against the total available system memory, regardless of how much memory is " |
| 376 | + "actually available. This option enables online estimation of how much memory is " |
| 377 | + "available at any given time, and thus does not require accurate estimation of how " |
| 378 | + "much memory a given action will take." |
| 379 | ) |
| 380 | public boolean localMemoryEstimate; |
| 381 | |
| 382 | @Option( |
Googler | 7859ff2 | 2018-12-21 10:12:48 -0800 | [diff] [blame] | 383 | name = "local_test_jobs", |
| 384 | defaultValue = "auto", |
jingwen | 1329798 | 2020-04-24 14:01:19 -0700 | [diff] [blame] | 385 | documentationCategory = OptionDocumentationCategory.TESTING, |
| 386 | effectTags = {OptionEffectTag.EXECUTION}, |
Googler | 7859ff2 | 2018-12-21 10:12:48 -0800 | [diff] [blame] | 387 | help = |
| 388 | "The max number of local test jobs to run concurrently. " |
| 389 | + "Takes " |
| 390 | + ResourceConverter.FLAG_SYNTAX |
| 391 | + ". 0 means local resources will limit the number of local test jobs to run " |
| 392 | + "concurrently instead. Setting this greater than the value for --jobs " |
| 393 | + "is ineffectual.", |
| 394 | converter = LocalTestJobsConverter.class) |
Mark Schaller | dffb6ee | 2015-02-25 20:01:01 +0000 | [diff] [blame] | 395 | public int localTestJobs; |
| 396 | |
| 397 | public boolean usingLocalTestJobs() { |
| 398 | return localTestJobs != 0; |
| 399 | } |
Philipp Wollermann | 4ca5dfa | 2017-02-01 13:45:55 +0000 | [diff] [blame] | 400 | |
| 401 | @Option( |
| 402 | name = "debug_print_action_contexts", |
| 403 | defaultValue = "false", |
ccalvarin | 456adb2 | 2017-07-11 14:23:46 +0200 | [diff] [blame] | 404 | documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, |
ccalvarin | 3bc1547 | 2017-06-27 17:58:35 +0200 | [diff] [blame] | 405 | effectTags = {OptionEffectTag.UNKNOWN}, |
Philipp Wollermann | 4ca5dfa | 2017-02-01 13:45:55 +0000 | [diff] [blame] | 406 | help = "Print the contents of the SpawnActionContext and ContextProviders maps." |
| 407 | ) |
| 408 | public boolean debugPrintActionContexts; |
Julio Merino | 7ac6d59 | 2017-03-16 19:12:32 +0000 | [diff] [blame] | 409 | |
| 410 | @Option( |
Dan Fabulich | 1d35ca0 | 2018-07-05 16:08:06 -0700 | [diff] [blame] | 411 | name = "cache_computed_file_digests", |
| 412 | defaultValue = "50000", |
| 413 | documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, |
| 414 | effectTags = {OptionEffectTag.UNKNOWN}, |
| 415 | help = |
| 416 | "If greater than 0, configures Bazel to cache file digests in memory based on their " |
| 417 | + "metadata instead of recomputing the digests from disk every time they are needed. " |
| 418 | + "Setting this to 0 ensures correctness because not all file changes can be noted " |
| 419 | + "from file metadata. When not 0, the number indicates the size of the cache as the " |
| 420 | + "number of file digests to be cached.") |
Julio Merino | 7ac6d59 | 2017-03-16 19:12:32 +0000 | [diff] [blame] | 421 | public long cacheSizeForComputedFileDigests; |
janakr | 1fb90fd | 2017-03-30 21:07:04 +0000 | [diff] [blame] | 422 | |
janakr | 1fb90fd | 2017-03-30 21:07:04 +0000 | [diff] [blame] | 423 | @Option( |
| 424 | name = "experimental_enable_critical_path_profiling", |
| 425 | defaultValue = "true", |
ccalvarin | 456adb2 | 2017-07-11 14:23:46 +0200 | [diff] [blame] | 426 | documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, |
ccalvarin | 3bc1547 | 2017-06-27 17:58:35 +0200 | [diff] [blame] | 427 | effectTags = {OptionEffectTag.UNKNOWN}, |
janakr | 1fb90fd | 2017-03-30 21:07:04 +0000 | [diff] [blame] | 428 | help = |
| 429 | "If set (the default), critical path profiling is enabled for the execution phase. " |
| 430 | + "This has a slight overhead in RAM and CPU, and may prevent Bazel from making certain" |
| 431 | + " aggressive RAM optimizations in some cases." |
| 432 | ) |
| 433 | public boolean enableCriticalPathProfiling; |
jcater | 2dd46e6 | 2018-02-20 14:00:33 -0800 | [diff] [blame] | 434 | |
olaola | 913b66c | 2018-04-19 10:43:53 -0700 | [diff] [blame] | 435 | @Option( |
ulfjack | 97a3ee4 | 2018-11-20 05:40:35 -0800 | [diff] [blame] | 436 | name = "experimental_stats_summary", |
| 437 | documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, |
| 438 | effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, |
| 439 | defaultValue = "false", |
| 440 | help = "Enable a modernized summary of the build stats." |
| 441 | ) |
| 442 | public boolean statsSummary; |
| 443 | |
| 444 | @Option( |
Googler | d03d3f3 | 2019-04-16 08:06:23 -0700 | [diff] [blame] | 445 | name = "experimental_execution_log_file", |
| 446 | defaultValue = "null", |
| 447 | category = "verbosity", |
| 448 | documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, |
| 449 | effectTags = {OptionEffectTag.UNKNOWN}, |
| 450 | converter = OptionsUtils.PathFragmentConverter.class, |
| 451 | help = "Log the executed spawns into this file as delimited Spawn protos.") |
| 452 | public PathFragment executionLogFile; |
| 453 | |
| 454 | @Option( |
| 455 | name = "execution_log_binary_file", |
| 456 | defaultValue = "null", |
| 457 | category = "verbosity", |
| 458 | documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, |
| 459 | effectTags = {OptionEffectTag.UNKNOWN}, |
| 460 | converter = OptionsUtils.PathFragmentConverter.class, |
| 461 | help = "Log the executed spawns into this file as delimited Spawn protos.") |
| 462 | public PathFragment executionLogBinaryFile; |
| 463 | |
| 464 | @Option( |
| 465 | name = "execution_log_json_file", |
| 466 | defaultValue = "null", |
| 467 | category = "verbosity", |
| 468 | documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, |
| 469 | effectTags = {OptionEffectTag.UNKNOWN}, |
| 470 | converter = OptionsUtils.PathFragmentConverter.class, |
| 471 | help = |
| 472 | "Log the executed spawns into this file as json representation of the delimited Spawn" |
| 473 | + " protos.") |
| 474 | public PathFragment executionLogJsonFile; |
olaola | 913b66c | 2018-04-19 10:43:53 -0700 | [diff] [blame] | 475 | |
ulfjack | 0858ae1 | 2018-07-27 02:37:53 -0700 | [diff] [blame] | 476 | @Option( |
ulfjack | 6da8982 | 2019-02-04 13:06:34 -0800 | [diff] [blame] | 477 | name = "experimental_split_xml_generation", |
| 478 | defaultValue = "true", |
| 479 | documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, |
| 480 | effectTags = {OptionEffectTag.EXECUTION}, |
| 481 | help = |
| 482 | "If this flag is set, and a test action does not generate a test.xml file, then " |
| 483 | + "Bazel uses a separate action to generate a dummy test.xml file containing the " |
| 484 | + "test log. Otherwise, Bazel generates a test.xml as part of the test action.") |
ulfjack | 0858ae1 | 2018-07-27 02:37:53 -0700 | [diff] [blame] | 485 | public boolean splitXmlGeneration; |
| 486 | |
jcater | d990df5 | 2020-04-07 04:38:15 -0700 | [diff] [blame] | 487 | /** An enum for specifying different formats of test output. */ |
| 488 | public enum TestOutputFormat { |
| 489 | SUMMARY, // Provide summary output only. |
| 490 | ERRORS, // Print output from failed tests to the stderr after the test failure. |
| 491 | ALL, // Print output from all tests to the stderr after the test completion. |
| 492 | STREAMED; // Stream output for each test. |
| 493 | |
| 494 | /** Converts to {@link TestOutputFormat}. */ |
| 495 | public static class Converter extends EnumConverter<TestOutputFormat> { |
| 496 | public Converter() { |
| 497 | super(TestOutputFormat.class, "test output"); |
| 498 | } |
| 499 | } |
| 500 | } |
| 501 | |
| 502 | /** An enum for specifying different formatting styles of test summaries. */ |
| 503 | public enum TestSummaryFormat { |
| 504 | SHORT, // Print information only about tests. |
| 505 | TERSE, // Like "SHORT", but even shorter: Do not print PASSED and NO STATUS tests. |
| 506 | DETAILED, // Print information only about failed test cases. |
| 507 | NONE, // Do not print summary. |
| 508 | TESTCASE; // Print summary in test case resolution, do not print detailed information about |
| 509 | // failed test cases. |
| 510 | |
| 511 | /** Converts to {@link TestSummaryFormat}. */ |
| 512 | public static class Converter extends EnumConverter<TestSummaryFormat> { |
| 513 | public Converter() { |
| 514 | super(TestSummaryFormat.class, "test summary"); |
| 515 | } |
| 516 | } |
| 517 | } |
| 518 | |
jcater | 2dd46e6 | 2018-02-20 14:00:33 -0800 | [diff] [blame] | 519 | /** Converter for the --flaky_test_attempts option. */ |
| 520 | public static class TestAttemptsConverter extends PerLabelOptions.PerLabelOptionsConverter { |
| 521 | private static final int MIN_VALUE = 1; |
| 522 | private static final int MAX_VALUE = 10; |
| 523 | |
| 524 | private void validateInput(String input) throws OptionsParsingException { |
| 525 | if ("default".equals(input)) { |
| 526 | return; |
| 527 | } else { |
| 528 | Integer value = Integer.parseInt(input); |
| 529 | if (value < MIN_VALUE) { |
| 530 | throw new OptionsParsingException("'" + input + "' should be >= " + MIN_VALUE); |
| 531 | } else if (value < MIN_VALUE || value > MAX_VALUE) { |
| 532 | throw new OptionsParsingException("'" + input + "' should be <= " + MAX_VALUE); |
| 533 | } |
| 534 | return; |
| 535 | } |
| 536 | } |
| 537 | |
| 538 | @Override |
| 539 | public PerLabelOptions convert(String input) throws OptionsParsingException { |
| 540 | try { |
| 541 | return parseAsInteger(input); |
| 542 | } catch (NumberFormatException ignored) { |
| 543 | return parseAsRegex(input); |
| 544 | } |
| 545 | } |
| 546 | |
| 547 | private PerLabelOptions parseAsInteger(String input) |
| 548 | throws NumberFormatException, OptionsParsingException { |
| 549 | validateInput(input); |
| 550 | RegexFilter catchAll = |
| 551 | new RegexFilter(Collections.singletonList(".*"), Collections.<String>emptyList()); |
| 552 | return new PerLabelOptions(catchAll, Collections.singletonList(input)); |
| 553 | } |
| 554 | |
| 555 | private PerLabelOptions parseAsRegex(String input) throws OptionsParsingException { |
| 556 | PerLabelOptions testRegexps = super.convert(input); |
| 557 | if (testRegexps.getOptions().size() != 1) { |
| 558 | throw new OptionsParsingException("'" + input + "' has multiple runs for a single pattern"); |
| 559 | } |
| 560 | String runsPerTest = Iterables.getOnlyElement(testRegexps.getOptions()); |
| 561 | try { |
| 562 | // Run this in order to catch errors. |
| 563 | validateInput(runsPerTest); |
| 564 | } catch (NumberFormatException e) { |
| 565 | throw new OptionsParsingException("'" + input + "' has a non-numeric value", e); |
| 566 | } |
| 567 | return testRegexps; |
| 568 | } |
| 569 | |
| 570 | @Override |
| 571 | public String getTypeDescription() { |
| 572 | return "a positive integer, the string \"default\", or test_regex@attempts. " |
| 573 | + "This flag may be passed more than once"; |
| 574 | } |
| 575 | } |
ahumesky | be31bb8 | 2018-07-26 13:37:45 -0700 | [diff] [blame] | 576 | |
Googler | 7859ff2 | 2018-12-21 10:12:48 -0800 | [diff] [blame] | 577 | /** Converter for --local_test_jobs, which takes {@value FLAG_SYNTAX} */ |
| 578 | public static class LocalTestJobsConverter extends ResourceConverter { |
| 579 | public LocalTestJobsConverter() throws OptionsParsingException { |
| 580 | super(/* autoSupplier= */ () -> 0, /* minValue= */ 0, /* maxValue= */ Integer.MAX_VALUE); |
| 581 | } |
| 582 | } |
| 583 | |
ahumesky | be31bb8 | 2018-07-26 13:37:45 -0700 | [diff] [blame] | 584 | /** Converter for --subcommands */ |
| 585 | public static class ShowSubcommandsConverter extends BoolOrEnumConverter<ShowSubcommands> { |
| 586 | public ShowSubcommandsConverter() { |
| 587 | super( |
| 588 | ShowSubcommands.class, "subcommand option", ShowSubcommands.TRUE, ShowSubcommands.FALSE); |
| 589 | } |
| 590 | } |
| 591 | |
steinman | 13a628a | 2019-01-09 08:39:32 -0800 | [diff] [blame] | 592 | /** |
| 593 | * Converter for --local_cpu_resources, which takes an integer greater than or equal to 1, or |
| 594 | * "HOST_CPUS", optionally followed by [-|*]<float>. |
| 595 | */ |
| 596 | public static class CpuResourceConverter extends ResourceConverter { |
| 597 | public CpuResourceConverter() { |
| 598 | super( |
| 599 | ImmutableMap.of( |
| 600 | "HOST_CPUS", |
| 601 | () -> (int) Math.ceil(LocalHostCapacity.getLocalHostCapacity().getCpuUsage())), |
| 602 | 1, |
| 603 | Integer.MAX_VALUE); |
| 604 | } |
| 605 | |
| 606 | @Override |
| 607 | public String getTypeDescription() { |
| 608 | return "an integer, or \"HOST_CPUS\", optionally followed by [-|*]<float>."; |
| 609 | } |
| 610 | } |
| 611 | |
| 612 | /** |
| 613 | * Converter for --local_cpu_resources, which takes an integer greater than or equal to 1, or |
| 614 | * "HOST_RAM", optionally followed by [-|*]<float>. |
| 615 | */ |
| 616 | public static class RamResourceConverter extends ResourceConverter { |
| 617 | public RamResourceConverter() { |
| 618 | super( |
| 619 | ImmutableMap.of( |
| 620 | "HOST_RAM", |
lberki | f1e5e87 | 2019-05-23 08:11:58 -0700 | [diff] [blame] | 621 | () -> (int) Math.ceil(LocalHostCapacity.getLocalHostCapacity().getMemoryMb())), |
steinman | 13a628a | 2019-01-09 08:39:32 -0800 | [diff] [blame] | 622 | 1, |
| 623 | Integer.MAX_VALUE); |
| 624 | } |
| 625 | |
| 626 | @Override |
| 627 | public String getTypeDescription() { |
| 628 | return "an integer, or \"HOST_RAM\", optionally followed by [-|*]<float>."; |
| 629 | } |
| 630 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 631 | } |