blob: 1011898230bf985866516361c63677af8cd7a6b7 [file] [log] [blame]
// 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.bazel.rules;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.ActionEnvironment;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.BaseRuleClasses.EmptyRule;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider.RuleSet;
import com.google.devtools.build.lib.analysis.PackageSpecificationProvider;
import com.google.devtools.build.lib.analysis.PlatformConfiguration;
import com.google.devtools.build.lib.analysis.ShellConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.CoreOptions;
import com.google.devtools.build.lib.analysis.config.Fragment;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.analysis.config.RequiresOptions;
import com.google.devtools.build.lib.bazel.BazelConfiguration;
import com.google.devtools.build.lib.bazel.repository.LocalConfigPlatformRule;
import com.google.devtools.build.lib.bazel.rules.android.AndroidNdkRepositoryRule;
import com.google.devtools.build.lib.bazel.rules.android.AndroidSdkRepositoryRule;
import com.google.devtools.build.lib.bazel.rules.android.BazelAarImportRule;
import com.google.devtools.build.lib.bazel.rules.android.BazelAndroidBinaryRule;
import com.google.devtools.build.lib.bazel.rules.android.BazelAndroidDevice;
import com.google.devtools.build.lib.bazel.rules.android.BazelAndroidDeviceScriptFixture;
import com.google.devtools.build.lib.bazel.rules.android.BazelAndroidHostServiceFixture;
import com.google.devtools.build.lib.bazel.rules.android.BazelAndroidLibraryRule;
import com.google.devtools.build.lib.bazel.rules.android.BazelAndroidLocalTestRule;
import com.google.devtools.build.lib.bazel.rules.android.BazelAndroidSdkRule;
import com.google.devtools.build.lib.bazel.rules.android.BazelAndroidSemantics;
import com.google.devtools.build.lib.bazel.rules.android.BazelAndroidToolsDefaultsJarRule;
import com.google.devtools.build.lib.bazel.rules.android.BazelDexArchiveAspect;
import com.google.devtools.build.lib.bazel.rules.android.BazelSdkToolchainRule;
import com.google.devtools.build.lib.bazel.rules.python.BazelPyBinaryRule;
import com.google.devtools.build.lib.bazel.rules.python.BazelPyBuiltins;
import com.google.devtools.build.lib.bazel.rules.python.BazelPyRuleClasses;
import com.google.devtools.build.lib.bazel.rules.python.BazelPyTestRule;
import com.google.devtools.build.lib.bazel.rules.python.BazelPythonConfiguration;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.packages.PackageCallable;
import com.google.devtools.build.lib.rules.android.AarImportBaseRule;
import com.google.devtools.build.lib.rules.android.AndroidApplicationResourceInfo;
import com.google.devtools.build.lib.rules.android.AndroidAssetsInfo;
import com.google.devtools.build.lib.rules.android.AndroidBinaryDataInfo;
import com.google.devtools.build.lib.rules.android.AndroidBinaryNativeLibsInfo;
import com.google.devtools.build.lib.rules.android.AndroidCcLinkParamsProvider;
import com.google.devtools.build.lib.rules.android.AndroidConfiguration;
import com.google.devtools.build.lib.rules.android.AndroidDeviceBrokerInfo;
import com.google.devtools.build.lib.rules.android.AndroidDeviceRule;
import com.google.devtools.build.lib.rules.android.AndroidDeviceScriptFixtureRule;
import com.google.devtools.build.lib.rules.android.AndroidDexInfo;
import com.google.devtools.build.lib.rules.android.AndroidFeatureFlagSetProvider;
import com.google.devtools.build.lib.rules.android.AndroidHostServiceFixtureRule;
import com.google.devtools.build.lib.rules.android.AndroidIdeInfoProvider;
import com.google.devtools.build.lib.rules.android.AndroidIdlProvider;
import com.google.devtools.build.lib.rules.android.AndroidInstrumentationInfo;
import com.google.devtools.build.lib.rules.android.AndroidLibraryAarInfo;
import com.google.devtools.build.lib.rules.android.AndroidLibraryBaseRule;
import com.google.devtools.build.lib.rules.android.AndroidLibraryResourceClassJarProvider;
import com.google.devtools.build.lib.rules.android.AndroidLocalTestBaseRule;
import com.google.devtools.build.lib.rules.android.AndroidManifestInfo;
import com.google.devtools.build.lib.rules.android.AndroidNativeLibsInfo;
import com.google.devtools.build.lib.rules.android.AndroidNeverLinkLibrariesProvider;
import com.google.devtools.build.lib.rules.android.AndroidNeverlinkAspect;
import com.google.devtools.build.lib.rules.android.AndroidOptimizationInfo;
import com.google.devtools.build.lib.rules.android.AndroidOptimizedJarInfo;
import com.google.devtools.build.lib.rules.android.AndroidPreDexJarProvider;
import com.google.devtools.build.lib.rules.android.AndroidProguardInfo;
import com.google.devtools.build.lib.rules.android.AndroidResourcesInfo;
import com.google.devtools.build.lib.rules.android.AndroidRuleClasses;
import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.AndroidBaseToolsDefaultsJarRule;
import com.google.devtools.build.lib.rules.android.AndroidSdkBaseRule;
import com.google.devtools.build.lib.rules.android.AndroidSdkProvider;
import com.google.devtools.build.lib.rules.android.AndroidStarlarkCommon;
import com.google.devtools.build.lib.rules.android.ApkInfo;
import com.google.devtools.build.lib.rules.android.BaselineProfileProvider;
import com.google.devtools.build.lib.rules.android.BazelAndroidConfiguration;
import com.google.devtools.build.lib.rules.android.DexArchiveAspect;
import com.google.devtools.build.lib.rules.android.ProguardMappingProvider;
import com.google.devtools.build.lib.rules.android.databinding.DataBindingV2Provider;
import com.google.devtools.build.lib.rules.config.ConfigRules;
import com.google.devtools.build.lib.rules.core.CoreRules;
import com.google.devtools.build.lib.rules.cpp.CcStarlarkInternal;
import com.google.devtools.build.lib.rules.objc.ObjcStarlarkInternal;
import com.google.devtools.build.lib.rules.platform.PlatformRules;
import com.google.devtools.build.lib.rules.proto.BazelProtoCommon;
import com.google.devtools.build.lib.rules.proto.ProtoConfiguration;
import com.google.devtools.build.lib.rules.python.PyRuntimeRule;
import com.google.devtools.build.lib.rules.python.PythonConfiguration;
import com.google.devtools.build.lib.rules.repository.CoreWorkspaceRules;
import com.google.devtools.build.lib.rules.repository.NewLocalRepositoryRule;
import com.google.devtools.build.lib.rules.test.TestingSupportRules;
import com.google.devtools.build.lib.starlarkbuildapi.android.AndroidBootstrap;
import com.google.devtools.build.lib.starlarkbuildapi.core.ContextGuardedValue;
import com.google.devtools.build.lib.starlarkbuildapi.proto.ProtoBootstrap;
import com.google.devtools.build.lib.starlarkbuildapi.python.PyBootstrap;
import com.google.devtools.build.lib.starlarkbuildapi.stubs.ProviderStub;
import com.google.devtools.build.lib.starlarkbuildapi.stubs.StarlarkAspectStub;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.util.ResourceFileLoader;
import com.google.devtools.build.lib.vfs.PathFragment;
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 java.io.IOException;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Function;
import javax.annotation.Nullable;
import net.starlark.java.eval.Starlark;
/** A rule class provider implementing the rules Bazel knows. */
public class BazelRuleClassProvider {
/** Command-line options. */
public static class StrictActionEnvOptions extends FragmentOptions {
@Option(
name = "incompatible_strict_action_env",
oldName = "experimental_strict_action_env",
defaultValue = "false",
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
effectTags = {OptionEffectTag.LOADING_AND_ANALYSIS},
metadataTags = {OptionMetadataTag.INCOMPATIBLE_CHANGE},
help =
"If true, Bazel uses an environment with a static value for PATH and does not "
+ "inherit LD_LIBRARY_PATH. Use --action_env=ENV_VARIABLE if you want to "
+ "inherit specific environment variables from the client, but note that doing so "
+ "can prevent cross-user caching if a shared cache is used.")
public boolean useStrictActionEnv;
}
private static final PathFragment FALLBACK_SHELL = PathFragment.create("/bin/bash");
public static final ImmutableMap<OS, PathFragment> SHELL_EXECUTABLE =
ImmutableMap.<OS, PathFragment>builder()
.put(OS.WINDOWS, PathFragment.create("c:/tools/msys64/usr/bin/bash.exe"))
.put(OS.FREEBSD, PathFragment.create("/usr/local/bin/bash"))
.put(OS.OPENBSD, PathFragment.create("/usr/local/bin/bash"))
.put(OS.UNKNOWN, FALLBACK_SHELL)
.buildOrThrow();
/**
* {@link BuildConfigurationFunction} constructs {@link BuildOptions} out of the options required
* by the registered fragments. We create and register this fragment exclusively to ensure {@link
* StrictActionEnvOptions} is always available.
*/
@RequiresOptions(options = {StrictActionEnvOptions.class})
public static class StrictActionEnvConfiguration extends Fragment {
public StrictActionEnvConfiguration(BuildOptions buildOptions) {}
}
@Nullable
public static PathFragment getDefaultPathFromOptions(ShellConfiguration.Options options) {
if (options.shellExecutable != null) {
return options.shellExecutable;
}
// Honor BAZEL_SH env variable for backwards compatibility.
String path = System.getenv("BAZEL_SH");
if (path != null) {
return PathFragment.create(path);
}
return null;
}
@VisibleForTesting
static PathFragment getShellExecutableForOs(OS os, ShellConfiguration.Options options) {
// TODO(ulfjack): instead of using the OS Bazel runs on, we need to use the exec platform,
// which may be different for remote execution. For now, this can be overridden with
// --shell_executable, so at least there's a workaround.
return getDefaultPathFromOptions(options) != null
? getDefaultPathFromOptions(options)
: SHELL_EXECUTABLE.getOrDefault(os, FALLBACK_SHELL);
}
public static final Function<BuildOptions, ActionEnvironment> SHELL_ACTION_ENV =
(BuildOptions options) -> {
if (options.hasNoConfig()) {
return ActionEnvironment.EMPTY;
}
boolean strictActionEnv = options.get(StrictActionEnvOptions.class).useStrictActionEnv;
OS os = OS.getCurrent();
// TODO(ulfjack): instead of using the OS Bazel runs on, we need to use the exec platform,
// which may be different for remote execution. For now, this can be overridden with
// --shell_executable, so at least there's a workaround.
PathFragment shellExecutable =
getShellExecutableForOs(os, options.get(ShellConfiguration.Options.class));
TreeMap<String, String> env = new TreeMap<>();
// All entries in the builder that have a value of null inherit the value from the client
// environment, which is only known at execution time - we don't want to bake the client env
// into the configuration since any change to the configuration requires rerunning the full
// analysis phase.
if (!strictActionEnv) {
env.put("LD_LIBRARY_PATH", null);
}
if (strictActionEnv) {
env.put("PATH", pathOrDefault(os, null, shellExecutable));
} else if (os == OS.WINDOWS) {
// TODO(ulfjack): We want to add the MSYS root to the PATH, but that prevents us from
// inheriting PATH from the client environment. For now we use System.getenv even though
// that is incorrect. We should enable strict_action_env by default and then remove this
// code, but that change may break Windows users who are relying on the MSYS root being in
// the PATH.
env.put("PATH", pathOrDefault(os, System.getenv("PATH"), shellExecutable));
} else {
// The previous implementation used System.getenv (which uses the server's environment),
// and fell back to a hard-coded "/bin:/usr/bin" if PATH was not set.
env.put("PATH", null);
}
// Shell environment variables specified via options take precedence over the
// ones inherited from the fragments. In the long run, these fragments will
// be replaced by appropriate default rc files anyway.
for (Map.Entry<String, String> entry : options.get(CoreOptions.class).actionEnvironment) {
env.put(entry.getKey(), entry.getValue());
}
if (!BuildConfigurationValue.runfilesEnabled(options.get(CoreOptions.class))) {
// Setting this environment variable is for telling the binary running
// in a Bazel action when to use runfiles library or runfiles tree.
// The downside is that it will discard cache for all actions once
// --enable_runfiles changes, but this also prevents wrong caching result if a binary
// behaves differently with and without runfiles tree.
env.put("RUNFILES_MANIFEST_ONLY", "1");
}
return ActionEnvironment.split(env);
};
/** Convenience wrapper around {@link #setup} that returns a final ConfiguredRuleClassProvider. */
// Used by the build encyclopedia generator.
public static ConfiguredRuleClassProvider create() {
ConfiguredRuleClassProvider.Builder builder = new ConfiguredRuleClassProvider.Builder();
setup(builder);
return builder.build();
}
/** Adds this class's definitions to a builder. */
public static void setup(ConfiguredRuleClassProvider.Builder builder) {
builder.setToolsRepository(RepositoryName.BAZEL_TOOLS);
builder.setBuiltinsBzlZipResource(
ResourceFileLoader.resolveResource(BazelRuleClassProvider.class, "builtins_bzl.zip"));
builder.setBuiltinsBzlPackagePathInSource("src/main/starlark/builtins_bzl");
for (RuleSet ruleSet : RULE_SETS) {
ruleSet.init(builder);
}
}
public static final RuleSet BAZEL_SETUP =
new RuleSet() {
@Override
public void init(ConfiguredRuleClassProvider.Builder builder) {
ShellConfiguration.injectShellExecutableFinder(
BazelRuleClassProvider::getDefaultPathFromOptions, SHELL_EXECUTABLE);
builder
.setPrelude("//tools/build_rules:prelude_bazel")
.setRunfilesPrefix("_main")
.setPrerequisiteValidator(new BazelPrerequisiteValidator())
.setActionEnvironmentProvider(SHELL_ACTION_ENV)
.addUniversalConfigurationFragment(ShellConfiguration.class)
.addUniversalConfigurationFragment(PlatformConfiguration.class)
.addUniversalConfigurationFragment(BazelConfiguration.class)
.addUniversalConfigurationFragment(StrictActionEnvConfiguration.class)
.addConfigurationOptions(CoreOptions.class);
builder.addStarlarkBuiltinsInternal(
ObjcStarlarkInternal.NAME, new ObjcStarlarkInternal());
builder.addStarlarkBuiltinsInternal(CcStarlarkInternal.NAME, new CcStarlarkInternal());
// Add the package() function.
// TODO(bazel-team): Factor this into a group of similar BUILD definitions, or add a more
// convenient way of obtaining a BuiltinFunction than addMethods().
ImmutableMap.Builder<String, Object> symbols = ImmutableMap.builder();
Starlark.addMethods(symbols, PackageCallable.INSTANCE);
for (Map.Entry<String, Object> entry : symbols.buildOrThrow().entrySet()) {
builder.addBuildFileToplevel(entry.getKey(), entry.getValue());
}
}
};
public static final RuleSet PROTO_RULES =
new RuleSet() {
@Override
public void init(ConfiguredRuleClassProvider.Builder builder) {
builder.addConfigurationFragment(ProtoConfiguration.class);
builder.addRuleDefinition(new BaseRuleClasses.EmptyRule("proto_library") {});
builder.addRuleDefinition(new BaseRuleClasses.EmptyRule("proto_lang_toolchain") {});
ProtoBootstrap bootstrap =
new ProtoBootstrap(
BazelProtoCommon.INSTANCE, new StarlarkAspectStub(), new ProviderStub());
builder.addStarlarkBootstrap(bootstrap);
}
@Override
public ImmutableList<RuleSet> requires() {
return ImmutableList.of(CoreRules.INSTANCE);
}
};
public static final RuleSet JAVA_PROTO_RULES =
new RuleSet() {
@Override
public void init(ConfiguredRuleClassProvider.Builder builder) {
builder.addRuleDefinition(new BaseRuleClasses.EmptyRule("java_proto_library") {});
builder.addRuleDefinition(new BaseRuleClasses.EmptyRule("java_lite_proto_library") {});
}
@Override
public ImmutableList<RuleSet> requires() {
return ImmutableList.of(CoreRules.INSTANCE, JavaRules.INSTANCE);
}
};
public static final RuleSet ANDROID_RULES =
new RuleSet() {
@Override
public void init(ConfiguredRuleClassProvider.Builder builder) {
RepositoryName toolsRepository = checkNotNull(builder.getToolsRepository());
builder.addConfigurationFragment(AndroidConfiguration.class);
builder.addConfigurationFragment(BazelAndroidConfiguration.class);
AndroidNeverlinkAspect androidNeverlinkAspect = new AndroidNeverlinkAspect();
DexArchiveAspect dexArchiveAspect = new BazelDexArchiveAspect(toolsRepository);
builder.addNativeAspectClass(androidNeverlinkAspect);
builder.addNativeAspectClass(dexArchiveAspect);
builder.addRuleDefinition(new AndroidSdkBaseRule());
builder.addRuleDefinition(new BazelAndroidSdkRule());
builder.addRuleDefinition(new AndroidBaseToolsDefaultsJarRule());
builder.addRuleDefinition(new BazelAndroidToolsDefaultsJarRule());
builder.addRuleDefinition(new AndroidRuleClasses.AndroidBaseRule());
builder.addRuleDefinition(new AndroidRuleClasses.AndroidResourceSupportRule());
builder.addRuleDefinition(
new AndroidRuleClasses.AndroidBinaryBaseRule(
androidNeverlinkAspect, dexArchiveAspect));
builder.addRuleDefinition(new BazelSdkToolchainRule());
builder.addRuleDefinition(new AndroidLibraryBaseRule(androidNeverlinkAspect));
builder.addRuleDefinition(new BazelAndroidLibraryRule());
builder.addRuleDefinition(new BazelAndroidBinaryRule());
builder.addRuleDefinition(new AarImportBaseRule());
builder.addRuleDefinition(new BazelAarImportRule());
builder.addRuleDefinition(new AndroidDeviceRule(BazelAndroidDevice.class));
builder.addRuleDefinition(new AndroidLocalTestBaseRule());
builder.addRuleDefinition(new BazelAndroidLocalTestRule());
builder.addRuleDefinition(
new AndroidDeviceScriptFixtureRule(BazelAndroidDeviceScriptFixture.class));
builder.addRuleDefinition(
new AndroidHostServiceFixtureRule(BazelAndroidHostServiceFixture.class));
AndroidBootstrap bootstrap =
new AndroidBootstrap(
new AndroidStarlarkCommon(),
ApkInfo.PROVIDER,
AndroidInstrumentationInfo.PROVIDER,
AndroidDeviceBrokerInfo.PROVIDER,
AndroidResourcesInfo.PROVIDER,
AndroidNativeLibsInfo.PROVIDER,
AndroidApplicationResourceInfo.PROVIDER,
AndroidSdkProvider.PROVIDER,
AndroidManifestInfo.PROVIDER,
AndroidAssetsInfo.PROVIDER,
AndroidLibraryAarInfo.PROVIDER,
AndroidProguardInfo.PROVIDER,
AndroidIdlProvider.PROVIDER,
AndroidIdeInfoProvider.PROVIDER,
AndroidPreDexJarProvider.PROVIDER,
AndroidCcLinkParamsProvider.PROVIDER,
DataBindingV2Provider.PROVIDER,
AndroidLibraryResourceClassJarProvider.PROVIDER,
AndroidFeatureFlagSetProvider.PROVIDER,
ProguardMappingProvider.PROVIDER,
AndroidBinaryDataInfo.PROVIDER,
AndroidBinaryNativeLibsInfo.PROVIDER,
BaselineProfileProvider.PROVIDER,
AndroidNeverLinkLibrariesProvider.PROVIDER,
AndroidOptimizedJarInfo.PROVIDER,
AndroidDexInfo.PROVIDER,
AndroidOptimizationInfo.PROVIDER);
builder.addStarlarkBootstrap(bootstrap);
try {
builder.addWorkspaceFilePrefix(
ResourceFileLoader.loadResource(BazelAndroidSemantics.class, "android.WORKSPACE"));
builder.addWorkspaceFileSuffix(
ResourceFileLoader.loadResource(
BazelAndroidSemantics.class, "android_remote_tools.WORKSPACE"));
builder.addWorkspaceFileSuffix(
ResourceFileLoader.loadResource(JavaRules.class, "coverage.WORKSPACE"));
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
@Override
public ImmutableList<RuleSet> requires() {
return ImmutableList.of(CoreRules.INSTANCE, CcRules.INSTANCE, JavaRules.INSTANCE);
}
};
public static final RuleSet PYTHON_RULES =
new RuleSet() {
@Override
public void init(ConfiguredRuleClassProvider.Builder builder) {
builder.addConfigurationFragment(PythonConfiguration.class);
builder.addConfigurationFragment(BazelPythonConfiguration.class);
builder.addRuleDefinition(new BazelPyRuleClasses.PyBaseRule());
builder.addRuleDefinition(new BazelPyRuleClasses.PyBinaryBaseRule());
builder.addRuleDefinition(new EmptyRule("py_library") {});
builder.addRuleDefinition(new BazelPyBinaryRule());
builder.addRuleDefinition(new BazelPyTestRule());
builder.addRuleDefinition(new PyRuntimeRule());
// This symbol is overridden by exports.bzl
builder.addBzlToplevel(
"py_internal",
ContextGuardedValue.onlyInAllowedRepos(
Starlark.NONE, PyBootstrap.allowedRepositories));
builder.addStarlarkBuiltinsInternal(BazelPyBuiltins.NAME, new BazelPyBuiltins());
builder.addStarlarkBootstrap(new PyBootstrap());
try {
builder.addWorkspaceFileSuffix(
ResourceFileLoader.loadResource(BazelPyBinaryRule.class, "python.WORKSPACE"));
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
@Override
public ImmutableList<RuleSet> requires() {
return ImmutableList.of(CoreRules.INSTANCE, CcRules.INSTANCE);
}
};
public static final RuleSet VARIOUS_WORKSPACE_RULES =
new RuleSet() {
@Override
public void init(ConfiguredRuleClassProvider.Builder builder) {
// TODO(ulfjack): Split this up by conceptual units.
builder.addRuleDefinition(new NewLocalRepositoryRule());
builder.addRuleDefinition(new AndroidSdkRepositoryRule());
builder.addRuleDefinition(new AndroidNdkRepositoryRule());
builder.addRuleDefinition(new LocalConfigPlatformRule());
try {
builder.addWorkspaceFileSuffix(
ResourceFileLoader.loadResource(
LocalConfigPlatformRule.class, "local_config_platform.WORKSPACE"));
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
@Override
public ImmutableList<RuleSet> requires() {
return ImmutableList.of(CoreRules.INSTANCE, CoreWorkspaceRules.INSTANCE);
}
};
static final RuleSet PACKAGING_RULES =
new RuleSet() {
@Override
public void init(ConfiguredRuleClassProvider.Builder builder) {
builder.addBzlToplevel("PackageSpecificationInfo", PackageSpecificationProvider.PROVIDER);
}
};
private static final ImmutableSet<RuleSet> RULE_SETS =
ImmutableSet.of(
BAZEL_SETUP,
CoreRules.INSTANCE,
CoreWorkspaceRules.INSTANCE,
GenericRules.INSTANCE,
ConfigRules.INSTANCE,
PlatformRules.INSTANCE,
PROTO_RULES,
ShRules.INSTANCE,
CcRules.INSTANCE,
JavaRules.INSTANCE,
JAVA_PROTO_RULES,
ANDROID_RULES,
PYTHON_RULES,
ObjcRules.INSTANCE,
TestingSupportRules.INSTANCE,
VARIOUS_WORKSPACE_RULES,
PACKAGING_RULES,
// This rule set is a little special: it needs to depend on every configuration fragment
// that has Make variables, so we put it last.
ToolchainRules.INSTANCE);
@VisibleForTesting
public static String pathOrDefault(OS os, @Nullable String path, @Nullable PathFragment sh) {
// TODO(ulfjack): The default PATH should be set from the exec platform, which may be different
// from the local machine. For now, this can be overridden with --action_env=PATH=<value>, so
// at least there's a workaround.
if (os != OS.WINDOWS) {
// The default used to be "/bin:/usr/bin". However, on Mac the Python 3 interpreter, if it is
// installed at all, tends to be under /usr/local/bin. The autodetecting Python toolchain
// searches PATH for "python3", so if we don't include this directory then we can't run PY3
// targets with this toolchain if strict action environment is on.
//
// Note that --action_env does not propagate to the exec config, so it is not a viable
// workaround when a genrule is itself built in the exec config (e.g. nested genrules). See
// #8536.
return "/bin:/usr/bin:/usr/local/bin";
}
String newPath = "";
// Attempt to compute the MSYS root (the real Windows path of "/") from `sh`.
if (sh != null && sh.getParentDirectory() != null) {
newPath = sh.getParentDirectory().getPathString();
if (sh.getParentDirectory().endsWith(PathFragment.create("usr/bin"))) {
newPath +=
";" + sh.getParentDirectory().getParentDirectory().replaceName("bin").getPathString();
} else if (sh.getParentDirectory().endsWith(PathFragment.create("bin"))) {
newPath +=
";" + sh.getParentDirectory().replaceName("usr").getRelative("bin").getPathString();
}
newPath = newPath.replace('/', '\\');
}
// On Windows, the following dirs should always be available in PATH:
// C:\Windows
// C:\Windows\System32
// C:\Windows\System32\WindowsPowerShell\v1.0
// They are similar to /bin:/usr/bin, which makes the basic tools on the platform available.
String systemRoot = System.getenv("SYSTEMROOT");
if (Strings.isNullOrEmpty(systemRoot)) {
systemRoot = "C:\\Windows";
}
newPath += ";" + systemRoot;
newPath += ";" + systemRoot + "\\System32";
newPath += ";" + systemRoot + "\\System32\\WindowsPowerShell\\v1.0";
if (path != null) {
newPath += ";" + path;
}
return newPath;
}
}