Skip to content

Commit bedc0bf

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 4d15cb9 commit bedc0bf

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

lldb/cmake/modules/AddLLDB.cmake

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ function(add_lldb_executable name)
248248
)
249249

250250
target_link_libraries(${name} PRIVATE ${ARG_LINK_LIBS})
251+
if(WIN32)
252+
list(FIND ARG_LINK_LIBS liblldb LIBLLDB_INDEX)
253+
if(NOT LIBLLDB_INDEX EQUAL -1)
254+
target_link_options(${name} PRIVATE "/DELAYLOAD:$<TARGET_FILE_BASE_NAME:liblldb>.dll")
255+
endif()
256+
endif()
251257
if(CLANG_LINK_CLANG_DYLIB)
252258
target_link_libraries(${name} PRIVATE clang-cpp)
253259
else()

lldb/tools/driver/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ add_dependencies(lldb
3434
${tablegen_deps}
3535
)
3636

37+
if(DEFINED LLDB_PYTHON_DLL_RELATIVE_PATH)
38+
target_compile_definitions(lldb PRIVATE LLDB_PYTHON_DLL_RELATIVE_PATH="${LLDB_PYTHON_DLL_RELATIVE_PATH}")
39+
endif()
40+
3741
if(LLDB_BUILD_FRAMEWORK)
3842
# In the build-tree, we know the exact path to the framework directory.
3943
# The installed framework can be in different locations.

lldb/tools/driver/Driver.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,22 @@
2222
#include "lldb/Host/MainLoop.h"
2323
#include "lldb/Host/MainLoopBase.h"
2424
#include "lldb/Utility/Status.h"
25+
26+
#include "llvm/ADT/SmallString.h"
2527
#include "llvm/ADT/StringRef.h"
28+
#include "llvm/Support/ConvertUTF.h"
29+
#include "llvm/Support/FileSystem.h"
2630
#include "llvm/Support/Format.h"
2731
#include "llvm/Support/InitLLVM.h"
2832
#include "llvm/Support/Path.h"
2933
#include "llvm/Support/Signals.h"
3034
#include "llvm/Support/WithColor.h"
3135
#include "llvm/Support/raw_ostream.h"
3236

37+
#ifdef _WIN32
38+
#include "llvm/Support/Windows/WindowsSupport.h"
39+
#endif
40+
3341
#include <algorithm>
3442
#include <atomic>
3543
#include <bitset>
@@ -436,6 +444,47 @@ SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) {
436444
return error;
437445
}
438446

447+
#ifdef _WIN32
448+
/// Returns the full path to the lldb.exe executable.
449+
inline std::wstring GetPathToExecutableW() {
450+
// Iterate until we reach the Windows API maximum path length (32,767).
451+
std::vector<WCHAR> buffer;
452+
buffer.resize(MAX_PATH /*=260*/);
453+
while (buffer.size() < 32767) {
454+
if (GetModuleFileNameW(NULL, buffer.data(), buffer.size()) < buffer.size())
455+
return std::wstring(buffer.begin(), buffer.end());
456+
buffer.resize(buffer.size() * 2);
457+
}
458+
return L"";
459+
}
460+
461+
/// Resolve the full path of the directory defined by
462+
/// LLDB_PYTHON_DLL_RELATIVE_PATH. If it exists, add it to the list of DLL
463+
/// search directories.
464+
void AddPythonDLLToSearchPath() {
465+
std::wstring modulePath = GetPathToExecutableW();
466+
if (modulePath.empty()) {
467+
llvm::errs() << "error: unable to find python.dll." << '\n';
468+
return;
469+
}
470+
471+
SmallVector<char, MAX_PATH> utf8Path;
472+
if (sys::windows::UTF16ToUTF8(modulePath.c_str(), modulePath.length(),
473+
utf8Path))
474+
return;
475+
sys::path::remove_filename(utf8Path);
476+
sys::path::append(utf8Path, LLDB_PYTHON_DLL_RELATIVE_PATH);
477+
sys::fs::make_absolute(utf8Path);
478+
479+
SmallVector<wchar_t, 1> widePath;
480+
if (sys::windows::widenPath(utf8Path.data(), widePath))
481+
return;
482+
483+
if (sys::fs::exists(utf8Path))
484+
SetDllDirectoryW(widePath.data());
485+
}
486+
#endif
487+
439488
std::string EscapeString(std::string arg) {
440489
std::string::size_type pos = 0;
441490
while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) {
@@ -738,6 +787,10 @@ int main(int argc, char const *argv[]) {
738787
"~/Library/Logs/DiagnosticReports/.\n");
739788
#endif
740789

790+
#if defined(_WIN32) && defined(LLDB_PYTHON_DLL_RELATIVE_PATH)
791+
AddPythonDLLToSearchPath();
792+
#endif
793+
741794
// Parse arguments.
742795
LLDBOptTable T;
743796
unsigned MissingArgIndex;

0 commit comments

Comments
 (0)