forked from bazel-contrib/rules_python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinterpreter.bzl
82 lines (76 loc) · 3.21 KB
/
interpreter.bzl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# Copyright 2025 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Implementation of the rules to access the underlying Python interpreter."""
load("@bazel_skylib//lib:paths.bzl", "paths")
load("//python:py_runtime_info.bzl", "PyRuntimeInfo")
load(":common.bzl", "runfiles_root_path")
load(":sentinel.bzl", "SentinelInfo")
load(":toolchain_types.bzl", "TARGET_TOOLCHAIN_TYPE")
def _interpreter_binary_impl(ctx):
if SentinelInfo in ctx.attr.binary:
toolchain = ctx.toolchains[TARGET_TOOLCHAIN_TYPE]
runtime = toolchain.py3_runtime
else:
runtime = ctx.attr.binary[PyRuntimeInfo]
# NOTE: We name the output filename after the underlying file name
# because of things like pyenv: they use $0 to determine what to
# re-exec. If it's not a recognized name, then they fail.
if runtime.interpreter:
# In order for this to work both locally and remotely, we create a
# shell script here that re-exec's into the real interpreter. Ideally,
# we'd just use a symlink, but that breaks under certain conditions. If
# we use a ctx.actions.symlink(target=...) then it fails under remote
# execution. If we use ctx.actions.symlink(target_path=...) then it
# behaves differently inside the runfiles tree and outside the runfiles
# tree.
#
# This currently does not work on Windows. Need to find a way to enable
# that.
executable = ctx.actions.declare_file(runtime.interpreter.basename)
ctx.actions.expand_template(
template = ctx.file._template,
output = executable,
substitutions = {
"%target_file%": runfiles_root_path(ctx, runtime.interpreter.short_path),
},
is_executable = True,
)
else:
executable = ctx.actions.declare_symlink(paths.basename(runtime.interpreter_path))
ctx.actions.symlink(output = executable, target_path = runtime.interpreter_path)
return [
DefaultInfo(
executable = executable,
runfiles = ctx.runfiles([executable], transitive_files = runtime.files).merge_all([
ctx.attr._bash_runfiles[DefaultInfo].default_runfiles,
]),
),
]
interpreter_binary = rule(
implementation = _interpreter_binary_impl,
toolchains = [TARGET_TOOLCHAIN_TYPE],
executable = True,
attrs = {
"binary": attr.label(
mandatory = True,
),
"_bash_runfiles": attr.label(
default = "@bazel_tools//tools/bash/runfiles",
),
"_template": attr.label(
default = "//python/private:interpreter_tmpl.sh",
allow_single_file = True,
),
},
)