Skip to content

Commit e662c02

Browse files
Merge pull request #11897 from charles-zablit/charles-zablit/lldb/windows/test-if-python.dll-is-in-path-to-swift-release-6.2.2
🍒 [lldb][windows] print an error if python.dll is not in the DLL search path
2 parents e28b865 + c9bc949 commit e662c02

File tree

3 files changed

+64
-12
lines changed

3 files changed

+64
-12
lines changed

lldb/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ if (LLDB_ENABLE_PYTHON)
110110
set(LLDB_PYTHON_EXT_SUFFIX "_d${LLDB_PYTHON_EXT_SUFFIX}")
111111
endif()
112112
endif()
113+
if(TARGET Python3::Python)
114+
get_target_property(_Python3_LIB_PATH Python3::Python IMPORTED_LIBRARY_LOCATION)
115+
if(_Python3_LIB_PATH)
116+
get_filename_component(LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME "${_Python3_LIB_PATH}" NAME)
117+
endif()
118+
endif()
113119
endif ()
114120

115121
if (LLDB_ENABLE_LUA)

lldb/tools/driver/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ add_dependencies(lldb
3131
if(DEFINED LLDB_PYTHON_DLL_RELATIVE_PATH)
3232
target_compile_definitions(lldb PRIVATE LLDB_PYTHON_DLL_RELATIVE_PATH="${LLDB_PYTHON_DLL_RELATIVE_PATH}")
3333
endif()
34+
if(DEFINED LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME)
35+
target_compile_definitions(lldb PRIVATE LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME="${LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME}")
36+
endif()
3437

3538
if(LLDB_BUILD_FRAMEWORK)
3639
# In the build-tree, we know the exact path to the framework directory.

lldb/tools/driver/Driver.cpp

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) {
430430
return error;
431431
}
432432

433-
#if defined(_WIN32) && defined(LLDB_PYTHON_DLL_RELATIVE_PATH)
433+
#ifdef _WIN32
434+
#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
434435
/// Returns the full path to the lldb.exe executable.
435436
inline std::wstring GetPathToExecutableW() {
436437
// Iterate until we reach the Windows API maximum path length (32,767).
@@ -444,30 +445,72 @@ inline std::wstring GetPathToExecutableW() {
444445
return L"";
445446
}
446447

447-
/// Resolve the full path of the directory defined by
448+
/// \brief Resolve the full path of the directory defined by
448449
/// LLDB_PYTHON_DLL_RELATIVE_PATH. If it exists, add it to the list of DLL
449450
/// search directories.
450-
void AddPythonDLLToSearchPath() {
451+
/// \return `true` if the library was added to the search path.
452+
/// `false` otherwise.
453+
bool AddPythonDLLToSearchPath() {
451454
std::wstring modulePath = GetPathToExecutableW();
452-
if (modulePath.empty()) {
453-
llvm::errs() << "error: unable to find python.dll." << '\n';
454-
return;
455-
}
455+
if (modulePath.empty())
456+
return false;
456457

457458
SmallVector<char, MAX_PATH> utf8Path;
458459
if (sys::windows::UTF16ToUTF8(modulePath.c_str(), modulePath.length(),
459460
utf8Path))
460-
return;
461+
return false;
461462
sys::path::remove_filename(utf8Path);
462463
sys::path::append(utf8Path, LLDB_PYTHON_DLL_RELATIVE_PATH);
463464
sys::fs::make_absolute(utf8Path);
464465

465466
SmallVector<wchar_t, 1> widePath;
466467
if (sys::windows::widenPath(utf8Path.data(), widePath))
467-
return;
468+
return false;
468469

469470
if (sys::fs::exists(utf8Path))
470-
SetDllDirectoryW(widePath.data());
471+
return SetDllDirectoryW(widePath.data());
472+
return false;
473+
}
474+
#endif
475+
476+
#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
477+
/// Returns true if `python3x.dll` can be loaded.
478+
bool IsPythonDLLInPath() {
479+
#define WIDEN2(x) L##x
480+
#define WIDEN(x) WIDEN2(x)
481+
HMODULE h = LoadLibraryW(WIDEN(LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME));
482+
if (!h)
483+
return false;
484+
FreeLibrary(h);
485+
return true;
486+
#undef WIDEN2
487+
#undef WIDEN
488+
}
489+
#endif
490+
491+
/// Try to setup the DLL search path for the Python Runtime Library
492+
/// (python3xx.dll).
493+
///
494+
/// If `LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME` is set, we first check if
495+
/// python3xx.dll is in the search path. If it's not, we try to add it and
496+
/// check for it a second time.
497+
/// If only `LLDB_PYTHON_DLL_RELATIVE_PATH` is set, we try to add python3xx.dll
498+
/// to the search path python.dll is already in the search path or not.
499+
void SetupPythonRuntimeLibrary() {
500+
#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
501+
if (IsPythonDLLInPath())
502+
return;
503+
#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
504+
if (AddPythonDLLToSearchPath() && IsPythonDLLInPath())
505+
return;
506+
#endif
507+
WithColor::error() << "unable to find '"
508+
<< LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME << "'.\n";
509+
return;
510+
#elif defined(LLDB_PYTHON_DLL_RELATIVE_PATH)
511+
if (!AddPythonDLLToSearchPath())
512+
WithColor::error() << "unable to find the Python runtime library.\n";
513+
#endif
471514
}
472515
#endif
473516

@@ -801,8 +844,8 @@ int main(int argc, char const *argv[]) {
801844
"~/Library/Logs/DiagnosticReports/.\n");
802845
#endif
803846

804-
#if defined(_WIN32) && defined(LLDB_PYTHON_DLL_RELATIVE_PATH)
805-
AddPythonDLLToSearchPath();
847+
#ifdef _WIN32
848+
SetupPythonRuntimeLibrary();
806849
#endif
807850

808851
// Parse arguments.

0 commit comments

Comments
 (0)