| // 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.actions; | |
| import com.google.auto.value.AutoValue; | |
| import com.google.common.base.Function; | |
| import com.google.common.base.Preconditions; | |
| import com.google.common.collect.ImmutableMap; | |
| import com.google.devtools.build.lib.packages.Rule; | |
| import java.util.regex.Matcher; | |
| import java.util.regex.Pattern; | |
| /** | |
| * Strings used to express requirements on action execution environments. | |
| * | |
| * <ol> | |
| * If you are adding a new execution requirement, pay attention to the following: | |
| * <li>If its name starts with one of the supported prefixes, then it can be also used as a tag on | |
| * a target and will be propagated to the execution requirements, see for prefixes {@link | |
| * com.google.devtools.build.lib.packages.TargetUtils#getExecutionInfo(Rule)} | |
| * <li>If this is a potentially conflicting execution requirements, e.g. you are adding a pair | |
| * 'requires-x' and 'block-x', you MUST take care of a potential conflict in the Executor that | |
| * is using new execution requirements. As an example, see {@link | |
| * Spawns#requiresNetwork(com.google.devtools.build.lib.actions.Spawn, boolean)}. | |
| * </ol> | |
| */ | |
| public class ExecutionRequirements { | |
| /** An execution requirement that can be split into a key and a value part using a regex. */ | |
| @AutoValue | |
| public abstract static class ParseableRequirement { | |
| /** | |
| * Thrown when a {@link ParseableRequirement} feels responsible for a tag, but the {@link | |
| * #validator()} method returns an error. | |
| */ | |
| public static class ValidationException extends Exception { | |
| private final String tagValue; | |
| /** | |
| * Creates a new {@link ValidationException}. | |
| * | |
| * @param tagValue the erroneous value that was parsed from the tag. | |
| * @param errorMsg an error message that tells the user what's wrong with the value. | |
| */ | |
| public ValidationException(String tagValue, String errorMsg) { | |
| super(errorMsg); | |
| this.tagValue = tagValue; | |
| } | |
| /** | |
| * Returns the erroneous value of the parsed tag. | |
| * | |
| * <p>Useful to put in error messages shown to the user. | |
| */ | |
| public String getTagValue() { | |
| return tagValue; | |
| } | |
| } | |
| /** | |
| * Create a new parseable execution requirement definition. | |
| * | |
| * <p>If a tag doesn't match the detectionPattern, it will be ignored. If a tag matches the | |
| * detectionPattern, but not the validationPattern, it is assumed that the value is somehow | |
| * wrong (e.g. the user put a float or random string where we expected an integer). | |
| * | |
| * @param userFriendlyName a human readable name of the tag and its format, e.g. "cpu:<int>" | |
| * @param detectionPattern a regex that will be used to detect whether a tag matches this | |
| * execution requirement. It should have one capture group that grabs the value of the tag. | |
| * This should be general enough to permit even wrong value types. Example: "cpu:(.+)". | |
| * @param validator a Function that will be used to validate the value of the tag. It should | |
| * return null if the value is fine to use or a human-friendly error message describing why | |
| * the value is not valid. | |
| */ | |
| static ParseableRequirement create( | |
| String userFriendlyName, Pattern detectionPattern, Function<String, String> validator) { | |
| return new AutoValue_ExecutionRequirements_ParseableRequirement( | |
| userFriendlyName, detectionPattern, validator); | |
| } | |
| public abstract String userFriendlyName(); | |
| public abstract Pattern detectionPattern(); | |
| public abstract Function<String, String> validator(); | |
| /** | |
| * Returns the parsed value from a tag, if this {@link ParseableRequirement} detects that it is | |
| * responsible for it, otherwise returns {@code null}. | |
| * | |
| * @throws ValidationException if the value parsed out of the tag doesn't pass the validator. | |
| */ | |
| public String parseIfMatches(String tag) throws ValidationException { | |
| Matcher matcher = detectionPattern().matcher(tag); | |
| if (!matcher.matches()) { | |
| return null; | |
| } | |
| String tagValue = matcher.group(1); | |
| String errorMsg = validator().apply(tagValue); | |
| if (errorMsg != null) { | |
| throw new ValidationException(tagValue, errorMsg); | |
| } | |
| return tagValue; | |
| } | |
| } | |
| /** If specified, the timeout of this action in seconds. Must be decimal integer. */ | |
| public static final String TIMEOUT = "timeout"; | |
| /** If an action would not successfully run other than on Darwin. */ | |
| public static final String REQUIRES_DARWIN = "requires-darwin"; | |
| /** Whether we should disable prefetching of inputs before running a local action. */ | |
| public static final String DISABLE_LOCAL_PREFETCH = "disable-local-prefetch"; | |
| /** How many hardware threads an action requires for execution. */ | |
| public static final ParseableRequirement CPU = | |
| ParseableRequirement.create( | |
| "cpu:<int>", | |
| Pattern.compile("cpu:(.+)"), | |
| s -> { | |
| Preconditions.checkNotNull(s); | |
| int value; | |
| try { | |
| value = Integer.parseInt(s); | |
| } catch (NumberFormatException e) { | |
| return "can't be parsed as an integer"; | |
| } | |
| // De-and-reserialize & compare to only allow canonical integer formats. | |
| if (!Integer.toString(value).equals(s)) { | |
| return "must be in canonical format (e.g. '4' instead of '+04')"; | |
| } | |
| if (value < 1) { | |
| return "can't be zero or negative"; | |
| } | |
| return null; | |
| }); | |
| /** If an action supports running in persistent worker mode. */ | |
| public static final String SUPPORTS_WORKERS = "supports-workers"; | |
| public static final String SUPPORTS_MULTIPLEX_WORKERS = "supports-multiplex-workers"; | |
| public static final ImmutableMap<String, String> WORKER_MODE_ENABLED = | |
| ImmutableMap.of(SUPPORTS_WORKERS, "1"); | |
| /** | |
| * Requires local execution without sandboxing for a spawn. | |
| * | |
| * <p>This tag is deprecated; use no-cache, no-remote, or no-sandbox instead. | |
| */ | |
| public static final String LOCAL = "local"; | |
| /** | |
| * Disables local and remote caching for a spawn, but note that the local action cache may still | |
| * apply. | |
| * | |
| * <p>This tag can also be set on an action, in which case it completely disables all caching for | |
| * that action, but note that action-generated spawns may still be cached, unless they also carry | |
| * this tag. | |
| */ | |
| public static final String NO_CACHE = "no-cache"; | |
| /** Disables remote caching of a spawn. Note: does not disable remote execution */ | |
| public static final String NO_REMOTE_CACHE = "no-remote-cache"; | |
| /** Disables remote execution of a spawn. Note: does not disable remote caching */ | |
| public static final String NO_REMOTE_EXEC = "no-remote-exec"; | |
| /** | |
| * Disables both remote execution and remote caching of a spawn. This is the equivalent of using | |
| * no-remote-cache and no-remote-exec together. | |
| */ | |
| public static final String NO_REMOTE = "no-remote"; | |
| /** Disables local execution of a spawn. */ | |
| public static final String NO_LOCAL = "no-local"; | |
| /** Disables local sandboxing of a spawn. */ | |
| public static final String LEGACY_NOSANDBOX = "nosandbox"; | |
| /** Disables local sandboxing of a spawn. */ | |
| public static final String NO_SANDBOX = "no-sandbox"; | |
| /** | |
| * Set for Xcode-related rules. Used for quality control to make sure that all Xcode-dependent | |
| * rules propagate the necessary configurations. Begins with "supports" so as not to be filtered | |
| * out for Bazel by {@code TargetUtils}. | |
| */ | |
| public static final String REQUIREMENTS_SET = "supports-xcode-requirements-set"; | |
| /** | |
| * Enables networking for a spawn if possible (only if sandboxing is enabled and if the sandbox | |
| * supports it). | |
| */ | |
| public static final String REQUIRES_NETWORK = "requires-network"; | |
| /** | |
| * Disables networking for a spawn if possible (only if sandboxing is enabled and if the sandbox | |
| * supports it). | |
| */ | |
| public static final String BLOCK_NETWORK = "block-network"; | |
| /** | |
| * On linux, if sandboxing is enabled, ensures that a spawn is run with uid 0, i.e., root. Has no | |
| * effect otherwise. | |
| */ | |
| public static final String REQUIRES_FAKEROOT = "requires-fakeroot"; | |
| /** Suppress CLI reporting for this spawn - it's part of another action. */ | |
| public static final String DO_NOT_REPORT = "internal-do-not-report"; | |
| /** Use this to request eager fetching of a single remote output into local memory. */ | |
| public static final String REMOTE_EXECUTION_INLINE_OUTPUTS = "internal-inline-outputs"; | |
| } |