LLDB mainline
PythonPathSetup.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
12#include "llvm/Support/Windows/WindowsSupport.h"
13
14#include "llvm/ADT/SmallVector.h"
15#include "llvm/Support/ConvertUTF.h"
16#include "llvm/Support/FileSystem.h"
17#include "llvm/Support/Path.h"
18#include <pathcch.h>
19
20using namespace llvm;
21
22#if defined(LLDB_PYTHON_DLL_RELATIVE_PATH) || \
23 defined(LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME)
24static std::string GetModulePath(HMODULE module) {
25 std::vector<WCHAR> buffer(MAX_PATH);
26 while (buffer.size() <= PATHCCH_MAX_CCH) {
27 DWORD len = GetModuleFileNameW(module, buffer.data(), buffer.size());
28 if (len == 0)
29 return "";
30 if (len < buffer.size()) {
31 std::string buffer_utf8;
32 if (convertWideToUTF8(std::wstring(buffer.data(), len), buffer_utf8))
33 return buffer_utf8;
34 return "";
35 }
36 if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
37 buffer.resize(buffer.size() * 2);
38 }
39 return "";
40}
41#endif
42
43#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
44/// Returns the full path to the lldb.exe executable.
45static std::string GetPathToExecutable() { return GetModulePath(NULL); }
46
47bool AddPythonDLLToSearchPath() {
48 std::string path_str = GetPathToExecutable();
49 if (path_str.empty())
50 return false;
51
52 SmallVector<char, MAX_PATH> path(path_str.begin(), path_str.end());
53 sys::path::remove_filename(path);
54 sys::path::append(path, LLDB_PYTHON_DLL_RELATIVE_PATH);
55 sys::fs::make_absolute(path);
56
57 SmallVector<wchar_t, 1> path_wide;
58 if (sys::windows::widenPath(path.data(), path_wide))
59 return false;
60
61 if (sys::fs::exists(path))
62 return SetDllDirectoryW(path_wide.data());
63 return false;
64}
65#endif
66
67#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
68std::optional<std::string> GetPythonDLLPath() {
69#define WIDEN2(x) L##x
70#define WIDEN(x) WIDEN2(x)
71 HMODULE h = LoadLibraryW(WIDEN(LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME));
72 if (!h)
73 return std::nullopt;
74
75 std::string path = GetModulePath(h);
76 FreeLibrary(h);
77
78 return path;
79#undef WIDEN2
80#undef WIDEN
81}
82#endif
83
84llvm::Expected<std::string> SetupPythonRuntimeLibrary() {
85#ifdef LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME
86 if (std::optional<std::string> python_path = GetPythonDLLPath())
87 return *python_path;
88#ifdef LLDB_PYTHON_DLL_RELATIVE_PATH
89 if (AddPythonDLLToSearchPath()) {
90 if (std::optional<std::string> python_path = GetPythonDLLPath())
91 return *python_path;
92 }
93#endif
94 return createStringError(
95 inconvertibleErrorCode(),
96 "unable to find '" LLDB_PYTHON_RUNTIME_LIBRARY_FILENAME "'");
97#elif defined(LLDB_PYTHON_DLL_RELATIVE_PATH)
98 if (!AddPythonDLLToSearchPath())
99 return createStringError(inconvertibleErrorCode(),
100 "unable to find the Python runtime library");
101#endif
102 return "";
103}
llvm::Expected< std::string > SetupPythonRuntimeLibrary()
Attempts to setup the DLL search path for the Python runtime library.