blob: a76e088eda46ce71d7013ef2d246be0940e2203a [file] [log] [blame]
// Copyright 2017 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.buildtool;
import com.github.benmanes.caffeine.cache.CaffeineSpec;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.flogger.GoogleLogger;
import com.google.devtools.build.lib.util.OptionsUtils;
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.Converters;
import com.google.devtools.common.options.Converters.CaffeineSpecConverter;
import com.google.devtools.common.options.Converters.PercentageConverter;
import com.google.devtools.common.options.Converters.RangeConverter;
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.OptionMetadataTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParsingException;
import com.google.devtools.common.options.RegexPatternOption;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
/**
* Options interface for {@link BuildRequest}: can be used to parse command-line arguments.
*
* <p>See also {@code ExecutionOptions}; from the user's point of view, there's no qualitative
* difference between these two sets of options.
*/
public class BuildRequestOptions extends OptionsBase {
private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
private static final int JOBS_TOO_HIGH_WARNING = 2500;
@VisibleForTesting public static final int MAX_JOBS = 5000;
/* "Execution": options related to the execution of a build: */
@Option(
name = "jobs",
abbrev = 'j',
defaultValue = "auto",
documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
effectTags = {OptionEffectTag.HOST_MACHINE_RESOURCE_OPTIMIZATIONS, OptionEffectTag.EXECUTION},
converter = JobsConverter.class,
help =
"The number of concurrent jobs to run. Takes "
+ ResourceConverter.FLAG_SYNTAX
+ ". Values must be between 1 and "
+ MAX_JOBS
+ ". Values above "
+ JOBS_TOO_HIGH_WARNING
+ " may cause memory issues. \"auto\" calculates a reasonable default based on"
+ " host resources.")
public int jobs;
@Option(
name = "experimental_use_semaphore_for_jobs",
defaultValue = "true",
documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
effectTags = {OptionEffectTag.HOST_MACHINE_RESOURCE_OPTIMIZATIONS, OptionEffectTag.EXECUTION},
help = "If set to true, additionally use semaphore to limit number of concurrent jobs.")
public boolean useSemaphoreForJobs;
@Option(
name = "experimental_async_execution",
defaultValue = "false",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
metadataTags = OptionMetadataTag.INCOMPATIBLE_CHANGE,
effectTags = {OptionEffectTag.BAZEL_INTERNAL_CONFIGURATION},
help =
"If set to true, Bazel is allowed to run action in a virtual thread. The number of"
+ " actions in flight is still capped with --jobs.")
public boolean useAsyncExecution;
@Option(
name = "progress_report_interval",
defaultValue = "0",
documentationCategory = OptionDocumentationCategory.LOGGING,
effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
converter = ProgressReportIntervalConverter.class,
help =
"The number of seconds to wait between reports on still running jobs. The "
+ "default value 0 means the first report will be printed after 10 "
+ "seconds, then 30 seconds and after that progress is reported once every minute. "
+ "When --curses is enabled, progress is reported every second.")
public int progressReportInterval;
@Option(
name = "explain",
defaultValue = "null",
documentationCategory = OptionDocumentationCategory.LOGGING,
effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
converter = OptionsUtils.PathFragmentConverter.class,
help =
"Causes the build system to explain each executed step of the "
+ "build. The explanation is written to the specified log file.")
public PathFragment explanationPath;
@Option(
name = "verbose_explanations",
defaultValue = "false",
documentationCategory = OptionDocumentationCategory.LOGGING,
effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
help =
"Increases the verbosity of the explanations issued if --explain is enabled. "
+ "Has no effect if --explain is not enabled.")
public boolean verboseExplanations;
@Option(
name = "output_filter",
converter = Converters.RegexPatternConverter.class,
defaultValue = "null",
documentationCategory = OptionDocumentationCategory.LOGGING,
effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
help =
"Only shows warnings and action outputs for rules with a name matching the provided "
+ "regular expression.")
@Nullable
public RegexPatternOption outputFilter;
@Option(
name = "analyze",
defaultValue = "true",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
effectTags = {OptionEffectTag.LOADING_AND_ANALYSIS, OptionEffectTag.AFFECTS_OUTPUTS},
help =
"Execute the loading/analysis phase; this is the usual behaviour. Specifying --noanalyze"
+ "causes the build to stop before starting the loading/analysis phase, just doing "
+ "target pattern parsing and returning zero iff that completed successfully; this "
+ "mode is useful for testing.")
public boolean performAnalysisPhase;
@Option(
name = "build",
defaultValue = "true",
documentationCategory = OptionDocumentationCategory.OUTPUT_SELECTION,
effectTags = {OptionEffectTag.EXECUTION, OptionEffectTag.AFFECTS_OUTPUTS},
help =
"Execute the build; this is the usual behaviour. "
+ "Specifying --nobuild causes the build to stop before executing the build "
+ "actions, returning zero iff the package loading and analysis phases completed "
+ "successfully; this mode is useful for testing those phases.")
public boolean performExecutionPhase;
@Option(
name = "output_groups",
converter = Converters.CommaSeparatedOptionListConverter.class,
allowMultiple = true,
documentationCategory = OptionDocumentationCategory.OUTPUT_SELECTION,
effectTags = {OptionEffectTag.EXECUTION, OptionEffectTag.AFFECTS_OUTPUTS},
defaultValue = "null",
help =
"A list of comma-separated output group names, each of which optionally prefixed by a +"
+ " or a -. A group prefixed by + is added to the default set of output groups,"
+ " while a group prefixed by - is removed from the default set. If at least one"
+ " group is not prefixed, the default set of output groups is omitted. For example,"
+ " --output_groups=+foo,+bar builds the union of the default set, foo, and bar,"
+ " while --output_groups=foo,bar overrides the default set such that only foo and"
+ " bar are built.")
public List<String> outputGroups;
@Option(
name = "run_validations",
oldName = "experimental_run_validations",
defaultValue = "true",
documentationCategory = OptionDocumentationCategory.OUTPUT_SELECTION,
effectTags = {OptionEffectTag.EXECUTION, OptionEffectTag.AFFECTS_OUTPUTS},
help =
"Whether to run validation actions as part of the build. See"
+ " https://bazel.build/extending/rules#validation_actions")
public boolean runValidationActions;
@Option(
name = "experimental_use_validation_aspect",
defaultValue = "false",
documentationCategory = OptionDocumentationCategory.OUTPUT_SELECTION,
effectTags = {OptionEffectTag.EXECUTION, OptionEffectTag.AFFECTS_OUTPUTS},
help = "Whether to run validation actions using aspect (for parallelism with tests).")
public boolean useValidationAspect;
@Option(
name = "show_result",
defaultValue = "1",
documentationCategory = OptionDocumentationCategory.LOGGING,
effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
help =
"Show the results of the build. For each target, state whether or not it was brought"
+ " up-to-date, and if so, a list of output files that were built. The printed files"
+ " are convenient strings for copy+pasting to the shell, to execute them.\n"
+ "This option requires an integer argument, which is the threshold number of targets"
+ " above which result information is not printed. Thus zero causes suppression of"
+ " the message and MAX_INT causes printing of the result to occur always. The"
+ " default is one.\n"
+ "If nothing was built for a target its results may be omitted to keep the output"
+ " under the threshold.")
public int maxResultTargets;
@Option(
name = "hide_aspect_results",
converter = Converters.CommaSeparatedOptionListConverter.class,
defaultValue = "",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
effectTags = {OptionEffectTag.TERMINAL_OUTPUT},
help =
"Comma-separated list of aspect names to not display in results (see --show_result). "
+ "Useful for keeping aspects added by wrappers which are typically not interesting "
+ "to end users out of console output.")
public List<String> hideAspectResults;
@Option(
name = "symlink_prefix",
defaultValue = "null",
documentationCategory = OptionDocumentationCategory.OUTPUT_PARAMETERS,
effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
help =
"The prefix that is prepended to any of the convenience symlinks that are created "
+ "after a build. If omitted, the default value is the name of the build tool "
+ "followed by a hyphen. If '/' is passed, then no symlinks are created and no "
+ "warning is emitted. Warning: the special functionality for '/' will be deprecated "
+ "soon; use --experimental_convenience_symlinks=ignore instead.")
@Nullable
public String symlinkPrefix;
@Option(
name = "experimental_convenience_symlinks",
converter = ConvenienceSymlinksConverter.class,
defaultValue = "normal",
documentationCategory = OptionDocumentationCategory.OUTPUT_PARAMETERS,
effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
help =
"This flag controls how the convenience symlinks (the symlinks that appear in the "
+ "workspace after the build) will be managed. Possible values:\n"
+ " normal (default): Each kind of convenience symlink will be created or deleted, "
+ "as determined by the build.\n"
+ " clean: All symlinks will be unconditionally deleted.\n"
+ " ignore: Symlinks will not be created or cleaned up.\n"
+ " log_only: Generate log messages as if 'normal' were passed, but don't actually "
+ "perform any filesystem operations (useful for tools).\n"
+ "Note that only symlinks whose names are generated by the current value of "
+ "--symlink_prefix can be affected; if the prefix changes, any pre-existing "
+ "symlinks will be left alone.")
@Nullable
public ConvenienceSymlinksMode experimentalConvenienceSymlinks;
@Option(
name = "experimental_convenience_symlinks_bep_event",
defaultValue = "true",
documentationCategory = OptionDocumentationCategory.OUTPUT_PARAMETERS,
effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
help =
"This flag controls whether or not we will post the build event"
+ "ConvenienceSymlinksIdentified to the BuildEventProtocol. If the value is true, "
+ "the BuildEventProtocol will have an entry for convenienceSymlinksIdentified, "
+ "listing all of the convenience symlinks created in your workspace. If false, then "
+ "the convenienceSymlinksIdentified entry in the BuildEventProtocol will be empty.")
public boolean experimentalConvenienceSymlinksBepEvent;
@Option(
name = "output_tree_tracking",
oldName = "experimental_output_tree_tracking",
defaultValue = "true",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
effectTags = {OptionEffectTag.BAZEL_INTERNAL_CONFIGURATION},
help =
"If set, tell the output service (if any) to track when files in the output "
+ "tree have been modified externally (not by the build system). "
+ "This should improve incremental build speed when an appropriate output service "
+ "is enabled.")
public boolean finalizeActions;
@Option(
name = "directory_creation_cache",
defaultValue = "maximumSize=100000",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
effectTags = {OptionEffectTag.EXECUTION},
converter = CaffeineSpecConverter.class,
help =
"Describes the cache used to store known regular directories as they're created. Parent"
+ " directories of output files are created on-demand during action execution.")
public CaffeineSpec directoryCreationCacheSpec;
@Option(
name = "aspects",
converter = Converters.CommaSeparatedOptionListConverter.class,
defaultValue = "null",
documentationCategory = OptionDocumentationCategory.OUTPUT_PARAMETERS,
effectTags = {OptionEffectTag.UNKNOWN},
allowMultiple = true,
help =
"Comma-separated list of aspects to be applied to top-level targets. In the list, if"
+ " aspect some_aspect specifies required aspect providers via"
+ " required_aspect_providers, some_aspect will run after"
+ " every aspect that was mentioned before it in the aspects list whose advertised"
+ " providers satisfy some_aspect required aspect providers. Moreover,"
+ " some_aspect will run after all its required aspects specified by"
+ " requires attribute."
+ " some_aspect will then have access to the values of those aspects'"
+ " providers."
+ " <bzl-file-label>%<aspect_name>, for example '//tools:my_def.bzl%my_aspect', where"
+ " 'my_aspect' is a top-level value from a file tools/my_def.bzl")
public List<String> aspects;
@Option(
name = "aspects_parameters",
converter = Converters.AssignmentConverter.class,
defaultValue = "null",
documentationCategory = OptionDocumentationCategory.GENERIC_INPUTS,
effectTags = {OptionEffectTag.LOADING_AND_ANALYSIS},
allowMultiple = true,
help =
"Specifies the values of the command-line aspects parameters. Each parameter value is"
+ " specified via <param_name>=<param_value>, for example 'my_param=my_val' where"
+ " 'my_param' is a parameter of some aspect in --aspects list or required by an"
+ " aspect in the list. This option can be used multiple times. However, it is not"
+ " allowed to assign values to the same parameter more than once.")
public List<Map.Entry<String, String>> aspectsParameters;
public BuildRequestOptions() throws OptionsParsingException {}
public String getSymlinkPrefix(String productName) {
return symlinkPrefix == null ? productName + "-" : symlinkPrefix;
}
@Option(
name = "use_action_cache",
defaultValue = "true",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
effectTags = {
OptionEffectTag.BAZEL_INTERNAL_CONFIGURATION,
OptionEffectTag.HOST_MACHINE_RESOURCE_OPTIMIZATIONS
},
help = "Whether to use the action cache")
public boolean useActionCache;
@Option(
name = "rewind_lost_inputs",
defaultValue = "false",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
effectTags = {OptionEffectTag.EXECUTION},
help = "Whether to use action rewinding to recover from lost inputs.")
public boolean rewindLostInputs;
@Option(
name = "incompatible_skip_genfiles_symlink",
defaultValue = "true",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
metadataTags = {OptionMetadataTag.INCOMPATIBLE_CHANGE},
effectTags = {OptionEffectTag.LOSES_INCREMENTAL_STATE},
help =
"If set to true, the genfiles symlink will not be created. For more information, see "
+ "https://github.com/bazelbuild/bazel/issues/8651")
public boolean incompatibleSkipGenfilesSymlink;
@Option(
name = "target_pattern_file",
defaultValue = "",
documentationCategory = OptionDocumentationCategory.GENERIC_INPUTS,
effectTags = {OptionEffectTag.CHANGES_INPUTS},
help =
"If set, build will read patterns from the file named here, rather than on the command "
+ "line. It is an error to specify a file here as well as command-line patterns.")
public String targetPatternFile;
/**
* Do not use directly. Instead use {@link
* com.google.devtools.build.lib.runtime.CommandEnvironment#withMergedAnalysisAndExecutionSourceOfTruth()}.
*/
@Option(
name = "experimental_merged_skyframe_analysis_execution",
defaultValue = "true",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
metadataTags = OptionMetadataTag.EXPERIMENTAL,
effectTags = {OptionEffectTag.LOADING_AND_ANALYSIS, OptionEffectTag.EXECUTION},
help = "If this flag is set, the analysis and execution phases of Skyframe are merged.")
public boolean mergedSkyframeAnalysisExecutionDoNotUseDirectly;
@Option(
name = "experimental_skymeld_analysis_overlap_percentage",
defaultValue = "100",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
metadataTags = OptionMetadataTag.EXPERIMENTAL,
effectTags = {OptionEffectTag.LOADING_AND_ANALYSIS, OptionEffectTag.EXECUTION},
converter = PercentageConverter.class,
help =
"The value represents the % of the analysis phase which will be overlapped with the"
+ " execution phase. A value of x means Skyframe will queue up execution tasks and"
+ " wait until there's x% of the top level target left to be analyzed before allowing"
+ " them to launch. When the value is 0%, we'd wait for all analysis to finish before"
+ " executing (no overlap). When it's 100%, the phases are free to overlap as much as"
+ " they can.")
public int skymeldAnalysisOverlapPercentage;
/** Converter for filesystem value checker threads. */
public static class ThreadConverter extends ResourceConverter.IntegerConverter {
public ThreadConverter() {
super(/* auto= */ HOST_CPUS_SUPPLIER, /* minValue= */ 1, /* maxValue= */ Integer.MAX_VALUE);
}
}
@Option(
name = "experimental_fsvc_threads",
defaultValue = "200",
converter = ThreadConverter.class,
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
metadataTags = OptionMetadataTag.EXPERIMENTAL,
effectTags = {OptionEffectTag.EXECUTION},
help = "The number of threads that are used by the FileSystemValueChecker.")
public int fsvcThreads;
@Option(
name = "experimental_skyframe_memory_dump",
defaultValue = "null",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
help =
"Dump the memory use of individual nodes in the Skyframe graph after the build. This"
+ " option takes a number of flags separated by commas: 'json' (no-op, that's the"
+ " only format), 'notransient' (don't traverse transient fields), 'noconfig' (ignore"
+ " objects related to configurations), 'noprecomputed' (ignore precomputed values)"
+ " and 'noworkspacestatus' (ignore objects related to the workspace status"
+ " machinery)")
public String skyframeMemoryDump;
@Option(
name = "enforce_project_configs",
defaultValue = "true",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
effectTags = {OptionEffectTag.LOADING_AND_ANALYSIS, OptionEffectTag.AFFECTS_OUTPUTS},
metadataTags = {OptionMetadataTag.EXPERIMENTAL},
// TODO: b/341931019 - link to user documentation when available.
help =
"If true, interactive builds may only pass the --scl_config build flag; they may not use"
+ " any other build flags. --scl_config must be set to an officially suported project"
+ " configuration. Supported configurations are defined in the target's PROJECT.scl,"
+ " which can be found by walking up the target's packagge path. See b/324126745.")
public boolean enforceProjectConfigs;
@Option(
name = "experimental_aquery_dump_after_build_format",
defaultValue = "null",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
help =
"Writes the state of Skyframe (which includes previous invocations on this blaze instance"
+ " as well) after a build. Output is streamed remotely unless local output is"
+ " requested with --experimental_aquery_dump_after_build_output_file. Does not"
+ " honor aquery flags for --include_*, but uses the same defaults, except for"
+ " --include_commandline=false. Possible output formats:"
+ " proto|streamed_proto|textproto|jsonproto. Using this will disable Skymeld.")
@Nullable
public String aqueryDumpAfterBuildFormat;
@Option(
name = "experimental_aquery_dump_after_build_output_file",
defaultValue = "null",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
converter = OptionsUtils.PathFragmentConverter.class,
// NOTE: This produces a very very large amount of data on large builds,
// very useful for debugging, but may not be used regularly. When removing
// unused flags based on usage this may not be a good candidate for
// removal.
help =
"Specify the output file for the aquery dump after a build. Use in conjunction with"
+ " --experimental_aquery_dump_after_build_format. The path provided is relative to"
+ " Bazel's output base, unless it's an absolute path. Using this will disable"
+ " Skymeld.")
@Nullable
public PathFragment aqueryDumpAfterBuildOutputFile;
/**
* Converter for jobs: Takes keyword ({@value #FLAG_SYNTAX}). Values must be between 1 and
* MAX_JOBS.
*/
public static class JobsConverter extends ResourceConverter.IntegerConverter {
public JobsConverter() {
super(/* auto= */ HOST_CPUS_SUPPLIER, /* minValue= */ 1, /* maxValue= */ MAX_JOBS);
}
@Override
public Integer checkAndLimit(Integer value) throws OptionsParsingException {
if (value.doubleValue() < minValue) {
throw new OptionsParsingException(
String.format("Value '(%d)' must be at least %d.", value, minValue));
}
if (value.doubleValue() > maxValue) {
logger.atWarning().log(
"Flag remoteWorker \"jobs\" ('%d') was set too high. "
+ "This is a result of passing large values to --local_resources or --jobs. "
+ "Using '%d' jobs",
value, maxValue);
return maxValue;
}
return value;
}
}
/** Converter for progress_report_interval: [0, 3600]. */
public static class ProgressReportIntervalConverter extends RangeConverter {
public ProgressReportIntervalConverter() {
super(0, 3600);
}
}
/**
* The {@link BoolOrEnumConverter} for the {@link ConvenienceSymlinksMode} where NORMAL is true
* and IGNORE is false.
*/
public static class ConvenienceSymlinksConverter
extends BoolOrEnumConverter<ConvenienceSymlinksMode> {
public ConvenienceSymlinksConverter() {
super(
ConvenienceSymlinksMode.class,
"convenience symlinks mode",
ConvenienceSymlinksMode.NORMAL,
ConvenienceSymlinksMode.IGNORE);
}
}
/** Determines how the convenience symlinks are presented to the user */
enum ConvenienceSymlinksMode {
/** Will manage symlinks based on the symlink prefix. */
NORMAL,
/** Will clean up any existing symlinks. */
CLEAN,
/** Will not create or clean up any symlinks. */
IGNORE,
/** Will not create or clean up any symlinks, but will record the symlinks. */
LOG_ONLY
}
}