Skip to content

Commit ccf7715

Browse files
committed
use full runfiles path; add basic docs
1 parent ebe1842 commit ccf7715

File tree

5 files changed

+72
-30
lines changed

5 files changed

+72
-30
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
:::{default-domain} bzl
2+
:::
3+
:::{bzl:currentfile} //python/bin:BUILD.bazel
4+
:::
5+
6+
# //python/bin
7+
8+
:::{bzl:target} python
9+
10+
A target to directly run a Python interpreter.
11+
12+
By default, it uses the Python version that toolchain resolution matches
13+
(typically the one marked `is_default=True` in `MODULE.bazel`).
14+
15+
This runs a Python interpreter in a similar manner as when running `python3`
16+
on the command line. It can be invoked using `bazel run`. Remember that in
17+
order to pass flags onto the program `--` must be specified to separate
18+
Bazel flags from the program flags.
19+
20+
An example that will run Python 3.12 and have it print the version
21+
22+
```
23+
bazel run @rules_python//python/bin:python \
24+
`--@rule_python//python/config_settings:python_verion=3.12 \
25+
-- \
26+
--version
27+
```
28+
29+
::::{seealso}
30+
The {flag}`--python_src` flag for using the intepreter a binary/test uses.
31+
::::
32+
33+
::::{versionadded} VERSION_NEXT_FEATURE
34+
::::
35+
:::
36+
37+
:::{bzl:flag} python_src
38+
39+
The target (one providing `PyRuntimeInfo`) whose python interpreter to use for
40+
{obj}`:python`.
41+
:::

python/private/common.bzl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,3 +543,20 @@ def target_platform_has_any_constraint(ctx, constraints):
543543
if ctx.target_platform_has_constraint(constraint_value):
544544
return True
545545
return False
546+
547+
def runfiles_root_path(ctx, short_path):
548+
"""Compute a runfiles-root relative path from `File.short_path`
549+
550+
Args:
551+
ctx: current target ctx
552+
short_path: str, a main-repo relative path from `File.short_path`
553+
554+
Returns:
555+
{type}`str`, a runflies-root relative path
556+
"""
557+
558+
# The ../ comes from short_path is for files in other repos.
559+
if short_path.startswith("../"):
560+
return short_path[3:]
561+
else:
562+
return "{}/{}".format(ctx.workspace_name, short_path)

python/private/interpreter.bzl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
load("@bazel_skylib//lib:paths.bzl", "paths")
1818
load("//python:py_runtime_info.bzl", "PyRuntimeInfo")
19+
load(":common.bzl", "runfiles_root_path")
1920
load(":sentinel.bzl", "SentinelInfo")
2021
load(":toolchain_types.bzl", "TARGET_TOOLCHAIN_TYPE")
2122

@@ -45,10 +46,7 @@ def _interpreter_binary_impl(ctx):
4546
template = ctx.file._template,
4647
output = executable,
4748
substitutions = {
48-
# Since we never invoke this rule from within the interpreter's
49-
# own repository, the short_path here should give us a
50-
# predictable path of "../<repo>/<path within repo>".
51-
"%target_file%": runtime.interpreter.short_path,
49+
"%target_file%": runfiles_root_path(ctx, runtime.interpreter.short_path),
5250
},
5351
is_executable = True,
5452
)

python/private/interpreter_tmpl.sh

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
1212
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
1313
# --- end runfiles.bash initialization v3 ---
1414

15+
set +e # allow us to check for errors more easily
1516
readonly TARGET_FILE="%target_file%"
17+
MAIN_BIN=$(rlocation "$TARGET_FILE")
1618

17-
# Strip the leading "../" from "../<repo>/<path within repo>" so that we can do
18-
# a runfiles lookup.
19-
MAIN_BIN="$(rlocation "${TARGET_FILE#*/}")"
20-
19+
if [[ -z "$MAIN_BIN" || ! -e "$MAIN_BIN" ]]; then
20+
echo "ERROR: interpreter executable not found: $MAIN_BIN (from $TARGET_FILE)"
21+
exit 1
22+
fi
2123
exec "${MAIN_BIN}" "$@"

python/private/py_executable.bzl

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ load(
4848
"filter_to_py_srcs",
4949
"get_imports",
5050
"is_bool",
51+
"runfiles_root_path",
5152
"target_platform_has_any_constraint",
5253
"union_attrs",
5354
)
@@ -447,7 +448,7 @@ def _create_executable(
447448
)
448449

449450
def _create_zip_main(ctx, *, stage2_bootstrap, runtime_details, venv):
450-
python_binary = _runfiles_root_path(ctx, venv.interpreter.short_path)
451+
python_binary = runfiles_root_path(ctx, venv.interpreter.short_path)
451452
python_binary_actual = venv.interpreter_actual_path
452453

453454
# The location of this file doesn't really matter. It's added to
@@ -522,7 +523,7 @@ def _create_venv(ctx, output_prefix, imports, runtime_details):
522523

523524
if not venvs_use_declare_symlink_enabled:
524525
if runtime.interpreter:
525-
interpreter_actual_path = _runfiles_root_path(ctx, runtime.interpreter.short_path)
526+
interpreter_actual_path = runfiles_root_path(ctx, runtime.interpreter.short_path)
526527
else:
527528
interpreter_actual_path = runtime.interpreter_path
528529

@@ -543,11 +544,11 @@ def _create_venv(ctx, output_prefix, imports, runtime_details):
543544
# may choose to write what symlink() points to instead.
544545
interpreter = ctx.actions.declare_symlink("{}/bin/{}".format(venv, py_exe_basename))
545546

546-
interpreter_actual_path = _runfiles_root_path(ctx, runtime.interpreter.short_path)
547+
interpreter_actual_path = runfiles_root_path(ctx, runtime.interpreter.short_path)
547548
rel_path = relative_path(
548549
# dirname is necessary because a relative symlink is relative to
549550
# the directory the symlink resides within.
550-
from_ = paths.dirname(_runfiles_root_path(ctx, interpreter.short_path)),
551+
from_ = paths.dirname(runfiles_root_path(ctx, interpreter.short_path)),
551552
to = interpreter_actual_path,
552553
)
553554

@@ -646,23 +647,6 @@ def _create_stage2_bootstrap(
646647
)
647648
return output
648649

649-
def _runfiles_root_path(ctx, short_path):
650-
"""Compute a runfiles-root relative path from `File.short_path`
651-
652-
Args:
653-
ctx: current target ctx
654-
short_path: str, a main-repo relative path from `File.short_path`
655-
656-
Returns:
657-
{type}`str`, a runflies-root relative path
658-
"""
659-
660-
# The ../ comes from short_path is for files in other repos.
661-
if short_path.startswith("../"):
662-
return short_path[3:]
663-
else:
664-
return "{}/{}".format(ctx.workspace_name, short_path)
665-
666650
def _create_stage1_bootstrap(
667651
ctx,
668652
*,
@@ -676,7 +660,7 @@ def _create_stage1_bootstrap(
676660
runtime = runtime_details.effective_runtime
677661

678662
if venv:
679-
python_binary_path = _runfiles_root_path(ctx, venv.interpreter.short_path)
663+
python_binary_path = runfiles_root_path(ctx, venv.interpreter.short_path)
680664
else:
681665
python_binary_path = runtime_details.executable_interpreter_path
682666

0 commit comments

Comments
 (0)