python: Make Starlark implementation of Python rules build/pass most tests
This makes the Starlark implementation load without errors and pass almost all
of the Java unit tests for the Python rules.
* Expose `--python_path` flag via fragments to Starlark
* Remove load of Google-only toplevel_aliases to get CcInfo symbol
* Implement `imports` attribute completely/correctly; the semantics
`get_imports()` function is only for processing the `imports` attribute
itself, not all imports for a target. That is done by (the new) common
function `collect_imports()`.
* Only return OutputGroupInfo once (the `output_groups` arg of
`_create_providers()` would cause it to be returned twice.
* Make `PyCcLinkParamsProvider` usable: bind this global name to the actual
Python rule implementation instead of the C++ no-op implementation.
* Move the Python-specific `PyWrapCcInfo` and `py_wrap_cc_helper_do_not_use`
symbols out of the C++ rules and into the Python rules. This is necessary do
avoid a circular dependency between the two rule sets after moving the
`PyCcLinkParamsProvider` into the Python rules. These two symbols are still
bound to no-ops in Bazel because they are unused in the Bazel parts of the
Python rules.
* Fix an undefined variable usage in the Bazel `get_imports` function.
* Various Bazel-specific functions were slightly renamed to better distinguish
them from their common counterparts.
* Pass missing `inherited_environment` arg in `py_binary`
* Make `py_binary`, `py_test`, and `py_library` macros load and call their
respective rule implementations.
* Fix `_create_providers` returns doc.
* Implement `legacy_create_init` attribute
* Implement and fixes for `--build_python_zip`, boostrap-template-executables,
and Windows launcher executables.
* Fix computing the base executable name: `.basename` attribute, not `.name`
* Create zip and supporting files next to the executable (use the `sibling`
arg when declaring the artifacts)
* Add the zip file to files to build outputs.
* Fix undefined variable usage (`bootstrap_output`, not `bootstrap_template`)
* Add stub intended for the zip to the zip action's inputs
* Add missing methods to Bazel binary semantics object. Note that a few
features are still unimplemented (i.e. coverage).
* Fix `PLATFORMS_LOCATION` prefix (missing leading slash)
* Fix fragment name for getting `--python_path` flag.
Closes #17188. Work towards #15897.
PiperOrigin-RevId: 502656401
Change-Id: I2cbf103ca1159f8e78dacbe91fd24dd1c60e5dab
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
index bee8e13..728538f 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
@@ -102,6 +102,7 @@
import com.google.devtools.build.lib.rules.cpp.CcSharedLibraryPermissionsRule;
import com.google.devtools.build.lib.rules.cpp.CcSharedLibraryRule;
import com.google.devtools.build.lib.rules.cpp.CcStarlarkInternal;
+import com.google.devtools.build.lib.rules.cpp.GoogleLegacyStubs;
import com.google.devtools.build.lib.rules.cpp.proto.CcProtoLibraryRule;
import com.google.devtools.build.lib.rules.objc.BazelObjcStarlarkInternal;
import com.google.devtools.build.lib.rules.objc.ObjcStarlarkInternal;
@@ -111,6 +112,7 @@
import com.google.devtools.build.lib.rules.proto.ProtoConfiguration;
import com.google.devtools.build.lib.rules.proto.ProtoInfo;
import com.google.devtools.build.lib.rules.proto.ProtoLangToolchainRule;
+import com.google.devtools.build.lib.rules.python.PyCcLinkParamsProvider;
import com.google.devtools.build.lib.rules.python.PyInfo;
import com.google.devtools.build.lib.rules.python.PyRuleClasses.PySymlink;
import com.google.devtools.build.lib.rules.python.PyRuntimeInfo;
@@ -471,7 +473,12 @@
builder.addStarlarkBootstrap(
new PyBootstrap(
- PyInfo.PROVIDER, PyRuntimeInfo.PROVIDER, PyStarlarkTransitions.INSTANCE));
+ PyInfo.PROVIDER,
+ PyRuntimeInfo.PROVIDER,
+ PyStarlarkTransitions.INSTANCE,
+ new GoogleLegacyStubs.PyWrapCcHelper(),
+ new GoogleLegacyStubs.PyWrapCcInfoProvider(),
+ PyCcLinkParamsProvider.PROVIDER));
builder.addSymlinkDefinition(PySymlink.PY2);
builder.addSymlinkDefinition(PySymlink.PY3);
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/CcRules.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/CcRules.java
index b9a75e2..506b6af 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/CcRules.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/CcRules.java
@@ -41,7 +41,6 @@
import com.google.devtools.build.lib.rules.cpp.DebugPackageProvider;
import com.google.devtools.build.lib.rules.cpp.FdoPrefetchHintsRule;
import com.google.devtools.build.lib.rules.cpp.FdoProfileRule;
-import com.google.devtools.build.lib.rules.cpp.GoogleLegacyStubs;
import com.google.devtools.build.lib.rules.cpp.GraphNodeAspect;
import com.google.devtools.build.lib.rules.cpp.PropellerOptimizeRule;
import com.google.devtools.build.lib.rules.platform.PlatformRules;
@@ -97,10 +96,7 @@
new BazelCcModule(),
CcInfo.PROVIDER,
DebugPackageProvider.PROVIDER,
- CcToolchainConfigInfo.PROVIDER,
- new GoogleLegacyStubs.PyWrapCcHelper(),
- new GoogleLegacyStubs.PyWrapCcInfoProvider(),
- new GoogleLegacyStubs.PyCcLinkParamsProvider()));
+ CcToolchainConfigInfo.PROVIDER));
try {
builder.addWorkspaceFileSuffix(
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonConfiguration.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonConfiguration.java
index 1c4766a..e6afbd5 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonConfiguration.java
@@ -148,6 +148,10 @@
return options.pythonTop;
}
+ @StarlarkMethod(
+ name = "python_path",
+ structField = true,
+ doc = "The value of the --python_path flag.")
public String getPythonPath() {
return options.pythonPath == null ? "python" : options.pythonPath;
}
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/BUILD b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/BUILD
index 8892c7b..96c2878 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/BUILD
@@ -30,7 +30,6 @@
"//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/core",
"//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/go",
"//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/platform",
- "//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/python",
"//src/main/java/net/starlark/java/annot",
"//src/main/java/net/starlark/java/eval",
"//third_party:guava",
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcBootstrap.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcBootstrap.java
index ddf936b..33afd77 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcBootstrap.java
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcBootstrap.java
@@ -24,8 +24,6 @@
import com.google.devtools.build.lib.starlarkbuildapi.core.Bootstrap;
import com.google.devtools.build.lib.starlarkbuildapi.core.ContextAndFlagGuardedValue;
import com.google.devtools.build.lib.starlarkbuildapi.platform.ConstraintValueInfoApi;
-import com.google.devtools.build.lib.starlarkbuildapi.python.PyBootstrap;
-import net.starlark.java.eval.FlagGuardedValue;
/** {@link Bootstrap} for Starlark objects related to cpp rules. */
public class CcBootstrap implements Bootstrap {
@@ -70,9 +68,6 @@
private final CcInfoApi.Provider<? extends FileApi> ccInfoProvider;
private final DebugPackageInfoApi.Provider<? extends FileApi> debugPackageInfoProvider;
private final CcToolchainConfigInfoApi.Provider ccToolchainConfigInfoProvider;
- private final PyWrapCcHelperApi<?, ?, ?, ?, ?, ?, ?, ?, ?> pyWrapCcHelper;
- private final PyWrapCcInfoApi.Provider pyWrapCcInfoProvider;
- private final PyCcLinkParamsProviderApi.Provider pyCcLinkInfoParamsInfoProvider;
public CcBootstrap(
CcModuleApi<
@@ -107,17 +102,11 @@
ccModule,
CcInfoApi.Provider<? extends FileApi> ccInfoProvider,
DebugPackageInfoApi.Provider<? extends FileApi> debugPackageInfoProvider,
- CcToolchainConfigInfoApi.Provider ccToolchainConfigInfoProvider,
- PyWrapCcHelperApi<?, ?, ?, ?, ?, ?, ?, ?, ?> pyWrapCcHelper,
- PyWrapCcInfoApi.Provider pyWrapCcInfoProvider,
- PyCcLinkParamsProviderApi.Provider pyCcLinkInfoParamsInfoProvider) {
+ CcToolchainConfigInfoApi.Provider ccToolchainConfigInfoProvider) {
this.ccModule = ccModule;
this.ccInfoProvider = ccInfoProvider;
this.debugPackageInfoProvider = debugPackageInfoProvider;
this.ccToolchainConfigInfoProvider = ccToolchainConfigInfoProvider;
- this.pyWrapCcHelper = pyWrapCcHelper;
- this.pyWrapCcInfoProvider = pyWrapCcInfoProvider;
- this.pyCcLinkInfoParamsInfoProvider = pyCcLinkInfoParamsInfoProvider;
}
@Override
@@ -146,21 +135,5 @@
BuildLanguageOptions.INCOMPATIBLE_STOP_EXPORTING_LANGUAGE_MODULES,
ccToolchainConfigInfoProvider,
allowedRepositories));
- builder.put(
- "py_wrap_cc_helper_do_not_use",
- FlagGuardedValue.onlyWhenExperimentalFlagIsTrue(
- BuildLanguageOptions.EXPERIMENTAL_GOOGLE_LEGACY_API, pyWrapCcHelper));
- builder.put(
- "PyWrapCcInfo",
- ContextAndFlagGuardedValue.onlyInAllowedReposOrWhenIncompatibleFlagIsFalse(
- BuildLanguageOptions.INCOMPATIBLE_STOP_EXPORTING_LANGUAGE_MODULES,
- pyWrapCcInfoProvider,
- PyBootstrap.allowedRepositories));
- builder.put(
- "PyCcLinkParamsProvider",
- ContextAndFlagGuardedValue.onlyInAllowedReposOrWhenIncompatibleFlagIsFalse(
- BuildLanguageOptions.INCOMPATIBLE_STOP_EXPORTING_LANGUAGE_MODULES,
- pyCcLinkInfoParamsInfoProvider,
- PyBootstrap.allowedRepositories));
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/python/BUILD b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/python/BUILD
index 24e8a68..6bea525 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/python/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/python/BUILD
@@ -26,6 +26,7 @@
"//src/main/java/com/google/devtools/build/lib/packages/semantics",
"//src/main/java/com/google/devtools/build/lib/starlarkbuildapi",
"//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/core",
+ "//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp",
"//src/main/java/net/starlark/java/annot",
"//src/main/java/net/starlark/java/eval",
"//third_party:guava",
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/python/PyBootstrap.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/python/PyBootstrap.java
index 1b6c95a..fcfe03e 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/python/PyBootstrap.java
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/python/PyBootstrap.java
@@ -20,6 +20,9 @@
import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
import com.google.devtools.build.lib.starlarkbuildapi.core.Bootstrap;
import com.google.devtools.build.lib.starlarkbuildapi.core.ContextAndFlagGuardedValue;
+import com.google.devtools.build.lib.starlarkbuildapi.cpp.PyCcLinkParamsProviderApi;
+import com.google.devtools.build.lib.starlarkbuildapi.cpp.PyWrapCcHelperApi;
+import com.google.devtools.build.lib.starlarkbuildapi.cpp.PyWrapCcInfoApi;
import com.google.devtools.build.lib.starlarkbuildapi.python.PyInfoApi.PyInfoProviderApi;
import com.google.devtools.build.lib.starlarkbuildapi.python.PyRuntimeInfoApi.PyRuntimeInfoProviderApi;
import net.starlark.java.eval.FlagGuardedValue;
@@ -36,14 +39,23 @@
private final PyInfoProviderApi pyInfoProviderApi;
private final PyRuntimeInfoProviderApi pyRuntimeInfoProviderApi;
private final PyStarlarkTransitionsApi pyStarlarkTransitionsApi;
+ private final PyWrapCcHelperApi<?, ?, ?, ?, ?, ?, ?, ?, ?> pyWrapCcHelper;
+ private final PyWrapCcInfoApi.Provider pyWrapCcInfoProvider;
+ private final PyCcLinkParamsProviderApi.Provider pyCcLinkInfoParamsInfoProvider;
public PyBootstrap(
PyInfoProviderApi pyInfoProviderApi,
PyRuntimeInfoProviderApi pyRuntimeInfoProviderApi,
- PyStarlarkTransitionsApi pyStarlarkTransitionsApi) {
+ PyStarlarkTransitionsApi pyStarlarkTransitionsApi,
+ PyWrapCcHelperApi<?, ?, ?, ?, ?, ?, ?, ?, ?> pyWrapCcHelper,
+ PyWrapCcInfoApi.Provider pyWrapCcInfoProvider,
+ PyCcLinkParamsProviderApi.Provider pyCcLinkInfoParamsInfoProvider) {
this.pyInfoProviderApi = pyInfoProviderApi;
this.pyRuntimeInfoProviderApi = pyRuntimeInfoProviderApi;
this.pyStarlarkTransitionsApi = pyStarlarkTransitionsApi;
+ this.pyWrapCcHelper = pyWrapCcHelper;
+ this.pyWrapCcInfoProvider = pyWrapCcInfoProvider;
+ this.pyCcLinkInfoParamsInfoProvider = pyCcLinkInfoParamsInfoProvider;
}
@Override
@@ -65,5 +77,21 @@
"py_transitions",
FlagGuardedValue.onlyWhenExperimentalFlagIsTrue(
BuildLanguageOptions.EXPERIMENTAL_GOOGLE_LEGACY_API, pyStarlarkTransitionsApi));
+ builder.put(
+ "py_wrap_cc_helper_do_not_use",
+ FlagGuardedValue.onlyWhenExperimentalFlagIsTrue(
+ BuildLanguageOptions.EXPERIMENTAL_GOOGLE_LEGACY_API, pyWrapCcHelper));
+ builder.put(
+ "PyWrapCcInfo",
+ ContextAndFlagGuardedValue.onlyInAllowedReposOrWhenIncompatibleFlagIsFalse(
+ BuildLanguageOptions.INCOMPATIBLE_STOP_EXPORTING_LANGUAGE_MODULES,
+ pyWrapCcInfoProvider,
+ allowedRepositories));
+ builder.put(
+ "PyCcLinkParamsProvider",
+ ContextAndFlagGuardedValue.onlyInAllowedReposOrWhenIncompatibleFlagIsFalse(
+ BuildLanguageOptions.INCOMPATIBLE_STOP_EXPORTING_LANGUAGE_MODULES,
+ pyCcLinkInfoParamsInfoProvider,
+ allowedRepositories));
}
}
diff --git a/src/main/starlark/builtins_bzl/common/python/attributes.bzl b/src/main/starlark/builtins_bzl/common/python/attributes.bzl
index 987f4d5..f00b575 100644
--- a/src/main/starlark/builtins_bzl/common/python/attributes.bzl
+++ b/src/main/starlark/builtins_bzl/common/python/attributes.bzl
@@ -15,7 +15,6 @@
load(":common/python/common.bzl", "union_attrs")
load(":common/python/providers.bzl", "PyInfo")
-load(":blaze/common/toplevel_aliases.bzl", "CcInfo")
load(
":common/python/semantics.bzl",
"DEPS_ATTR_ALLOW_RULES",
@@ -24,6 +23,7 @@
"TOOLS_REPO",
)
+_CcInfo = _builtins.toplevel.CcInfo
_STAMP_VALUES = [-1, 0, 1]
def create_stamp_attr(**kwargs):
@@ -104,7 +104,7 @@
# Use create_srcs_attr to create one.
"srcs": None,
"deps": attr.label_list(
- providers = [[PyInfo], [CcInfo]],
+ providers = [[PyInfo], [_CcInfo]],
# TODO(b/228692666): Google-specific; remove these allowances once
# the depot is cleaned up.
allow_rules = DEPS_ATTR_ALLOW_RULES,
diff --git a/src/main/starlark/builtins_bzl/common/python/common.bzl b/src/main/starlark/builtins_bzl/common/python/common.bzl
index 8224ac3..a05b774 100644
--- a/src/main/starlark/builtins_bzl/common/python/common.bzl
+++ b/src/main/starlark/builtins_bzl/common/python/common.bzl
@@ -29,7 +29,6 @@
# Extensions without the dot
_PYTHON_SOURCE_EXTENSIONS = ["py"]
-# Todo: rename this to "binary" and split off library-parts
def create_binary_semantics_struct(
*,
create_executable,
@@ -74,8 +73,9 @@
of additional environment variable to pass to build data generation.
get_interpreter_path: Callable that returns an optional string, which is
the path to the Python interpreter to use for running the binary.
- get_imports: Callable that returns a depset of the target's import
- paths.
+ get_imports: Callable that returns a list of the target's import
+ paths (from the `imports` attribute, so just the target's own import
+ path strings, not from dependencies).
get_native_deps_dso_name: Callable that returns a string, which is the
basename (with extension) of the native deps DSO library.
get_native_deps_user_link_flags: Callable that returns a list of strings,
@@ -253,6 +253,13 @@
# as a valid extension.
return [f for f in srcs if f.extension == "py"]
+def collect_imports(ctx, semantics):
+ return depset(direct = semantics.get_imports(ctx), transitive = [
+ dep[PyInfo].imports
+ for dep in ctx.attr.deps
+ if PyInfo in dep
+ ])
+
def collect_runfiles(ctx, files):
"""Collects the necessary files from the rule's context.
@@ -402,10 +409,11 @@
extensions = _PYTHON_SOURCE_EXTENSIONS,
)
-def create_output_group_info(transitive_sources):
+def create_output_group_info(transitive_sources, extra_groups):
return OutputGroupInfo(
compilation_prerequisites_INTERNAL_ = transitive_sources,
compilation_outputs = transitive_sources,
+ **extra_groups
)
def maybe_add_test_execution_info(providers, ctx):
diff --git a/src/main/starlark/builtins_bzl/common/python/common_bazel.bzl b/src/main/starlark/builtins_bzl/common/python/common_bazel.bzl
index 1ae55e3..125bcc3 100644
--- a/src/main/starlark/builtins_bzl/common/python/common_bazel.bzl
+++ b/src/main/starlark/builtins_bzl/common/python/common_bazel.bzl
@@ -13,6 +13,8 @@
# limitations under the License.
"""Common functions that are specific to Bazel rule implementation"""
+load(":common/python/providers.bzl", "PyCcLinkParamsProvider")
+
_py_builtins = _builtins.internal.py_builtins
_CcInfo = _builtins.toplevel.CcInfo
_cc_common = _builtins.toplevel.cc_common
@@ -35,8 +37,10 @@
for dep in deps:
if _CcInfo in dep:
cc_infos.append(dep[_CcInfo])
+
if PyCcLinkParamsProvider in dep:
cc_infos.append(dep[PyCcLinkParamsProvider].cc_info)
+
return _cc_common.merge_cc_infos(cc_infos = cc_infos)
def maybe_precompile(ctx, srcs):
@@ -72,12 +76,15 @@
)
result = []
for import_str in ctx.attr.imports:
+ # todo: check if $(location) expansion is done here
import_str = ctx.expand_make_variables(import_str)
if import_str.startswith("/"):
continue
- import_path = "{}/{}".format(prefix, expanded)
+ import_path = "{}/{}".format(prefix, import_str)
# TODO: Reject paths with uplevel references (see
- # PathFragment#containsUplevelReferences)
+ # PathFragment#containsUplevelReferences). Basically, we want to
+ # prevent imports="../../../../../" (or similar) from "escaping" out
+ # of the runfiles tree.
result.append(import_path)
return result
diff --git a/src/main/starlark/builtins_bzl/common/python/py_binary_bazel.bzl b/src/main/starlark/builtins_bzl/common/python/py_binary_bazel.bzl
index 726676f..abd9a29 100644
--- a/src/main/starlark/builtins_bzl/common/python/py_binary_bazel.bzl
+++ b/src/main/starlark/builtins_bzl/common/python/py_binary_bazel.bzl
@@ -17,7 +17,7 @@
load(
":common/python/py_executable_bazel.bzl",
"create_executable_rule",
- "py_executable_impl",
+ "py_executable_bazel_impl",
)
load(":common/python/attributes.bzl", "AGNOSTIC_BINARY_ATTRS")
@@ -35,7 +35,11 @@
}
def _py_binary_impl(ctx):
- return py_executable_impl(ctx = ctx, is_test = False)
+ return py_executable_bazel_impl(
+ ctx = ctx,
+ is_test = False,
+ inherited_environment = [],
+ )
py_binary = create_executable_rule(
implementation = _py_binary_impl,
diff --git a/src/main/starlark/builtins_bzl/common/python/py_binary_macro.bzl b/src/main/starlark/builtins_bzl/common/python/py_binary_macro.bzl
index 82f15a26..833c98f 100644
--- a/src/main/starlark/builtins_bzl/common/python/py_binary_macro.bzl
+++ b/src/main/starlark/builtins_bzl/common/python/py_binary_macro.bzl
@@ -13,6 +13,7 @@
# limitations under the License.
"""Implementation of macro-half of py_binary rule."""
+load(":common/python/py_binary_bazel.bzl", py_binary_rule = "py_binary")
+
def py_binary(**kwargs):
- _ = kwargs # @unused
- pass
+ py_binary_rule(**kwargs)
diff --git a/src/main/starlark/builtins_bzl/common/python/py_executable.bzl b/src/main/starlark/builtins_bzl/common/python/py_executable.bzl
index 1591a65..bc8b63c 100644
--- a/src/main/starlark/builtins_bzl/common/python/py_executable.bzl
+++ b/src/main/starlark/builtins_bzl/common/python/py_executable.bzl
@@ -17,6 +17,7 @@
load(
":common/python/common.bzl",
"TOOLCHAIN_TYPE",
+ "collect_imports",
"collect_runfiles",
"create_instrumented_files_info",
"create_output_group_info",
@@ -108,7 +109,7 @@
main_py = determine_main(ctx)
direct_sources = filter_to_py_srcs(ctx.files.srcs)
output_sources = semantics.maybe_precompile(ctx, direct_sources)
- imports = semantics.get_imports(ctx)
+ imports = collect_imports(ctx, semantics)
executable, files_to_build = _compute_outputs(ctx, output_sources)
runtime_details = _get_runtime_details(ctx, semantics)
@@ -671,8 +672,9 @@
semantics: BinarySemantics struct; see create_binary_semantics()
Returns:
- A value that rules can return. i.e. a list of providers or
- a struct of providers.
+ A two-tuple of:
+ 1. A dict of legacy providers.
+ 2. A list of modern providers.
"""
providers = [
DefaultInfo(
@@ -707,7 +709,7 @@
)
providers.append(py_info)
- providers.append(create_output_group_info(py_info.transitive_sources))
+ providers.append(create_output_group_info(py_info.transitive_sources, output_groups))
extra_legacy_providers, extra_providers = semantics.get_extra_providers(
ctx,
@@ -715,9 +717,6 @@
runtime_details = runtime_details,
)
providers.extend(extra_providers)
- if output_groups:
- providers.append(OutputGroupInfo(**output_groups))
-
return extra_legacy_providers, providers
def _create_run_environment_info(ctx, inherited_environment):
diff --git a/src/main/starlark/builtins_bzl/common/python/py_executable_bazel.bzl b/src/main/starlark/builtins_bzl/common/python/py_executable_bazel.bzl
index 7c6a660..eca06cd 100644
--- a/src/main/starlark/builtins_bzl/common/python/py_executable_bazel.bzl
+++ b/src/main/starlark/builtins_bzl/common/python/py_executable_bazel.bzl
@@ -13,16 +13,49 @@
# limitations under the License.
"""Implementation for Bazel Python executable."""
+load(":common/paths.bzl", "paths")
load(":common/python/attributes_bazel.bzl", "IMPORTS_ATTRS")
-load(":common/python/common_bazel.bzl", "collect_cc_info")
+load(
+ ":common/python/common.bzl",
+ "create_binary_semantics_struct",
+ "create_cc_details_struct",
+ "create_executable_result_struct",
+ "union_attrs",
+)
+load(":common/python/common_bazel.bzl", "collect_cc_info", "get_imports", "maybe_precompile")
load(":common/python/providers.bzl", "DEFAULT_STUB_SHEBANG")
-load(":common/python/py_executable.bzl", "py_executable_base_impl")
+load(
+ ":common/python/py_executable.bzl",
+ "create_base_executable_rule",
+ "py_executable_base_impl",
+)
load(":common/python/semantics.bzl", "TOOLS_REPO")
+_py_builtins = _builtins.internal.py_builtins
+_EXTERNAL_PATH_PREFIX = "external"
+_ZIP_RUNFILES_DIRECTORY_NAME = "runfiles"
+
BAZEL_EXECUTABLE_ATTRS = union_attrs(
IMPORTS_ATTRS,
{
- "_zipper": attr.label(cfg = "exec"),
+ "legacy_create_init": attr.int(
+ default = -1,
+ values = [-1, 0, 1],
+ doc = """\
+Whether to implicitly create empty `__init__.py` files in the runfiles tree.
+These are created in every directory containing Python source code or shared
+libraries, and every parent directory of those directories, excluding the repo
+root directory. The default, `-1` (auto), means true unless
+`--incompatible_default_to_explicit_init_py` is used. If false, the user is
+responsible for creating (possibly empty) `__init__.py` files and adding them to
+the `srcs` of Python targets as required.
+ """,
+ ),
+ "_zipper": attr.label(
+ cfg = "exec",
+ executable = True,
+ default = "@" + TOOLS_REPO + "//tools/zip:zipper",
+ ),
"_launcher": attr.label(
cfg = "target",
default = "@" + TOOLS_REPO + "//tools/launcher:launcher",
@@ -35,6 +68,10 @@
# TODO: Remove this attribute; it's basically a no-op in Bazel due
# to toolchain resolution.
"_py_interpreter": attr.label(),
+ "_bootstrap_template": attr.label(
+ allow_single_file = True,
+ default = "@" + TOOLS_REPO + "//tools/python:python_bootstrap_template.txt",
+ ),
},
)
@@ -45,7 +82,8 @@
**kwargs
)
-def py_executable_impl(ctx, *, is_test, inherited_environment):
+def py_executable_bazel_impl(ctx, *, is_test, inherited_environment):
+ """Common code for executables for Baze."""
result = py_executable_base_impl(
ctx = ctx,
semantics = create_binary_semantics_bazel(),
@@ -58,17 +96,51 @@
)
def create_binary_semantics_bazel():
- return create_binary_semantics_bazel_common(
+ return create_binary_semantics_struct(
# keep-sorted start
create_executable = _create_executable,
get_cc_details_for_binary = _get_cc_details_for_binary,
+ get_central_uncachable_version_file = lambda ctx: None,
+ get_coverage_deps = _get_coverage_deps,
+ get_debugger_deps = _get_debugger_deps,
+ get_extra_common_runfiles_for_binary = lambda ctx: ctx.runfiles(),
+ get_extra_providers = _get_extra_providers,
+ get_extra_write_build_data_env = lambda ctx: {},
+ get_imports = get_imports,
get_interpreter_path = _get_interpreter_path,
get_native_deps_dso_name = _get_native_deps_dso_name,
get_native_deps_user_link_flags = _get_native_deps_user_link_flags,
- should_build_native_deps_dso = _should_build_native_deps_dso,
+ get_stamp_flag = _get_stamp_flag,
+ maybe_precompile = maybe_precompile,
+ should_build_native_deps_dso = lambda ctx: False,
+ should_create_init_files = _should_create_init_files,
+ should_include_build_data = lambda ctx: False,
# keep-sorted end
)
+# todo: implement by getting coverage files from the runtime
+def _get_coverage_deps(ctx, runtime_details):
+ _ = ctx, runtime_details # @unused
+ return []
+
+def _get_debugger_deps(ctx, runtime_details):
+ _ = ctx, runtime_details # @unused
+ return []
+
+def _get_extra_providers(ctx, main_py, runtime_details):
+ _ = ctx, main_py, runtime_details # @unused
+ return {}, []
+
+def _get_stamp_flag(ctx):
+ # NOTE: Undocumented API; private to builtins
+ return ctx.configuration.stamp_binaries
+
+def _should_create_init_files(ctx):
+ if ctx.attr.legacy_create_init == -1:
+ return ctx.fragments.py.default_to_explicit_init_py
+ else:
+ return bool(ctx.attr.legacy_create_init)
+
def _create_executable(
ctx,
*,
@@ -95,12 +167,12 @@
if is_windows:
if not executable.name.extension == "exe":
fail("Should not happen: somehow we are generating a non-.exe file on windows")
- base_executable_name = executable.name[0:-4]
+ base_executable_name = executable.basename[0:-4]
else:
- base_executable_name = executable.name
+ base_executable_name = executable.basename
- zip_bootstrap = ctx.actions.declare(base_executable_name + ".temp")
- zip_file = ctx.actions.declare(base_executable_name + ".zip")
+ zip_bootstrap = ctx.actions.declare_file(base_executable_name + ".temp", sibling = executable)
+ zip_file = ctx.actions.declare_file(base_executable_name + ".zip", sibling = executable)
_expand_bootstrap_template(
ctx,
@@ -112,10 +184,11 @@
ctx,
output = zip_file,
original_nonzip_executable = executable,
- zipfile_executable = zip_bootstrap,
+ executable_for_zip_file = zip_bootstrap,
runfiles = runfiles_details.default_runfiles,
)
+ extra_files_to_build = []
build_zip_enabled = ctx.fragments.py.build_python_zip
# When --build_python_zip is enabled, then the zip file becomes
@@ -155,17 +228,17 @@
extra_files_to_build.append(bootstrap_output)
if should_create_executable_zip:
- if bootstrap_template != None:
- fail("Should not occur: bootstrap_template should not be used " +
+ if bootstrap_output != None:
+ fail("Should not occur: bootstrap_output should not be used " +
"when creating an executable zip")
_create_executable_zip_file(ctx, output = executable, zip_file = zip_file)
else:
- if bootstrap_template == None:
- fail("Should not occur: bootstrap_template should set when " +
+ if bootstrap_output == None:
+ fail("Should not occur: bootstrap_output should set when " +
"build a bootstrap-template-based executable")
_expand_bootstrap_template(
ctx,
- output = bootstrap_template,
+ output = bootstrap_output,
is_for_zip = build_zip_enabled,
**common_bootstrap_template_kwargs
)
@@ -243,7 +316,7 @@
progress_message = "Creating launcher for %{label}",
)
-def _create_zip_file(ctx, *, zip_file, original_nonzip_executable, zip_executable, runfiles):
+def _create_zip_file(ctx, *, output, original_nonzip_executable, executable_for_zip_file, runfiles):
workspace_name = ctx.workspace_name
legacy_external_runfiles = _py_builtins.get_legacy_external_runfiles(ctx)
@@ -251,7 +324,7 @@
manifest.use_param_file("%s", use_always = True)
manifest.set_param_file_format("multiline")
- manifest.add("__main__.py=%s", zip_executable)
+ manifest.add("__main__.py=%s", executable_for_zip_file)
manifest.add("__init__.py=")
manifest.add(
"%s=",
@@ -261,7 +334,7 @@
manifest.add("%s=", _get_zip_runfiles_path(path, workspace_name, legacy_external_runfiles))
def map_zip_runfiles(file):
- if file != original_nonzip_executable and file != zip_file:
+ if file != original_nonzip_executable and file != output:
return "{}={}".format(
_get_zip_runfiles_path(file.short_path, workspace_name, legacy_external_runfiles),
file.path,
@@ -270,22 +343,22 @@
return None
manifest.add_all(runfiles.files, map_each = map_zip_runfiles, allow_closure = True)
- inputs = []
+ inputs = [executable_for_zip_file]
for artifact in runfiles.files.to_list():
# Don't include the original executable because it isn't used by the
# zip file, so no need to build it for the action.
# Don't include the zipfile itself because it's an output.
- if artifact != original_nonzip_executable and artifact != zip_file:
+ if artifact != original_nonzip_executable and artifact != output:
inputs.append(artifact)
zip_cli_args = ctx.actions.args()
zip_cli_args.add("cC")
- zip_cli_args.add(zip_file)
+ zip_cli_args.add(output)
ctx.actions.run(
executable = ctx.executable._zipper,
arguments = [zip_cli_args, manifest],
inputs = depset(inputs),
- outputs = [zip_file],
+ outputs = [output],
use_default_shell_env = True,
mnemonic = "PythonZipper",
progress_message = "Building Python zip: %{label}",
@@ -293,10 +366,10 @@
def _get_zip_runfiles_path(path, workspace_name, legacy_external_runfiles):
if legacy_external_runfiles and path.startswith(_EXTERNAL_PATH_PREFIX):
- zip_runfiles_path = path.relativeTo(EXTERNAL_PATH_PREFIX)
+ zip_runfiles_path = paths.relativize(_EXTERNAL_PATH_PREFIX, path)
else:
zip_runfiles_path = "{}/{}".format(workspace_name, path)
- return ZIP_RUNFILES_DIRECTORY_NAME.getRelative(zip_runfiles_path)
+ return "{}/{}".format(_ZIP_RUNFILES_DIRECTORY_NAME, zip_runfiles_path)
def _create_executable_zip_file(ctx, *, output, zip_file):
ctx.actions.run_shell(
diff --git a/src/main/starlark/builtins_bzl/common/python/py_library.bzl b/src/main/starlark/builtins_bzl/common/python/py_library.bzl
index c0ebbf3..a9b36fd 100644
--- a/src/main/starlark/builtins_bzl/common/python/py_library.bzl
+++ b/src/main/starlark/builtins_bzl/common/python/py_library.bzl
@@ -23,6 +23,7 @@
)
load(
":common/python/common.bzl",
+ "collect_imports",
"collect_runfiles",
"create_instrumented_files_info",
"create_output_group_info",
@@ -58,7 +59,7 @@
py_info, deps_transitive_sources = create_py_info(
ctx,
direct_sources = depset(direct_sources),
- imports = semantics.get_imports(ctx),
+ imports = collect_imports(ctx, semantics),
)
# TODO(b/253059598): Remove support for extra actions; https://github.com/bazelbuild/bazel/issues/16455
@@ -74,7 +75,7 @@
py_info,
create_instrumented_files_info(ctx),
_py_builtins.new_py_cc_link_params_provider(cc_info = cc_info),
- create_output_group_info(py_info.transitive_sources),
+ create_output_group_info(py_info.transitive_sources, extra_groups = {}),
]
def create_py_library_rule(*, attrs = {}, **kwargs):
diff --git a/src/main/starlark/builtins_bzl/common/python/py_library_bazel.bzl b/src/main/starlark/builtins_bzl/common/python/py_library_bazel.bzl
index 6d306d3e..b844b97 100644
--- a/src/main/starlark/builtins_bzl/common/python/py_library_bazel.bzl
+++ b/src/main/starlark/builtins_bzl/common/python/py_library_bazel.bzl
@@ -14,16 +14,19 @@
"""Implementation of py_library for Bazel."""
load(
- ":common/python/attributes.bzl",
- "IMPORTS_ATTR",
+ ":common/python/attributes_bazel.bzl",
+ "IMPORTS_ATTRS",
)
load(
":common/python/common.bzl",
- "collect_cc_info",
"create_library_semantics_struct",
+ "union_attrs",
+)
+load(
+ ":common/python/common_bazel.bzl",
+ "collect_cc_info",
"get_imports",
"maybe_precompile",
- "union_attrs",
)
load(
":common/python/py_library.bzl",
@@ -34,7 +37,7 @@
_BAZEL_LIBRARY_ATTRS = union_attrs(
LIBRARY_ATTRS,
- IMPORTS_ATTR,
+ IMPORTS_ATTRS,
)
def create_library_semantics_bazel():
diff --git a/src/main/starlark/builtins_bzl/common/python/py_library_macro.bzl b/src/main/starlark/builtins_bzl/common/python/py_library_macro.bzl
index a93edfa..729c426 100644
--- a/src/main/starlark/builtins_bzl/common/python/py_library_macro.bzl
+++ b/src/main/starlark/builtins_bzl/common/python/py_library_macro.bzl
@@ -13,6 +13,7 @@
# limitations under the License.
"""Implementation of macro-half of py_library rule."""
+load(":common/python/py_library_bazel.bzl", py_library_rule = "py_library")
+
def py_library(**kwargs):
- _ = kwargs # @unused
- pass
+ py_library_rule(**kwargs)
diff --git a/src/main/starlark/builtins_bzl/common/python/py_test_bazel.bzl b/src/main/starlark/builtins_bzl/common/python/py_test_bazel.bzl
index 2310620..0a9f3ff 100644
--- a/src/main/starlark/builtins_bzl/common/python/py_test_bazel.bzl
+++ b/src/main/starlark/builtins_bzl/common/python/py_test_bazel.bzl
@@ -13,11 +13,13 @@
# limitations under the License.
"""Rule implementation of py_test for Bazel."""
+load(":common/python/semantics.bzl", "TOOLS_REPO")
load(
":common/python/py_executable_bazel.bzl",
"create_executable_rule",
- "py_executable_impl",
+ "py_executable_bazel_impl",
)
+load(":common/python/common.bzl", "maybe_add_test_execution_info")
load(":common/python/attributes.bzl", "AGNOSTIC_TEST_ATTRS")
_BAZEL_PY_TEST_ATTRS = {
@@ -38,7 +40,7 @@
}
def _py_test_impl(ctx):
- providers = py_executable_impl(
+ providers = py_executable_bazel_impl(
ctx = ctx,
is_test = True,
inherited_environment = ctx.attr.env_inherit,
diff --git a/src/main/starlark/builtins_bzl/common/python/py_test_macro.bzl b/src/main/starlark/builtins_bzl/common/python/py_test_macro.bzl
index 700ea8e..9a3b491 100644
--- a/src/main/starlark/builtins_bzl/common/python/py_test_macro.bzl
+++ b/src/main/starlark/builtins_bzl/common/python/py_test_macro.bzl
@@ -13,6 +13,7 @@
# limitations under the License.
"""Implementation of macro-half of py_test rule."""
+load(":common/python/py_test_bazel.bzl", py_test_rule = "py_test")
+
def py_test(**kwargs):
- _ = kwargs # @unused
- pass
+ py_test_rule(**kwargs)
diff --git a/src/main/starlark/builtins_bzl/common/python/semantics.bzl b/src/main/starlark/builtins_bzl/common/python/semantics.bzl
index d60bb4c..af8848e 100644
--- a/src/main/starlark/builtins_bzl/common/python/semantics.bzl
+++ b/src/main/starlark/builtins_bzl/common/python/semantics.bzl
@@ -16,14 +16,14 @@
IMPORTS_ATTR_SUPPORTED = True
TOOLS_REPO = "bazel_tools"
-PLATFORMS_LOCATION = "@platforms"
+PLATFORMS_LOCATION = "@platforms/"
SRCS_ATTR_ALLOW_FILES = [".py", ".py3"]
DEPS_ATTR_ALLOW_RULES = None
PY_RUNTIME_ATTR_NAME = "_py_interpreter"
-PY_RUNTIME_FRAGMENT_NAME = "py"
+PY_RUNTIME_FRAGMENT_NAME = "bazel_py"
PY_RUNTIME_FRAGMENT_ATTR_NAME = "python_path"
BUILD_DATA_SYMLINK_PATH = "pyglib/build_data.txt"