Skip to content

Commit 8ca07f9

Browse files
Merge pull request #11735 from charles-zablit/charles-zablit/lldb/python-check-to-stable
2 parents 4d78bb7 + 64aa88f commit 8ca07f9

File tree

4 files changed

+115
-0
lines changed

4 files changed

+115
-0
lines changed

lldb/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ if (LLDB_ENABLE_PYTHON)
113113
set(LLDB_PYTHON_EXT_SUFFIX "_d${LLDB_PYTHON_EXT_SUFFIX}")
114114
endif()
115115
endif()
116+
if(TARGET Python3::Python)
117+
get_target_property(_Python3_LIB_PATH Python3::Python IMPORTED_LIBRARY_LOCATION)
118+
if(_Python3_LIB_PATH)
119+
get_filename_component(LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME "${_Python3_LIB_PATH}" NAME)
120+
endif()
121+
endif()
116122
endif ()
117123

118124
if (LLDB_ENABLE_LUA)

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: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ 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+
if(DEFINED LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME)
41+
target_compile_definitions(lldb PRIVATE LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME="${LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME}")
42+
endif()
43+
3744
if(LLDB_BUILD_FRAMEWORK)
3845
# In the build-tree, we know the exact path to the framework directory.
3946
# The installed framework can be in different locations.

lldb/tools/driver/Driver.cpp

Lines changed: 96 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,91 @@ SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) {
436443
return error;
437444
}
438445

446+
#ifdef _WIN32
447+
#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
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+
/// \brief 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+
/// \return `true` if the library was added to the search path.
465+
/// `false` otherwise.
466+
bool AddPythonDLLToSearchPath() {
467+
std::wstring modulePath = GetPathToExecutableW();
468+
if (modulePath.empty())
469+
return false;
470+
471+
SmallVector<char, MAX_PATH> utf8Path;
472+
if (sys::windows::UTF16ToUTF8(modulePath.c_str(), modulePath.length(),
473+
utf8Path))
474+
return false;
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 false;
482+
483+
if (sys::fs::exists(utf8Path))
484+
return SetDllDirectoryW(widePath.data());
485+
return false;
486+
}
487+
#endif
488+
489+
#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
490+
/// Returns whether `python3x.dll` is in the DLL search path.
491+
bool IsPythonDLLInPath() {
492+
#define WIDEN2(x) L##x
493+
#define WIDEN(x) WIDEN2(x)
494+
WCHAR foundPath[MAX_PATH];
495+
DWORD result =
496+
SearchPathW(nullptr, WIDEN(LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME), nullptr,
497+
MAX_PATH, foundPath, nullptr);
498+
#undef WIDEN2
499+
#undef WIDEN
500+
501+
return result > 0;
502+
}
503+
#endif
504+
505+
/// Try to setup the DLL search path for the Python Runtime Library
506+
/// (python3xx.dll).
507+
///
508+
/// If `LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME` is set, we first check if
509+
/// python3xx.dll is in the search path. If it's not, we try to add it and
510+
/// check for it a second time.
511+
/// If only `LLDB_PYTHON_DLL_RELATIVE_PATH` is set, we try to add python3xx.dll
512+
/// to the search path python.dll is already in the search path or not.
513+
void SetupPythonRuntimeLibrary() {
514+
#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
515+
if (IsPythonDLLInPath())
516+
return;
517+
#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
518+
if (AddPythonDLLToSearchPath() && IsPythonDLLInPath())
519+
return;
520+
#endif
521+
llvm::errs() << "error: unable to find '"
522+
<< LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME << "'.\n";
523+
return;
524+
#elif defined(LLDB_PYTHON_DLL_RELATIVE_PATH)
525+
if (!AddPythonDLLToSearchPath())
526+
llvm::errs() << "error: unable to find the Python runtime library.\n";
527+
#endif
528+
}
529+
#endif
530+
439531
std::string EscapeString(std::string arg) {
440532
std::string::size_type pos = 0;
441533
while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) {
@@ -738,6 +830,10 @@ int main(int argc, char const *argv[]) {
738830
"~/Library/Logs/DiagnosticReports/.\n");
739831
#endif
740832

833+
#ifdef _WIN32
834+
SetupPythonRuntimeLibrary();
835+
#endif
836+
741837
// Parse arguments.
742838
LLDBOptTable T;
743839
unsigned MissingArgIndex;

0 commit comments

Comments
 (0)