| // 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"; |
| |
| } |