Skip to content

Commit 9629d7a

Browse files
committed
fix: make bootstrap=script zipapp work
1 parent 466da1d commit 9629d7a

File tree

4 files changed

+109
-12
lines changed

4 files changed

+109
-12
lines changed

python/private/zip_main_template.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,10 @@ def main():
286286
# The bin/ directory may not exist if it is empty.
287287
os.makedirs(os.path.dirname(python_program), exist_ok=True)
288288
try:
289-
os.symlink(_PYTHON_BINARY_ACTUAL, python_program)
289+
os.symlink(symlink_to, python_program)
290290
except OSError as e:
291291
raise Exception(
292-
f"Unable to create venv python interpreter symlink: {python_program} -> {PYTHON_BINARY_ACTUAL}"
292+
f"Unable to create venv python interpreter symlink: {python_program} -> {symlink_to}"
293293
) from e
294294

295295
# Some older Python versions on macOS (namely Python 3.7) may unintentionally

tests/bootstrap_impls/BUILD.bazel

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
load("@rules_shell//shell:sh_test.bzl", "sh_test")
2+
13
# Copyright 2023 The Bazel Authors. All rights reserved.
24
#
35
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -11,10 +13,40 @@
1113
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1214
# See the License for the specific language governing permissions and
1315
# limitations under the License.
14-
load("//tests/support:sh_py_run_test.bzl", "py_reconfig_test", "sh_py_run_test")
16+
load("//tests/support:sh_py_run_test.bzl", "py_reconfig_binary", "py_reconfig_test", "sh_py_run_test")
1517
load("//tests/support:support.bzl", "SUPPORTS_BOOTSTRAP_SCRIPT")
1618
load(":venv_relative_path_tests.bzl", "relative_path_test_suite")
1719

20+
py_reconfig_binary(
21+
name = "bootstrap_script_zipapp_bin",
22+
srcs = ["bin.py"],
23+
bootstrap_impl = "script",
24+
# Force it to not be self-executable
25+
build_python_zip = "no",
26+
main = "bin.py",
27+
target_compatible_with = SUPPORTS_BOOTSTRAP_SCRIPT,
28+
)
29+
30+
filegroup(
31+
name = "bootstrap_script_zipapp_zip",
32+
testonly = 1,
33+
srcs = [":bootstrap_script_zipapp_bin"],
34+
output_group = "python_zip_file",
35+
)
36+
37+
sh_test(
38+
name = "bootstrap_script_zipapp_test",
39+
srcs = ["bootstrap_script_zipapp_test.sh"],
40+
data = [":bootstrap_script_zipapp_zip"],
41+
env = {
42+
"ZIP_RLOCATION": "$(rlocationpaths :bootstrap_script_zipapp_zip)".format(),
43+
},
44+
target_compatible_with = SUPPORTS_BOOTSTRAP_SCRIPT,
45+
deps = [
46+
"@bazel_tools//tools/bash/runfiles",
47+
],
48+
)
49+
1850
sh_py_run_test(
1951
name = "run_binary_zip_no_test",
2052
build_python_zip = "no",
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Copyright 2024 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# --- begin runfiles.bash initialization v3 ---
16+
# Copy-pasted from the Bazel Bash runfiles library v3.
17+
set -uo pipefail; set +e; f=bazel_tools/tools/bash/runfiles/runfiles.bash
18+
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
19+
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
20+
source "$0.runfiles/$f" 2>/dev/null || \
21+
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
22+
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
23+
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
24+
# --- end runfiles.bash initialization v3 ---
25+
set +e
26+
27+
bin=$(rlocation $ZIP_RLOCATION)
28+
if [[ -z "$bin" ]]; then
29+
echo "Unable to locate test binary: $ZIP_RLOCATION"
30+
exit 1
31+
fi
32+
set -x
33+
actual=$(python3 $bin)
34+
35+
# How we detect if a zip file was executed from depends on which bootstrap
36+
# is used.
37+
# bootstrap_impl=script outputs RULES_PYTHON_ZIP_DIR=<somepath>
38+
# bootstrap_impl=system_python outputs file:.*Bazel.runfiles
39+
expected_pattern="Hello"
40+
if ! (echo "$actual" | grep "$expected_pattern" ) >/dev/null; then
41+
echo "Test case failed: $1"
42+
echo "expected output to match: $expected_pattern"
43+
echo "but got:\n$actual"
44+
exit 1
45+
fi
46+
47+
exit 0

tests/support/sh_py_run_test.bzl

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def _py_reconfig_impl(ctx):
8686
default_info.default_runfiles,
8787
),
8888
),
89+
ctx.attr.target[OutputGroupInfo],
8990
# Inherit the expanded environment from the inner target.
9091
ctx.attr.target[RunEnvironmentInfo],
9192
]
@@ -120,31 +121,48 @@ _py_reconfig_binary = _make_reconfig_rule(executable = True)
120121

121122
_py_reconfig_test = _make_reconfig_rule(test = True)
122123

123-
def py_reconfig_test(*, name, **kwargs):
124-
"""Create a py_test with customized build settings for testing.
125-
126-
Args:
127-
name: str, name of teset target.
128-
**kwargs: kwargs to pass along to _py_reconfig_test and py_test.
129-
"""
124+
def _py_reconfig_executable(*, name, py_reconfig_rule, py_inner_rule, **kwargs):
130125
reconfig_kwargs = {}
131126
reconfig_kwargs["bootstrap_impl"] = kwargs.pop("bootstrap_impl", None)
132127
reconfig_kwargs["extra_toolchains"] = kwargs.pop("extra_toolchains", None)
133128
reconfig_kwargs["python_version"] = kwargs.pop("python_version", None)
134129
reconfig_kwargs["target_compatible_with"] = kwargs.get("target_compatible_with")
130+
reconfig_kwargs["build_python_zip"] = kwargs.pop("build_python_zip", None)
135131

136132
inner_name = "_{}_inner".format(name)
137-
_py_reconfig_test(
133+
py_reconfig_rule(
138134
name = name,
139135
target = inner_name,
140136
**reconfig_kwargs
141137
)
142-
py_test(
138+
py_inner_rule(
143139
name = inner_name,
144140
tags = ["manual"],
145141
**kwargs
146142
)
147143

144+
def py_reconfig_test(*, name, **kwargs):
145+
"""Create a py_test with customized build settings for testing.
146+
147+
Args:
148+
name: str, name of teset target.
149+
**kwargs: kwargs to pass along to _py_reconfig_test and py_test.
150+
"""
151+
_py_reconfig_executable(
152+
name = name,
153+
py_reconfig_rule = _py_reconfig_test,
154+
py_inner_rule = py_test,
155+
**kwargs
156+
)
157+
158+
def py_reconfig_binary(*, name, **kwargs):
159+
_py_reconfig_executable(
160+
name = name,
161+
py_reconfig_rule = _py_reconfig_binary,
162+
py_inner_rule = py_binary,
163+
**kwargs
164+
)
165+
148166
def sh_py_run_test(*, name, sh_src, py_src, **kwargs):
149167
"""Run a py_binary within a sh_test.
150168

0 commit comments

Comments
 (0)