Implement [`[RFC] Add a Python check command to lldb-dap and lldb`](https://discourse.llvm.org/t/rfc-add-a-python-check-command-to-lldb-dap-and-lldb/88972). This patch adds the `--check-python` flag to `lldb-dap` on Windows, to allow dap clients to verify the correct Python version is available before trying to start `lldb-dap`. Depends on: - https://github.com/llvm/llvm-project/pull/180786 rdar://165442474
101 lines
3.0 KiB
C++
101 lines
3.0 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Host/windows/PythonPathSetup/PythonPathSetup.h"
|
|
|
|
#include "lldb/Host/windows/windows.h"
|
|
#include "llvm/Support/Windows/WindowsSupport.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/Support/ConvertUTF.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include <pathcch.h>
|
|
|
|
using namespace llvm;
|
|
|
|
#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
|
|
static std::string GetModulePath(HMODULE module) {
|
|
std::vector<WCHAR> buffer(MAX_PATH);
|
|
while (buffer.size() <= PATHCCH_MAX_CCH) {
|
|
DWORD len = GetModuleFileNameW(module, buffer.data(), buffer.size());
|
|
if (len == 0)
|
|
return "";
|
|
if (len < buffer.size()) {
|
|
std::string buffer_utf8;
|
|
if (convertWideToUTF8(std::wstring(buffer.data(), len), buffer_utf8))
|
|
return buffer_utf8;
|
|
return "";
|
|
}
|
|
if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
buffer.resize(buffer.size() * 2);
|
|
}
|
|
return "";
|
|
}
|
|
|
|
/// Returns the full path to the lldb.exe executable.
|
|
static std::string GetPathToExecutable() { return GetModulePath(NULL); }
|
|
|
|
bool AddPythonDLLToSearchPath() {
|
|
std::string path_str = GetPathToExecutable();
|
|
if (path_str.empty())
|
|
return false;
|
|
|
|
SmallVector<char, MAX_PATH> path(path_str.begin(), path_str.end());
|
|
sys::path::remove_filename(path);
|
|
sys::path::append(path, LLDB_PYTHON_DLL_RELATIVE_PATH);
|
|
sys::fs::make_absolute(path);
|
|
|
|
SmallVector<wchar_t, 1> path_wide;
|
|
if (sys::windows::widenPath(path.data(), path_wide))
|
|
return false;
|
|
|
|
if (sys::fs::exists(path))
|
|
return SetDllDirectoryW(path_wide.data());
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
|
|
std::optional<std::string> GetPythonDLLPath() {
|
|
#define WIDEN2(x) L##x
|
|
#define WIDEN(x) WIDEN2(x)
|
|
HMODULE h = LoadLibraryW(WIDEN(LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME));
|
|
if (!h)
|
|
return std::nullopt;
|
|
|
|
std::string path = GetModulePath(h);
|
|
FreeLibrary(h);
|
|
|
|
return path;
|
|
#undef WIDEN2
|
|
#undef WIDEN
|
|
}
|
|
#endif
|
|
|
|
llvm::Expected<std::string> SetupPythonRuntimeLibrary() {
|
|
#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
|
|
if (std::optional<std::string> python_path = GetPythonDLLPath())
|
|
return *python_path;
|
|
#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
|
|
if (AddPythonDLLToSearchPath()) {
|
|
if (std::optional<std::string> python_path = GetPythonDLLPath())
|
|
return *python_path;
|
|
}
|
|
#endif
|
|
return createStringError(
|
|
inconvertibleErrorCode(),
|
|
"unable to find '" LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME "'");
|
|
#elif defined(LLDB_PYTHON_DLL_RELATIVE_PATH)
|
|
if (!AddPythonDLLToSearchPath())
|
|
return createStringError(inconvertibleErrorCode(),
|
|
"unable to find the Python runtime library");
|
|
#endif
|
|
return "";
|
|
}
|