Skip to content

Commit 8bd7d92

Browse files
[lldb][windows] add support for out of PATH python.dll resolution (llvm#162509)
This patch adds the `LLDB_PYTHON_DLL_RELATIVE_PATH` Cmake variable which is the relative path to the directory containing `python.dll`. The path is relative to the directory containing `lldb.exe`. If this variable is set and the resolved path points to an existing directory, we call `SetDllDirectoryW` to add `python.dll` to the list of DLL search paths. This, combined with `liblldb.dll` being delay loaded, allows to package `python.dll` with the `llvm` installer.
1 parent 840bc2a commit 8bd7d92

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
lines changed

lldb/cmake/modules/AddLLDB.cmake

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,12 @@ function(add_lldb_executable name)
283283
)
284284

285285
target_link_libraries(${name} PRIVATE ${ARG_LINK_LIBS})
286+
if(WIN32)
287+
list(FIND ARG_LINK_LIBS liblldb LIBLLDB_INDEX)
288+
if(NOT LIBLLDB_INDEX EQUAL -1)
289+
target_link_options(${name} PRIVATE "/DELAYLOAD:$<TARGET_FILE_BASE_NAME:liblldb>.dll")
290+
endif()
291+
endif()
286292
if(CLANG_LINK_CLANG_DYLIB)
287293
target_link_libraries(${name} PRIVATE clang-cpp)
288294
else()

lldb/tools/driver/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ add_dependencies(lldb
2828
${tablegen_deps}
2929
)
3030

31+
if(DEFINED LLDB_PYTHON_DLL_RELATIVE_PATH)
32+
target_compile_definitions(lldb PRIVATE LLDB_PYTHON_DLL_RELATIVE_PATH="${LLDB_PYTHON_DLL_RELATIVE_PATH}")
33+
endif()
34+
3135
if(LLDB_BUILD_FRAMEWORK)
3236
# In the build-tree, we know the exact path to the framework directory.
3337
# The installed framework can be in different locations.

lldb/tools/driver/Driver.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,21 @@
2020
#include "lldb/API/SBStructuredData.h"
2121
#include "lldb/Host/Config.h"
2222

23+
#include "llvm/ADT/SmallString.h"
2324
#include "llvm/ADT/StringRef.h"
25+
#include "llvm/Support/ConvertUTF.h"
26+
#include "llvm/Support/FileSystem.h"
2427
#include "llvm/Support/Format.h"
2528
#include "llvm/Support/InitLLVM.h"
2629
#include "llvm/Support/Path.h"
2730
#include "llvm/Support/Signals.h"
2831
#include "llvm/Support/WithColor.h"
2932
#include "llvm/Support/raw_ostream.h"
3033

34+
#ifdef _WIN32
35+
#include "llvm/Support/Windows/WindowsSupport.h"
36+
#endif
37+
3138
#include <algorithm>
3239
#include <atomic>
3340
#include <bitset>
@@ -423,6 +430,47 @@ SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) {
423430
return error;
424431
}
425432

433+
#ifdef _WIN32
434+
/// Returns the full path to the lldb.exe executable.
435+
inline std::wstring GetPathToExecutableW() {
436+
// Iterate until we reach the Windows API maximum path length (32,767).
437+
std::vector<WCHAR> buffer;
438+
buffer.resize(MAX_PATH /*=260*/);
439+
while (buffer.size() < 32767) {
440+
if (GetModuleFileNameW(NULL, buffer.data(), buffer.size()) < buffer.size())
441+
return std::wstring(buffer.begin(), buffer.end());
442+
buffer.resize(buffer.size() * 2);
443+
}
444+
return L"";
445+
}
446+
447+
/// Resolve the full path of the directory defined by
448+
/// LLDB_PYTHON_DLL_RELATIVE_PATH. If it exists, add it to the list of DLL
449+
/// search directories.
450+
void AddPythonDLLToSearchPath() {
451+
std::wstring modulePath = GetPathToExecutableW();
452+
if (modulePath.empty()) {
453+
llvm::errs() << "error: unable to find python.dll." << '\n';
454+
return;
455+
}
456+
457+
SmallVector<char, MAX_PATH> utf8Path;
458+
if (sys::windows::UTF16ToUTF8(modulePath.c_str(), modulePath.length(),
459+
utf8Path))
460+
return;
461+
sys::path::remove_filename(utf8Path);
462+
sys::path::append(utf8Path, LLDB_PYTHON_DLL_RELATIVE_PATH);
463+
sys::fs::make_absolute(utf8Path);
464+
465+
SmallVector<wchar_t, 1> widePath;
466+
if (sys::windows::widenPath(utf8Path.data(), widePath))
467+
return;
468+
469+
if (sys::fs::exists(utf8Path))
470+
SetDllDirectoryW(widePath.data());
471+
}
472+
#endif
473+
426474
std::string EscapeString(std::string arg) {
427475
std::string::size_type pos = 0;
428476
while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) {
@@ -753,6 +801,10 @@ int main(int argc, char const *argv[]) {
753801
"~/Library/Logs/DiagnosticReports/.\n");
754802
#endif
755803

804+
#if defined(_WIN32) && defined(LLDB_PYTHON_DLL_RELATIVE_PATH)
805+
AddPythonDLLToSearchPath();
806+
#endif
807+
756808
// Parse arguments.
757809
LLDBOptTable T;
758810
unsigned MissingArgIndex;

0 commit comments

Comments
 (0)