Skip to content

Commit 0230206

Browse files
committed
feat(zipapp): support RULES_PYTHON_EXTRACT_ROOT env var
1 parent df7a168 commit 0230206

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

python/private/zipapp/py_zipapp_rule.bzl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ def _create_zipapp_main_py(ctx, py_runtime, py_executable, stage2_bootstrap):
3939
"%python_binary_actual%": python_binary_actual_path,
4040
"%stage2_bootstrap%": runfiles_root_path(ctx, stage2_bootstrap.short_path),
4141
"%workspace_name%": ctx.workspace_name,
42+
"%EXTRACT_DIR%": paths.join(
43+
(ctx.label.repo_name or "_main"),
44+
ctx.label.package,
45+
ctx.label.name,
46+
),
4247
},
4348
)
4449
return zip_main_py

python/private/zipapp/zip_main_template.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
del sys.path[0]
2323

2424
import os
25+
from os.path import join
2526
import shutil
2627
import subprocess
2728
import tempfile
@@ -35,6 +36,10 @@
3536
# executable to use.
3637
_PYTHON_BINARY_ACTUAL = "%python_binary_actual%"
3738
_WORKSPACE_NAME = "%workspace_name%"
39+
# relative path under EXTRACT_ROOT to extract to.
40+
EXTRACT_DIR = "%EXTRACT_DIR%"
41+
42+
EXTRACT_ROOT = os.environ.get("RULES_PYTHON_EXTRACT_ROOT")
3843

3944

4045
def print_verbose(*args, mapping=None, values=None):
@@ -182,11 +187,14 @@ def extract_zip(zip_path, dest_dir):
182187

183188
# Create the runfiles tree by extracting the zip file
184189
def create_runfiles_root():
185-
temp_dir = tempfile.mkdtemp("", "Bazel.runfiles_")
186-
extract_zip(os.path.dirname(__file__), temp_dir)
190+
if EXTRACT_ROOT:
191+
extract_root = join(EXTRACT_ROOT, EXTRACT_DIR)
192+
else:
193+
extract_root = tempfile.mkdtemp("", "Bazel.runfiles_")
194+
extract_zip(os.path.dirname(__file__), extract_root)
187195
# IMPORTANT: Later code does `rm -fr` on dirname(runfiles_root) -- it's
188196
# important that deletion code be in sync with this directory structure
189-
return os.path.join(temp_dir, "runfiles")
197+
return os.path.join(extract_root, "runfiles")
190198

191199

192200
def execute_file(
@@ -223,18 +231,24 @@ def execute_file(
223231
# - When running in a zip file, we need to clean up the
224232
# workspace after the process finishes so control must return here.
225233
try:
226-
subprocess_argv = [python_program, main_filename] + args
234+
subprocess_argv = [python_program]
235+
if not EXTRACT_ROOT:
236+
subprocess_argv.append(f"-XRULES_PYTHON_ZIP_DIR={os.path.dirname(runfiles_root)}")
237+
subprocess_argv.append(main_filename)
238+
subprocess_argv += args
227239
print_verbose("subprocess argv:", values=subprocess_argv)
228240
print_verbose("subprocess env:", mapping=env)
229241
print_verbose("subprocess cwd:", workspace)
230242
ret_code = subprocess.call(subprocess_argv, env=env, cwd=workspace)
231243
sys.exit(ret_code)
232244
finally:
233-
# NOTE: dirname() is called because create_runfiles_root() creates a
234-
# sub-directory within a temporary directory, and we want to remove the
235-
# whole temporary directory.
236-
##shutil.rmtree(os.path.dirname(runfiles_root), True)
237-
pass
245+
if not EXTRACT_ROOT:
246+
# NOTE: dirname() is called because create_runfiles_root() creates a
247+
# sub-directory within a temporary directory, and we want to remove the
248+
# whole temporary directory.
249+
extract_root = os.path.dirname(runfiles_root)
250+
print_verbose("cleanup: rmtree: ", extract_root)
251+
shutil.rmtree(extract_root, True)
238252

239253

240254
def main():

0 commit comments

Comments
 (0)