diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f02c8bbb4..c5c2ad1212 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -104,6 +104,7 @@ END_UNRELEASED_TEMPLATE * 3.12.11 * 3.13.5 * 3.14.0b3 +* (rules) {obj}`main_module` now works without needing to set {obj}`--bootstrap_impl=script` {#v0-0-0-removed} ### Removed diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e1bd11b81d..3a384a74a0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -122,7 +122,7 @@ the [Breaking Changes](#breaking-changes) section for how to introduce breaking changes. User visible changes, such as features, fixes, or notable refactors, should -be documneted in CHANGELOG.md and their respective API doc. See [Documenting +be documented in CHANGELOG.md and their respective API doc. See [Documenting changes] for how to do so. Common `type`s: diff --git a/python/private/main_module_entrypoint_template.py b/python/private/main_module_entrypoint_template.py new file mode 100644 index 0000000000..e0f6778b29 --- /dev/null +++ b/python/private/main_module_entrypoint_template.py @@ -0,0 +1,9 @@ +""" +A shim to get `main_module` working with `bootstrap_impl=system_python`. +""" + +import os +import runpy + +if __name__ == "__main__": + runpy.run_module("%main_module%", run_name="__main__", alter_sys=True) diff --git a/python/private/py_executable.bzl b/python/private/py_executable.bzl index 7e50247e61..705416d209 100644 --- a/python/private/py_executable.bzl +++ b/python/private/py_executable.bzl @@ -201,6 +201,10 @@ accepting arbitrary Python versions. # empty target for other platforms. default = "//tools/launcher:launcher", ), + "_main_module_entrypoint_template": lambda: attrb.Label( + allow_single_file = True, + default = "//python/private:main_module_entrypoint_template.py", + ), "_py_interpreter": lambda: attrb.Label( # The configuration_field args are validated when called; # we use the precense of py_internal to indicate this Bazel @@ -360,9 +364,8 @@ def _create_executable( ) else: stage2_bootstrap = None - extra_runfiles = ctx.runfiles() zip_main = ctx.actions.declare_file(base_executable_name + ".temp", sibling = executable) - _create_stage1_bootstrap( + extra_runfiles = _create_stage1_bootstrap( ctx, output = zip_main, main_py = main_py, @@ -426,7 +429,7 @@ def _create_executable( if bootstrap_output != None: fail("Should not occur: bootstrap_output should not be used " + "when creating an executable zip") - _create_executable_zip_file( + more_runfiles = _create_executable_zip_file( ctx, output = executable, zip_file = zip_file, @@ -434,8 +437,9 @@ def _create_executable( runtime_details = runtime_details, venv = venv, ) + extra_runfiles = extra_runfiles.merge(more_runfiles) elif bootstrap_output: - _create_stage1_bootstrap( + more_runfiles = _create_stage1_bootstrap( ctx, output = bootstrap_output, stage2_bootstrap = stage2_bootstrap, @@ -445,6 +449,7 @@ def _create_executable( main_py = main_py, venv = venv, ) + extra_runfiles = extra_runfiles.merge(more_runfiles) else: # Otherwise, this should be the Windows case of launcher + zip. # Double check this just to make sure. @@ -796,6 +801,7 @@ def _create_stage1_bootstrap( is_for_zip, runtime_details, venv = None): + extra_runfiles = ctx.runfiles() runtime = runtime_details.effective_runtime if venv: @@ -833,9 +839,10 @@ def _create_stage1_bootstrap( ) template = runtime.bootstrap_template subs["%shebang%"] = runtime.stub_shebang - elif not ctx.files.srcs: - fail("mandatory 'srcs' files have not been provided") else: + if not ctx.files.srcs and not ctx.attr.main_module: + fail("mandatory 'srcs' files have not been provided") + if (ctx.configuration.coverage_enabled and runtime and runtime.coverage_tool): @@ -855,6 +862,20 @@ def _create_stage1_bootstrap( subs["%coverage_tool%"] = coverage_tool_runfiles_path subs["%import_all%"] = ("True" if ctx.fragments.bazel_py.python_import_all_repositories else "False") subs["%imports%"] = ":".join(imports.to_list()) + + if ctx.attr.main_module: + main_module_entrypoint = ctx.actions.declare_file("main_module_entrypoint.py") + ctx.actions.expand_template( + template = ctx.file._main_module_entrypoint_template, + output = main_module_entrypoint, + substitutions = {"%main_module%": ctx.attr.main_module}, + ) + main_py = main_module_entrypoint + extra_runfiles = extra_runfiles.merge(ctx.runfiles([main_module_entrypoint])) + elif not main_py: + # shouldn't happen + fail("Neither main nor main_module was provided") + subs["%main%"] = "{}/{}".format(ctx.workspace_name, main_py.short_path) ctx.actions.expand_template( @@ -863,6 +884,8 @@ def _create_stage1_bootstrap( substitutions = subs, ) + return extra_runfiles + def _create_windows_exe_launcher( ctx, *, @@ -985,7 +1008,7 @@ def _create_executable_zip_file( sibling = output, ) if stage2_bootstrap: - _create_stage1_bootstrap( + extra_runfiles = _create_stage1_bootstrap( ctx, output = prelude, stage2_bootstrap = stage2_bootstrap, @@ -994,6 +1017,7 @@ def _create_executable_zip_file( venv = venv, ) else: + extra_runfiles = ctx.runfiles() ctx.actions.write(prelude, "#!/usr/bin/env python3\n") ctx.actions.run_shell( @@ -1009,6 +1033,8 @@ def _create_executable_zip_file( progress_message = "Build Python zip executable: %{label}", ) + return extra_runfiles + def _get_cc_details_for_binary(ctx, extra_deps): cc_info = collect_cc_info(ctx, extra_deps = extra_deps) return create_cc_details_struct( diff --git a/tests/base_rules/py_executable_base_tests.bzl b/tests/base_rules/py_executable_base_tests.bzl index 49cbb1586c..d22a06f2bc 100644 --- a/tests/base_rules/py_executable_base_tests.bzl +++ b/tests/base_rules/py_executable_base_tests.bzl @@ -363,8 +363,8 @@ def _test_main_module_bootstrap_system_python(name, config): ) def _test_main_module_bootstrap_system_python_impl(env, target): - env.expect.that_target(target).failures().contains_predicate( - matching.str_matches("mandatory*srcs"), + env.expect.that_target(target).default_outputs().contains( + "{package}/{test_name}_subject", ) _tests.append(_test_main_module_bootstrap_system_python) diff --git a/tests/bootstrap_impls/BUILD.bazel b/tests/bootstrap_impls/BUILD.bazel index c3d44df240..5f3d1cde28 100644 --- a/tests/bootstrap_impls/BUILD.bazel +++ b/tests/bootstrap_impls/BUILD.bazel @@ -13,6 +13,7 @@ # limitations under the License. load("@rules_pkg//pkg:tar.bzl", "pkg_tar") load("@rules_shell//shell:sh_test.bzl", "sh_test") +load("//python:defs.bzl", "py_library") load("//tests/support:py_reconfig.bzl", "py_reconfig_binary", "py_reconfig_test") load("//tests/support:sh_py_run_test.bzl", "sh_py_run_test") load("//tests/support:support.bzl", "SUPPORTS_BOOTSTRAP_SCRIPT") @@ -123,13 +124,25 @@ py_reconfig_test( main = "sys_path_order_test.py", ) -py_reconfig_test( - name = "main_module_test", +py_library( + name = "main_module_lib", srcs = ["main_module.py"], - bootstrap_impl = "script", imports = ["."], +) + +py_reconfig_test( + name = "main_module_script_test", + bootstrap_impl = "script", main_module = "tests.bootstrap_impls.main_module", target_compatible_with = SUPPORTS_BOOTSTRAP_SCRIPT, + deps = [":main_module_lib"], +) + +py_reconfig_test( + name = "main_module_system_python_test", + bootstrap_impl = "system_python", + main_module = "tests.bootstrap_impls.main_module", + deps = [":main_module_lib"], ) sh_py_run_test( pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy