Skip to content

Commit 94428b0

Browse files
committed
feat: Support main_module with bootstrap_impl=system_python
1 parent 8f11a0f commit 94428b0

File tree

4 files changed

+44
-8
lines changed

4 files changed

+44
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ END_UNRELEASED_TEMPLATE
102102
* 3.12.11
103103
* 3.13.5
104104
* 3.14.0b3
105+
* (rules) `main_module` now works without needing to set `bootstrap_impl=script`
105106

106107
{#v0-0-0-removed}
107108
### Removed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ the [Breaking Changes](#breaking-changes) section for how to introduce breaking
122122
changes.
123123

124124
User visible changes, such as features, fixes, or notable refactors, should
125-
be documneted in CHANGELOG.md and their respective API doc. See [Documenting
125+
be documented in CHANGELOG.md and their respective API doc. See [Documenting
126126
changes] for how to do so.
127127

128128
Common `type`s:
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"""
2+
A shim to get `main_module` working with `bootstrap_impl=system_python`.
3+
"""
4+
5+
import os
6+
import runpy
7+
8+
if __name__ == '__main__':
9+
runpy.run_module('%main_module%', run_name='__main__', alter_sys=True)

python/private/py_executable.bzl

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ accepting arbitrary Python versions.
194194
allow_single_file = True,
195195
default = "@bazel_tools//tools/python:python_bootstrap_template.txt",
196196
),
197+
"_main_module_entrypoint_template": lambda: attrb.Label(
198+
allow_single_file = True,
199+
default = "//python/private:main_module_entrypoint_template.py",
200+
),
197201
"_launcher": lambda: attrb.Label(
198202
cfg = "target",
199203
# NOTE: This is an executable, but is only used for Windows. It
@@ -360,9 +364,8 @@ def _create_executable(
360364
)
361365
else:
362366
stage2_bootstrap = None
363-
extra_runfiles = ctx.runfiles()
364367
zip_main = ctx.actions.declare_file(base_executable_name + ".temp", sibling = executable)
365-
_create_stage1_bootstrap(
368+
extra_runfiles = _create_stage1_bootstrap(
366369
ctx,
367370
output = zip_main,
368371
main_py = main_py,
@@ -426,16 +429,17 @@ def _create_executable(
426429
if bootstrap_output != None:
427430
fail("Should not occur: bootstrap_output should not be used " +
428431
"when creating an executable zip")
429-
_create_executable_zip_file(
432+
more_runfiles = _create_executable_zip_file(
430433
ctx,
431434
output = executable,
432435
zip_file = zip_file,
433436
stage2_bootstrap = stage2_bootstrap,
434437
runtime_details = runtime_details,
435438
venv = venv,
436439
)
440+
extra_runfiles = extra_runfiles.merge(more_runfiles)
437441
elif bootstrap_output:
438-
_create_stage1_bootstrap(
442+
more_runfiles = _create_stage1_bootstrap(
439443
ctx,
440444
output = bootstrap_output,
441445
stage2_bootstrap = stage2_bootstrap,
@@ -445,6 +449,7 @@ def _create_executable(
445449
main_py = main_py,
446450
venv = venv,
447451
)
452+
extra_runfiles = extra_runfiles.merge(more_runfiles)
448453
else:
449454
# Otherwise, this should be the Windows case of launcher + zip.
450455
# Double check this just to make sure.
@@ -796,6 +801,7 @@ def _create_stage1_bootstrap(
796801
is_for_zip,
797802
runtime_details,
798803
venv = None):
804+
extra_runfiles = ctx.runfiles()
799805
runtime = runtime_details.effective_runtime
800806

801807
if venv:
@@ -833,9 +839,10 @@ def _create_stage1_bootstrap(
833839
)
834840
template = runtime.bootstrap_template
835841
subs["%shebang%"] = runtime.stub_shebang
836-
elif not ctx.files.srcs:
837-
fail("mandatory 'srcs' files have not been provided")
838842
else:
843+
if not ctx.files.srcs and not ctx.attr.main_module:
844+
fail("mandatory 'srcs' files have not been provided")
845+
839846
if (ctx.configuration.coverage_enabled and
840847
runtime and
841848
runtime.coverage_tool):
@@ -855,6 +862,20 @@ def _create_stage1_bootstrap(
855862
subs["%coverage_tool%"] = coverage_tool_runfiles_path
856863
subs["%import_all%"] = ("True" if ctx.fragments.bazel_py.python_import_all_repositories else "False")
857864
subs["%imports%"] = ":".join(imports.to_list())
865+
866+
if ctx.attr.main_module:
867+
main_module_entrypoint = ctx.actions.declare_file("main_module_entrypoint.py")
868+
ctx.actions.expand_template(
869+
template = ctx.file._main_module_entrypoint_template,
870+
output = main_module_entrypoint,
871+
substitutions = {"%main_module%": ctx.attr.main_module}
872+
)
873+
main_py = main_module_entrypoint
874+
extra_runfiles = extra_runfiles.merge(ctx.runfiles([main_module_entrypoint]))
875+
else:
876+
# shouldn't happen
877+
fail("Neither main nor main_module was provided")
878+
858879
subs["%main%"] = "{}/{}".format(ctx.workspace_name, main_py.short_path)
859880

860881
ctx.actions.expand_template(
@@ -863,6 +884,8 @@ def _create_stage1_bootstrap(
863884
substitutions = subs,
864885
)
865886

887+
return extra_runfiles
888+
866889
def _create_windows_exe_launcher(
867890
ctx,
868891
*,
@@ -985,7 +1008,7 @@ def _create_executable_zip_file(
9851008
sibling = output,
9861009
)
9871010
if stage2_bootstrap:
988-
_create_stage1_bootstrap(
1011+
extra_runfiles = _create_stage1_bootstrap(
9891012
ctx,
9901013
output = prelude,
9911014
stage2_bootstrap = stage2_bootstrap,
@@ -994,6 +1017,7 @@ def _create_executable_zip_file(
9941017
venv = venv,
9951018
)
9961019
else:
1020+
extra_runfiles = ctx.runfiles()
9971021
ctx.actions.write(prelude, "#!/usr/bin/env python3\n")
9981022

9991023
ctx.actions.run_shell(
@@ -1009,6 +1033,8 @@ def _create_executable_zip_file(
10091033
progress_message = "Build Python zip executable: %{label}",
10101034
)
10111035

1036+
return extra_runfiles
1037+
10121038
def _get_cc_details_for_binary(ctx, extra_deps):
10131039
cc_info = collect_cc_info(ctx, extra_deps = extra_deps)
10141040
return create_cc_details_struct(

0 commit comments

Comments
 (0)
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