Skip to content

Commit 4c2cf3a

Browse files
smoofralawrence-danna-apple
authored andcommitted
[lldb] fix -print-script-interpreter-info on windows
Apparently "{sys.prefix}/bin/python3" isn't where you find the python interpreter on windows, so the test I wrote for -print-script-interpreter-info is failing. We can't rely on sys.executable at runtime, because that will point to lldb.exe not python.exe. We can't just record sys.executable from build time, because python could have been moved to a different location. But it should be OK to apply relative path from sys.prefix to sys.executable from build-time to the sys.prefix at runtime. Reviewed By: JDevlieghere Differential Revision: https://reviews.llvm.org/D113650
1 parent 913d78c commit 4c2cf3a

File tree

5 files changed

+95
-39
lines changed

5 files changed

+95
-39
lines changed

lldb/CMakeLists.txt

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,28 @@ if (WIN32)
3131
endif()
3232

3333
if (LLDB_ENABLE_PYTHON)
34-
if (NOT CMAKE_CROSSCOMPILING)
35-
execute_process(
36-
COMMAND ${Python3_EXECUTABLE}
37-
-c "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(True, False, ''))"
38-
OUTPUT_VARIABLE LLDB_PYTHON_DEFAULT_RELATIVE_PATH
39-
OUTPUT_STRIP_TRAILING_WHITESPACE)
40-
41-
file(TO_CMAKE_PATH ${LLDB_PYTHON_DEFAULT_RELATIVE_PATH} LLDB_PYTHON_DEFAULT_RELATIVE_PATH)
42-
else ()
43-
if ("${LLDB_PYTHON_RELATIVE_PATH}" STREQUAL "")
44-
message(FATAL_ERROR
45-
"Crosscompiling LLDB with Python requires manually setting
46-
LLDB_PYTHON_RELATIVE_PATH.")
47-
endif ()
48-
endif ()
49-
50-
set(LLDB_PYTHON_RELATIVE_PATH ${LLDB_PYTHON_DEFAULT_RELATIVE_PATH}
51-
CACHE STRING "Path where Python modules are installed, relative to install prefix")
34+
set(cachestring_LLDB_PYTHON_RELATIVE_PATH
35+
"Path where Python modules are installed, relative to install prefix")
36+
set(cachestring_LLDB_PYTHON_EXE_RELATIVE_PATH
37+
"Path to python interpreter exectuable, relative to install prefix")
38+
39+
foreach(var LLDB_PYTHON_RELATIVE_PATH LLDB_PYTHON_EXE_RELATIVE_PATH)
40+
if(NOT DEFINED ${var} AND NOT CMAKE_CROSSCOMPILING)
41+
execute_process(
42+
COMMAND ${Python3_EXECUTABLE}
43+
${CMAKE_CURRENT_SOURCE_DIR}/bindings/python/get-python-config.py
44+
${var}
45+
OUTPUT_VARIABLE value
46+
OUTPUT_STRIP_TRAILING_WHITESPACE)
47+
file(TO_CMAKE_PATH "${value}" value)
48+
set(${var} ${value} CACHE STRING ${cachestring_${var}})
49+
else()
50+
if ("${${var}}" STREQUAL "")
51+
message(FATAL_ERROR
52+
"Crosscompiling LLDB with Python requires manually setting ${var}.")
53+
endif()
54+
endif()
55+
endforeach()
5256
endif ()
5357

5458
if (LLDB_ENABLE_LUA)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
import sys
5+
import argparse
6+
import sysconfig
7+
import distutils.sysconfig
8+
9+
10+
def relpath_nodots(path, base):
11+
rel = os.path.normpath(os.path.relpath(path, base))
12+
assert not os.path.isabs(rel)
13+
parts = rel.split(os.path.sep)
14+
if parts and parts[0] == '..':
15+
raise ValueError(f"{path} is not under {base}")
16+
return rel
17+
18+
def main():
19+
parser = argparse.ArgumentParser(description="extract cmake variables from python")
20+
parser.add_argument("variable_name")
21+
args = parser.parse_args()
22+
if args.variable_name == "LLDB_PYTHON_RELATIVE_PATH":
23+
print(distutils.sysconfig.get_python_lib(True, False, ''))
24+
elif args.variable_name == "LLDB_PYTHON_EXE_RELATIVE_PATH":
25+
tried = list()
26+
exe = sys.executable
27+
while True:
28+
try:
29+
print(relpath_nodots(exe, sys.prefix))
30+
break
31+
except ValueError:
32+
tried.append(exe)
33+
if os.path.islink(exe):
34+
exe = os.path.join(os.path.dirname(exe), os.readlink(exe))
35+
continue
36+
else:
37+
print("Could not find a relative path to sys.executable under sys.prefix", file=sys.stderr)
38+
for e in tried:
39+
print("tried:", e, file=sys.stderr)
40+
print("sys.prefix:", sys.prefix, file=sys.stderr)
41+
sys.exit(1)
42+
43+
else:
44+
parser.error(f"unknown variable {args.variable_name}")
45+
46+
if __name__ == '__main__':
47+
main()

lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ if(NOT LLDB_PYTHON_RELATIVE_PATH)
33
endif()
44
add_definitions(-DLLDB_PYTHON_RELATIVE_LIBDIR="${LLDB_PYTHON_RELATIVE_PATH}")
55

6+
if(NOT LLDB_PYTHON_EXE_RELATIVE_PATH)
7+
message(FATAL_ERROR "LLDB_PYTHON_EXE_RELATIVE_PATH is not set.")
8+
endif()
9+
add_definitions(-DLLDB_PYTHON_EXE_RELATIVE_PATH="${LLDB_PYTHON_EXE_RELATIVE_PATH}")
10+
11+
612
if (LLDB_ENABLE_LIBEDIT)
713
list(APPEND LLDB_LIBEDIT_LIBS ${LibEdit_LIBRARIES})
814
endif()

lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -410,30 +410,31 @@ FileSpec ScriptInterpreterPython::GetPythonDir() {
410410
return g_spec;
411411
}
412412

413+
static const char GetInterpreterInfoScript[] = R"(
414+
import os
415+
import sys
416+
417+
def main(lldb_python_dir, python_exe_relative_path):
418+
info = {
419+
"lldb-pythonpath": lldb_python_dir,
420+
"language": "python",
421+
"prefix": sys.prefix,
422+
"executable": os.path.join(sys.prefix, python_exe_relative_path)
423+
}
424+
return info
425+
)";
426+
427+
static const char python_exe_relative_path[] = LLDB_PYTHON_EXE_RELATIVE_PATH;
428+
413429
StructuredData::DictionarySP ScriptInterpreterPython::GetInterpreterInfo() {
414430
GIL gil;
415431
FileSpec python_dir_spec = GetPythonDir();
416432
if (!python_dir_spec)
417433
return nullptr;
418-
PythonString python_dir(python_dir_spec.GetPath());
419-
PythonDictionary info(PyInitialValue::Empty);
420-
llvm::Error error = info.SetItem("lldb-pythonpath", python_dir);
421-
if (error)
422-
return nullptr;
423-
static const char script[] = R"(
424-
def main(info):
425-
import sys
426-
import os
427-
name = 'python' + str(sys.version_info.major)
428-
info.update({
429-
"language": "python",
430-
"prefix": sys.prefix,
431-
"executable": os.path.join(sys.prefix, "bin", name),
432-
})
433-
return info
434-
)";
435-
PythonScript get_info(script);
436-
auto info_json = unwrapIgnoringErrors(As<PythonDictionary>(get_info(info)));
434+
PythonScript get_info(GetInterpreterInfoScript);
435+
auto info_json = unwrapIgnoringErrors(
436+
As<PythonDictionary>(get_info(PythonString(python_dir_spec.GetPath()),
437+
PythonString(python_exe_relative_path))));
437438
if (!info_json)
438439
return nullptr;
439440
return info_json.CreateStructuredDictionary();

lldb/test/API/functionalities/paths/TestPaths.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ def test_interpreter_info(self):
5151
stream = lldb.SBStream()
5252
self.assertTrue(info_sd.GetAsJSON(stream).Success())
5353
info = json.loads(stream.GetData())
54-
if os.name == 'nt': #FIXME
55-
return
5654
prefix = info['prefix']
5755
self.assertEqual(os.path.realpath(sys.prefix), os.path.realpath(prefix))
5856
self.assertEqual(

0 commit comments

Comments
 (0)