Skip to content

Commit 364fbbd

Browse files
charles-zablitsvkeerthy
authored andcommitted
[lldb][windows] add support for out of PATH python.dll resolution (#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 6f5d746 commit 364fbbd

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
@@ -167,6 +167,12 @@ function(add_lldb_executable name)
167167
)
168168

169169
target_link_libraries(${name} PRIVATE ${ARG_LINK_LIBS})
170+
if(WIN32)
171+
list(FIND ARG_LINK_LIBS liblldb LIBLLDB_INDEX)
172+
if(NOT LIBLLDB_INDEX EQUAL -1)
173+
target_link_options(${name} PRIVATE "/DELAYLOAD:$<TARGET_FILE_BASE_NAME:liblldb>.dll")
174+
endif()
175+
endif()
170176
if(CLANG_LINK_CLANG_DYLIB)
171177
target_link_libraries(${name} PRIVATE clang-cpp)
172178
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>
@@ -426,6 +433,47 @@ SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) {
426433
return error;
427434
}
428435

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

779+
#if defined(_WIN32) && defined(LLDB_PYTHON_DLL_RELATIVE_PATH)
780+
AddPythonDLLToSearchPath();
781+
#endif
782+
731783
// Parse arguments.
732784
LLDBOptTable T;
733785
unsigned MissingArgIndex;

0 commit comments

Comments
 (0)