Skip to content

Commit 9380c15

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 9380c15

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
@@ -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: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,21 @@
2222
#include "lldb/Host/MainLoop.h"
2323
#include "lldb/Host/MainLoopBase.h"
2424
#include "lldb/Utility/Status.h"
25+
#include "llvm/ADT/SmallString.h"
2526
#include "llvm/ADT/StringRef.h"
27+
#include "llvm/Support/ConvertUTF.h"
28+
#include "llvm/Support/FileSystem.h"
2629
#include "llvm/Support/Format.h"
2730
#include "llvm/Support/InitLLVM.h"
2831
#include "llvm/Support/Path.h"
2932
#include "llvm/Support/Signals.h"
3033
#include "llvm/Support/WithColor.h"
3134
#include "llvm/Support/raw_ostream.h"
3235

36+
#ifdef _WIN32
37+
#include "llvm/Support/Windows/WindowsSupport.h"
38+
#endif
39+
3340
#include <algorithm>
3441
#include <atomic>
3542
#include <bitset>
@@ -436,6 +443,47 @@ SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) {
436443
return error;
437444
}
438445

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

789+
#if defined(_WIN32) && defined(LLDB_PYTHON_DLL_RELATIVE_PATH)
790+
AddPythonDLLToSearchPath();
791+
#endif
792+
741793
// Parse arguments.
742794
LLDBOptTable T;
743795
unsigned MissingArgIndex;

0 commit comments

Comments
 (0)