diff --git a/python/private/internal_config_repo.bzl b/python/private/internal_config_repo.bzl index d5192ec44b..b208037c13 100644 --- a/python/private/internal_config_repo.bzl +++ b/python/private/internal_config_repo.bzl @@ -32,6 +32,7 @@ config = struct( enable_pystar = True, enable_pipstar = {enable_pipstar}, enable_deprecation_warnings = {enable_deprecation_warnings}, + bazel_9_or_later = {bazel_9_or_later}, BuiltinPyInfo = getattr(getattr(native, "legacy_globals", None), "PyInfo", {builtin_py_info_symbol}), BuiltinPyRuntimeInfo = getattr(getattr(native, "legacy_globals", None), "PyRuntimeInfo", {builtin_py_runtime_info_symbol}), BuiltinPyCcLinkParamsProvider = getattr(getattr(native, "legacy_globals", None), "PyCcLinkParamsProvider", {builtin_py_cc_link_params_provider}), @@ -87,7 +88,10 @@ _TRANSITION_SETTINGS_DEBUG_TEMPLATE = """ """ def _internal_config_repo_impl(rctx): - if not native.bazel_version or int(native.bazel_version.split(".")[0]) >= 8: + # An empty version signifies a development build, which is treated as + # the latest version. + bazel_major_version = int(native.bazel_version.split(".")[0]) if native.bazel_version else 99999 + if bazel_major_version >= 8: builtin_py_info_symbol = "None" builtin_py_runtime_info_symbol = "None" builtin_py_cc_link_params_provider = "None" @@ -103,6 +107,7 @@ def _internal_config_repo_impl(rctx): builtin_py_info_symbol = builtin_py_info_symbol, builtin_py_runtime_info_symbol = builtin_py_runtime_info_symbol, builtin_py_cc_link_params_provider = builtin_py_cc_link_params_provider, + bazel_9_or_later = str(bazel_major_version >= 9), )) shim_content = _PY_INTERNAL_SHIM diff --git a/python/private/py_executable.bzl b/python/private/py_executable.bzl index 669951e172..99a3dffb49 100644 --- a/python/private/py_executable.bzl +++ b/python/private/py_executable.bzl @@ -18,6 +18,7 @@ load("@bazel_skylib//lib:paths.bzl", "paths") load("@bazel_skylib//lib:structs.bzl", "structs") load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") load("@rules_cc//cc/common:cc_common.bzl", "cc_common") +load("@rules_python_internal//:rules_python_config.bzl", rp_config = "config") load(":attr_builders.bzl", "attrb") load( ":attributes.bzl", @@ -69,6 +70,7 @@ load(":venv_runfiles.bzl", "create_venv_app_files") _py_builtins = py_internal _EXTERNAL_PATH_PREFIX = "external" _ZIP_RUNFILES_DIRECTORY_NAME = "runfiles" +_LAUNCHER_MAKER_TOOLCHAIN_TYPE = "@bazel_tools//tools/launcher:launcher_maker_toolchain_type" # Non-Google-specific attributes for executables # These attributes are for rules that accept Python sources. @@ -228,17 +230,19 @@ accepting arbitrary Python versions. "@platforms//os:windows", ], ), - "_windows_launcher_maker": lambda: attrb.Label( - default = "@bazel_tools//tools/launcher:launcher_maker", - cfg = "exec", - executable = True, - ), "_zipper": lambda: attrb.Label( cfg = "exec", executable = True, default = "@bazel_tools//tools/zip:zipper", ), }, + { + "_windows_launcher_maker": lambda: attrb.Label( + default = "@bazel_tools//tools/launcher:launcher_maker", + cfg = "exec", + executable = True, + ), + } if not rp_config.bazel_9_or_later else {}, ) def convert_legacy_create_init_to_int(kwargs): @@ -777,6 +781,11 @@ def _create_stage1_bootstrap( is_executable = True, ) +def _find_launcher_maker(ctx): + if rp_config.bazel_9_or_later: + return (ctx.toolchains[_LAUNCHER_MAKER_TOOLCHAIN_TYPE].binary, _LAUNCHER_MAKER_TOOLCHAIN_TYPE) + return (ctx.executable._windows_launcher_maker, None) + def _create_windows_exe_launcher( ctx, *, @@ -796,8 +805,9 @@ def _create_windows_exe_launcher( launch_info.add("1" if use_zip_file else "0", format = "use_zip_file=%s") launcher = ctx.attr._launcher[DefaultInfo].files_to_run.executable + executable, toolchain = _find_launcher_maker(ctx) ctx.actions.run( - executable = ctx.executable._windows_launcher_maker, + executable = executable, arguments = [launcher.path, launch_info, output.path], inputs = [launcher], outputs = [output], @@ -805,6 +815,7 @@ def _create_windows_exe_launcher( progress_message = "Creating launcher for %{label}", # Needed to inherit PATH when using non-MSVC compilers like MinGW use_default_shell_env = True, + toolchain = toolchain, ) def _create_zip_file(ctx, *, output, zip_main, runfiles): @@ -1838,7 +1849,7 @@ def create_executable_rule_builder(implementation, **kwargs): ruleb.ToolchainType(TOOLCHAIN_TYPE), ruleb.ToolchainType(EXEC_TOOLS_TOOLCHAIN_TYPE, mandatory = False), ruleb.ToolchainType("@bazel_tools//tools/cpp:toolchain_type", mandatory = False), - ], + ] + ([ruleb.ToolchainType(_LAUNCHER_MAKER_TOOLCHAIN_TYPE)] if rp_config.bazel_9_or_later else []), cfg = dict( implementation = _transition_executable_impl, inputs = TRANSITION_LABELS + [labels.PYTHON_VERSION], diff --git a/tests/base_rules/py_executable_base_tests.bzl b/tests/base_rules/py_executable_base_tests.bzl index e41bc2c022..ed1a55021d 100644 --- a/tests/base_rules/py_executable_base_tests.bzl +++ b/tests/base_rules/py_executable_base_tests.bzl @@ -14,6 +14,7 @@ """Tests common to py_binary and py_test (executable rules).""" load("@rules_python//python:py_runtime_info.bzl", RulesPythonPyRuntimeInfo = "PyRuntimeInfo") +load("@rules_python_internal//:rules_python_config.bzl", rp_config = "config") load("@rules_testing//lib:analysis_test.bzl", "analysis_test") load("@rules_testing//lib:truth.bzl", "matching") load("@rules_testing//lib:util.bzl", rt_util = "util") @@ -114,6 +115,29 @@ def _test_basic_zip_impl(env, target): _tests.append(_test_basic_zip) +def _test_cross_compile_to_unix(name, config): + rt_util.helper_target( + config.rule, + name = name + "_subject", + main_module = "dummy", + ) + analysis_test( + name = name, + impl = _test_cross_compile_to_unix_impl, + target = name + "_subject", + # Cross-compilation of py_test fails since the default test toolchain + # requires an execution platform that matches the target platform. + config_settings = { + "//command_line_option:platforms": [platform_targets.EXOTIC_UNIX], + } if rp_config.bazel_9_or_later and not "py_test" in str(config.rule) else {}, + expect_failure = True, + ) + +def _test_cross_compile_to_unix_impl(_env, _target): + pass + +_tests.append(_test_cross_compile_to_unix) + def _test_executable_in_runfiles(name, config): rt_util.helper_target( config.rule, diff --git a/tests/support/platforms/BUILD.bazel b/tests/support/platforms/BUILD.bazel index 41d7936394..eeb7ccb597 100644 --- a/tests/support/platforms/BUILD.bazel +++ b/tests/support/platforms/BUILD.bazel @@ -75,3 +75,11 @@ platform( "@platforms//cpu:aarch64", ], ) + +platform( + name = "exotic_unix", + constraint_values = [ + "@platforms//os:linux", + "@platforms//cpu:s390x", + ], +) diff --git a/tests/support/platforms/platforms.bzl b/tests/support/platforms/platforms.bzl index af049f202c..92a1d61844 100644 --- a/tests/support/platforms/platforms.bzl +++ b/tests/support/platforms/platforms.bzl @@ -10,4 +10,8 @@ platform_targets = struct( WINDOWS = Label("//tests/support/platforms:windows"), WINDOWS_AARCH64 = Label("//tests/support/platforms:windows_aarch64"), WINDOWS_X86_64 = Label("//tests/support/platforms:windows_x86_64"), + + # Unspecified Unix platform that is unlikely to be the host platform in CI, + # but still provides a Python toolchain. + EXOTIC_UNIX = Label("//tests/support/platforms:exotic_unix"), )