blob: 7a9feab317ebd5946eadd393f8230022f8a5213a [file] [log] [blame]
// Copyright 2019 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.syntax;
import com.google.auto.value.AutoValue;
import com.google.auto.value.extension.memoized.Memoized;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.List;
/**
* Options that affect the dynamic behavior of Starlark execution and operators.
*
* <p>For descriptions of what these options do, see {@link packages.StarlarkSemanticsOptions}.
*
* <p>For options that affect the static behavior of the Starlark frontend (lexer, parser,
* validator, compiler), see FileOptions.
*/
// TODO(brandjon): User error messages that reference options should maybe be substituted with the
// option name outside of the core Starlark interpreter?
// TODO(brandjon): Eventually these should be documented in full here, and StarlarkSemanticsOptions
// should refer to this class for documentation. But this doesn't play nice with the options
// parser's annotation mechanism.
//
// TODO(adonovan): nearly all of these options are Bazel-isms.
// The only ones that affect the Starlark interpreter directly are are:
// - incompatibleRestrictNamedParams, which affects calls to many built-ins,
// but is used only by copybara and will be deleted soon (CL 298871155);
// - incompatibleRestrictStringEscapes, which affects the lexer and is thus
// properly one of the FileOptions, but piggybacks on the command-line flag
// plumbing of StarlarkSemantics; and
// - internalStarlarkFlagTestCanary, which is used to test propagation of Bazel
// command-line flags to the 'print' built-in, but this could easily be
// achieved using some other Bazel-specific built-in.
// Most of the rest are used generically to disable parameters to built-ins,
// or to disable fields of modules, based on flags. In both of those cases,
// a generic set-of-feature-strings representation would do.
// A few could be expressed as Bazel-specific thread state,
// though several are inspected by the implementations of operations
// such as StarlarkIndexable, StarlarkQueryable, and StarlarkClassObject.
// TODO(adonovan): move to lib.packages.BuildLanguageSemantics.
//
@AutoValue
public abstract class StarlarkSemantics {
/**
* A set of names of boolean application flags each corresponding to a StarlarkSemantics feature.
*/
// TODO(adonovan): StarlarkSemantics, being part of the core frontend, shouldn't refer to Bazel
// features. There's no need for an enumeration to represent a set of boolean features. Instead,
// have StarlarkSemantics hold a set of enabled features (strings), and have callers query
// features by name. The features can be named string constants, defined close to the code they
// affect, to avoid accidential misspellings.
public static final class FlagIdentifier {
private FlagIdentifier() {} // uninstantiable
// The strings here match the names of the StarlarkSemantics methods,
// which in turn match the actual flag names; they should be kept
// consistent as they may appear in error messages.
// TODO(adonovan): move these constants up into the relevant packages of
// Bazel, and make them identical to the strings used in flag declarations.
public static final String EXPERIMENTAL_ACTION_ARGS = "experimental_action_args";
public static final String EXPERIMENTAL_ALLOW_INCREMENTAL_REPOSITORY_UPDATES =
"experimental_allow_incremental_repository_updates";
public static final String EXPERIMENTAL_DISABLE_EXTERNAL_PACKGE =
"experimental_disable_external_package";
public static final String EXPERIMENTAL_SIBLING_REPOSITORY_LAYOUT =
"experimental_sibling_repository_layout";
public static final String EXPERIMENTAL_ENABLE_ANDROID_MIGRATION_APIS =
"experimental_enable_android_migration_apis";
public static final String EXPERIMENTAL_GOOGLE_LEGACY_API = "experimental_google_legacy_api";
public static final String EXPERIMENTAL_NINJA_ACTIONS = "experimental_ninja_actions";
public static final String EXPERIMENTAL_PLATFORM_API = "experimental_platform_api";
public static final String EXPERIMENTAL_STARLARK_CONFIG_TRANSITION =
"experimental_starlark_config_transition";
public static final String EXPERIMENTAL_STARLARK_UNUSED_INPUTS_LIST =
"experimental_starlark_unused_inputs_list";
public static final String EXPERIMENTAL_REPO_REMOTE_EXEC = "experimental_repo_remote_exec";
public static final String EXPERIMENTAL_EXEC_GROUPS = "experimental_exec_groups";
public static final String INCOMPATIBLE_APPLICABLE_LICENSES =
"incompatible_applicable_licenses";
public static final String INCOMPATIBLE_DISABLE_DEPSET_ITEMS =
"incompatible_disable_depset_items";
public static final String INCOMPATIBLE_NO_RULE_OUTPUTS_PARAM =
"incompatible_no_rule_outputs_param";
public static final String INCOMPATIBLE_NO_ATTR_LICENSE = "incompatible_no_attr_license";
public static final String INCOMPATIBLE_ALLOW_TAGS_PROPAGATION =
"incompatible_allow_tags_propagation";
public static final String INCOMPATIBLE_OBJC_PROVIDER_REMOVE_COMPILE_INFO =
"incompatible_objc_provider_remove_compile_info";
public static final String INCOMPATIBLE_REQUIRE_LINKER_INPUT_CC_API =
"incompatible_require_linker_input_cc_api";
public static final String INCOMPATIBLE_LINKOPTS_TO_LINKLIBS =
"incompatible_linkopts_to_linklibs";
public static final String RECORD_RULE_INSTANTIATION_CALLSTACK =
"record_rule_instantiation_callstack";
}
// TODO(adonovan): replace the fields of StarlarkSemantics
// by a map from string to object, and make it the clients's job
// to know the type. This function would then become simply:
// return Boolean.TRUE.equals(map.get(flag)).
public boolean flagValue(String flag) {
switch (flag) {
case FlagIdentifier.EXPERIMENTAL_ACTION_ARGS:
return experimentalActionArgs();
case FlagIdentifier.EXPERIMENTAL_ALLOW_INCREMENTAL_REPOSITORY_UPDATES:
return experimentalAllowIncrementalRepositoryUpdates();
case FlagIdentifier.EXPERIMENTAL_DISABLE_EXTERNAL_PACKGE:
return experimentalDisableExternalPackage();
case FlagIdentifier.EXPERIMENTAL_SIBLING_REPOSITORY_LAYOUT:
return experimentalSiblingRepositoryLayout();
case FlagIdentifier.EXPERIMENTAL_ENABLE_ANDROID_MIGRATION_APIS:
return experimentalEnableAndroidMigrationApis();
case FlagIdentifier.EXPERIMENTAL_GOOGLE_LEGACY_API:
return experimentalGoogleLegacyApi();
case FlagIdentifier.EXPERIMENTAL_NINJA_ACTIONS:
return experimentalNinjaActions();
case FlagIdentifier.EXPERIMENTAL_PLATFORM_API:
return experimentalPlatformsApi();
case FlagIdentifier.EXPERIMENTAL_STARLARK_CONFIG_TRANSITION:
return experimentalStarlarkConfigTransitions();
case FlagIdentifier.EXPERIMENTAL_STARLARK_UNUSED_INPUTS_LIST:
return experimentalStarlarkUnusedInputsList();
case FlagIdentifier.EXPERIMENTAL_REPO_REMOTE_EXEC:
return experimentalRepoRemoteExec();
case FlagIdentifier.EXPERIMENTAL_EXEC_GROUPS:
return experimentalExecGroups();
case FlagIdentifier.INCOMPATIBLE_APPLICABLE_LICENSES:
return incompatibleApplicableLicenses();
case FlagIdentifier.INCOMPATIBLE_DISABLE_DEPSET_ITEMS:
return incompatibleDisableDepsetItems();
case FlagIdentifier.INCOMPATIBLE_NO_RULE_OUTPUTS_PARAM:
return incompatibleNoRuleOutputsParam();
case FlagIdentifier.INCOMPATIBLE_NO_ATTR_LICENSE:
return incompatibleNoAttrLicense();
case FlagIdentifier.INCOMPATIBLE_ALLOW_TAGS_PROPAGATION:
return experimentalAllowTagsPropagation();
case FlagIdentifier.INCOMPATIBLE_OBJC_PROVIDER_REMOVE_COMPILE_INFO:
return incompatibleObjcProviderRemoveCompileInfo();
case FlagIdentifier.INCOMPATIBLE_REQUIRE_LINKER_INPUT_CC_API:
return incompatibleRequireLinkerInputCcApi();
case FlagIdentifier.INCOMPATIBLE_LINKOPTS_TO_LINKLIBS:
return incompatibleLinkoptsToLinkLibs();
case FlagIdentifier.RECORD_RULE_INSTANTIATION_CALLSTACK:
return recordRuleInstantiationCallstack();
default:
throw new IllegalArgumentException(flag);
}
}
/**
* Returns true if a feature attached to the given toggling flags should be enabled.
*
* <ul>
* <li>If both parameters are empty, this indicates the feature is not controlled by flags, and
* should thus be enabled.
* <li>If the {@code enablingFlag} parameter is non-empty, this returns true if and only if that
* flag is true. (This represents a feature that is only on if a given flag is *on*).
* <li>If the {@code disablingFlag} parameter is non-empty, this returns true if and only if
* that flag is false. (This represents a feature that is only on if a given flag is *off*).
* <li>It is illegal to pass both parameters as non-empty.
* </ul>
*/
boolean isFeatureEnabledBasedOnTogglingFlags(String enablingFlag, String disablingFlag) {
Preconditions.checkArgument(
enablingFlag.isEmpty() || disablingFlag.isEmpty(),
"at least one of 'enablingFlag' or 'disablingFlag' must be empty");
if (!enablingFlag.isEmpty()) {
return this.flagValue(enablingFlag);
} else if (!disablingFlag.isEmpty()) {
return !this.flagValue(disablingFlag);
} else {
return true;
}
}
/**
* The AutoValue-generated concrete class implementing this one.
*
* <p>AutoValue implementation classes are usually package-private. We expose it here for the
* benefit of code that relies on reflection.
*/
public static final Class<? extends StarlarkSemantics> IMPL_CLASS =
AutoValue_StarlarkSemantics.class;
// <== Add new options here in alphabetic order ==>
public abstract boolean experimentalActionArgs();
public abstract boolean experimentalAllowIncrementalRepositoryUpdates();
public abstract String experimentalBuiltinsBzlPath();
public abstract ImmutableList<String> experimentalCcStarlarkApiEnabledPackages();
public abstract boolean experimentalEnableAndroidMigrationApis();
public abstract boolean experimentalGoogleLegacyApi();
public abstract boolean experimentalNinjaActions();
public abstract boolean experimentalPlatformsApi();
public abstract boolean experimentalStarlarkConfigTransitions();
public abstract boolean experimentalStarlarkUnusedInputsList();
public abstract boolean experimentalCcSharedLibrary();
public abstract boolean experimentalRepoRemoteExec();
public abstract boolean experimentalDisableExternalPackage();
public abstract boolean experimentalSiblingRepositoryLayout();
public abstract boolean experimentalExecGroups();
public abstract boolean incompatibleAlwaysCheckDepsetElements();
public abstract boolean incompatibleApplicableLicenses();
public abstract boolean incompatibleDisableTargetProviderFields();
public abstract boolean incompatibleDisableThirdPartyLicenseChecking();
public abstract boolean incompatibleDisableDepsetItems();
public abstract boolean incompatibleDisallowEmptyGlob();
public abstract boolean incompatibleDisallowStructProviderSyntax();
public abstract boolean incompatibleNewActionsApi();
public abstract boolean incompatibleNoAttrLicense();
public abstract boolean incompatibleNoImplicitFileExport();
public abstract boolean incompatibleNoRuleOutputsParam();
public abstract boolean incompatibleNoSupportToolsInActionInputs();
public abstract boolean incompatibleRunShellCommandString();
public abstract boolean incompatibleStringReplaceCount();
public abstract boolean incompatibleVisibilityPrivateAttributesAtDefinition();
public abstract boolean internalStarlarkFlagTestCanary();
public abstract boolean incompatibleDoNotSplitLinkingCmdline();
public abstract boolean incompatibleDepsetForLibrariesToLinkGetter();
public abstract boolean incompatibleObjcProviderRemoveCompileInfo();
public abstract boolean incompatibleRequireLinkerInputCcApi();
public abstract boolean incompatibleRestrictStringEscapes();
public abstract boolean experimentalAllowTagsPropagation();
public abstract boolean incompatibleUseCcConfigureFromRulesCc();
public abstract boolean incompatibleLinkoptsToLinkLibs();
public abstract long maxComputationSteps();
public abstract boolean recordRuleInstantiationCallstack();
@Memoized
@Override
public abstract int hashCode();
/** Returns a {@link Builder} initialized with the values of this instance. */
public abstract Builder toBuilder();
/**
* Returns a deterministic {@link String} representation of this object's values.
*
* <p>Strictly speaking, {@link AutoValue}'s generated toString implementations are unspecified.
* Therefore it is free to e.g. randomly shuffle the order of "property=value" entries on each
* call. In practice, it doesn't. The entries are printed in method declaration order.
*
* <p>We could attempt our own implementation via reflection but it's likely to be more fragile
* than relying on the unspecified behavior to be, at least, non-pathological. YAGNI.
*/
public String toDeterministicString() {
return toString();
}
public static Builder builder() {
return new AutoValue_StarlarkSemantics.Builder();
}
/** Returns a {@link Builder} initialized with default values for all options. */
public static Builder builderWithDefaults() {
return DEFAULT.toBuilder();
}
public static final StarlarkSemantics DEFAULT =
builder()
// <== Add new options here in alphabetic order ==>
.experimentalActionArgs(true)
.experimentalAllowTagsPropagation(false)
.experimentalBuiltinsBzlPath("")
.experimentalCcStarlarkApiEnabledPackages(ImmutableList.of())
.experimentalAllowIncrementalRepositoryUpdates(true)
.experimentalEnableAndroidMigrationApis(false)
.experimentalGoogleLegacyApi(false)
.experimentalNinjaActions(false)
.experimentalPlatformsApi(false)
.experimentalStarlarkConfigTransitions(true)
.experimentalStarlarkUnusedInputsList(true)
.experimentalCcSharedLibrary(false)
.experimentalRepoRemoteExec(false)
.experimentalDisableExternalPackage(false)
.experimentalSiblingRepositoryLayout(false)
.experimentalExecGroups(false)
.incompatibleAlwaysCheckDepsetElements(true)
.incompatibleApplicableLicenses(false)
.incompatibleDisableTargetProviderFields(false)
.incompatibleDisableThirdPartyLicenseChecking(true)
.incompatibleDisableDepsetItems(false)
.incompatibleDisallowEmptyGlob(false)
.incompatibleDisallowStructProviderSyntax(false)
.incompatibleNewActionsApi(true)
.incompatibleNoAttrLicense(true)
.incompatibleNoImplicitFileExport(false)
.incompatibleNoRuleOutputsParam(false)
.incompatibleNoSupportToolsInActionInputs(true)
.incompatibleRunShellCommandString(false)
.incompatibleStringReplaceCount(false)
.incompatibleVisibilityPrivateAttributesAtDefinition(false)
.internalStarlarkFlagTestCanary(false)
.incompatibleDoNotSplitLinkingCmdline(true)
.incompatibleDepsetForLibrariesToLinkGetter(true)
.incompatibleObjcProviderRemoveCompileInfo(false)
.incompatibleRequireLinkerInputCcApi(false)
.incompatibleRestrictStringEscapes(false)
.incompatibleUseCcConfigureFromRulesCc(false)
.incompatibleLinkoptsToLinkLibs(false)
.maxComputationSteps(0)
.recordRuleInstantiationCallstack(false)
.build();
/** Builder for {@link StarlarkSemantics}. All fields are mandatory. */
@AutoValue.Builder
public abstract static class Builder {
// <== Add new options here in alphabetic order ==>
public abstract Builder experimentalActionArgs(boolean value);
public abstract Builder experimentalAllowIncrementalRepositoryUpdates(boolean value);
public abstract Builder experimentalAllowTagsPropagation(boolean value);
public abstract Builder experimentalBuiltinsBzlPath(String value);
public abstract Builder experimentalCcStarlarkApiEnabledPackages(List<String> value);
public abstract Builder experimentalEnableAndroidMigrationApis(boolean value);
public abstract Builder experimentalGoogleLegacyApi(boolean value);
public abstract Builder experimentalNinjaActions(boolean value);
public abstract Builder experimentalPlatformsApi(boolean value);
public abstract Builder experimentalStarlarkConfigTransitions(boolean value);
public abstract Builder experimentalStarlarkUnusedInputsList(boolean value);
public abstract Builder experimentalCcSharedLibrary(boolean value);
public abstract Builder experimentalRepoRemoteExec(boolean value);
public abstract Builder experimentalDisableExternalPackage(boolean value);
public abstract Builder experimentalSiblingRepositoryLayout(boolean value);
public abstract Builder experimentalExecGroups(boolean value);
public abstract Builder incompatibleAlwaysCheckDepsetElements(boolean value);
public abstract Builder incompatibleApplicableLicenses(boolean value);
public abstract Builder incompatibleDisableTargetProviderFields(boolean value);
public abstract Builder incompatibleDisableThirdPartyLicenseChecking(boolean value);
public abstract Builder incompatibleDisableDepsetItems(boolean value);
public abstract Builder incompatibleDisallowEmptyGlob(boolean value);
public abstract Builder incompatibleDisallowStructProviderSyntax(boolean value);
public abstract Builder incompatibleNewActionsApi(boolean value);
public abstract Builder incompatibleNoAttrLicense(boolean value);
public abstract Builder incompatibleNoImplicitFileExport(boolean value);
public abstract Builder incompatibleNoRuleOutputsParam(boolean value);
public abstract Builder incompatibleNoSupportToolsInActionInputs(boolean value);
public abstract Builder incompatibleRunShellCommandString(boolean value);
public abstract Builder incompatibleStringReplaceCount(boolean value);
public abstract Builder incompatibleVisibilityPrivateAttributesAtDefinition(boolean value);
public abstract Builder internalStarlarkFlagTestCanary(boolean value);
public abstract Builder incompatibleDoNotSplitLinkingCmdline(boolean value);
public abstract Builder incompatibleDepsetForLibrariesToLinkGetter(boolean value);
public abstract Builder incompatibleObjcProviderRemoveCompileInfo(boolean value);
public abstract Builder incompatibleRequireLinkerInputCcApi(boolean value);
public abstract Builder incompatibleRestrictStringEscapes(boolean value);
public abstract Builder incompatibleUseCcConfigureFromRulesCc(boolean value);
public abstract Builder incompatibleLinkoptsToLinkLibs(boolean value);
public abstract Builder maxComputationSteps(long value);
public abstract Builder recordRuleInstantiationCallstack(boolean value);
public abstract StarlarkSemantics build();
}
}