Skip to content

Commit 0fb4ce1

Browse files
authored
fix: normalize argv0 so runfiles root can be found on windows with bazel 9 (#2481)
When the shell test invokes the python binary, it uses a combination of forward slashes and backslashes. Under Bazel 9, that mixture of slashes is preserved. This later breaks a regex that looks for the OS-specific path separator. To fix, normalize forward slashes to the OS path separator. Oddly, it's not Bazel that is passing the mixture of slashes (it's the shell), but behavior seems to vary based on which version of Bazel is used. Along the way, copy the nicer `print_verbose` function from the stage2 bootstrap into the old bootstrap. It prints debug information in a nicer format. Work towards #2469
1 parent a7119c9 commit 0fb4ce1

File tree

1 file changed

+34
-5
lines changed

1 file changed

+34
-5
lines changed

python/private/python_bootstrap_template.txt

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,28 @@ def FindPythonBinary(module_space):
8989
"""Finds the real Python binary if it's not a normal absolute path."""
9090
return FindBinary(module_space, PYTHON_BINARY)
9191

92-
def PrintVerbose(*args):
93-
if os.environ.get("RULES_PYTHON_BOOTSTRAP_VERBOSE"):
94-
print("bootstrap:", *args, file=sys.stderr, flush=True)
92+
def print_verbose(*args, mapping=None, values=None):
93+
if os.environ.get("RULES_PYTHON_BOOTSTRAP_VERBOSE"):
94+
if mapping is not None:
95+
for key, value in sorted((mapping or {}).items()):
96+
print(
97+
"bootstrap:",
98+
*args,
99+
f"{key}={value!r}",
100+
file=sys.stderr,
101+
flush=True,
102+
)
103+
elif values is not None:
104+
for i, v in enumerate(values):
105+
print(
106+
"bootstrap:",
107+
*args,
108+
f"[{i}] {v!r}",
109+
file=sys.stderr,
110+
flush=True,
111+
)
112+
else:
113+
print("bootstrap:", *args, file=sys.stderr, flush=True)
95114

96115
def PrintVerboseCoverage(*args):
97116
"""Print output if VERBOSE_COVERAGE is non-empty in the environment."""
@@ -157,6 +176,12 @@ def FindModuleSpace(main_rel_path):
157176
return runfiles_dir
158177

159178
stub_filename = sys.argv[0]
179+
# On Windows, the path may contain both forward and backslashes.
180+
# Normalize to the OS separator because the regex used later assumes
181+
# the OS-specific separator.
182+
if IsWindows:
183+
stub_filename = stub_filename.replace("/", os.sep)
184+
160185
if not os.path.isabs(stub_filename):
161186
stub_filename = os.path.join(os.getcwd(), stub_filename)
162187

@@ -380,9 +405,9 @@ def _RunExecv(python_program, main_filename, args, env):
380405
# type: (str, str, list[str], dict[str, str]) -> ...
381406
"""Executes the given Python file using the various environment settings."""
382407
os.environ.update(env)
383-
PrintVerbose("RunExecv: environ:", os.environ)
408+
print_verbose("RunExecv: environ:", mapping=os.environ)
384409
argv = [python_program, main_filename] + args
385-
PrintVerbose("RunExecv: argv:", python_program, argv)
410+
print_verbose("RunExecv: argv:", python_program, argv)
386411
os.execv(python_program, argv)
387412

388413
def _RunForCoverage(python_program, main_filename, args, env,
@@ -453,6 +478,10 @@ relative_files = True
453478
return ret_code
454479

455480
def Main():
481+
print_verbose("initial argv:", values=sys.argv)
482+
print_verbose("initial cwd:", os.getcwd())
483+
print_verbose("initial environ:", mapping=os.environ)
484+
print_verbose("initial sys.path:", values=sys.path)
456485
args = sys.argv[1:]
457486

458487
new_env = {}

0 commit comments

Comments
 (0)