forked from ollama/ollama
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
llama: add patch to fix ggml backend reg on Linux with utf-8 characte…
…rs in the path (ollama#9159)
- Loading branch information
Showing
2 changed files
with
325 additions
and
76 deletions.
There are no files selected for viewing
285 changes: 285 additions & 0 deletions
285
llama/patches/0018-use-std-filesystem-path-instead-of-wstring.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,285 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: jmorganca <[email protected]> | ||
Date: Sun, 16 Feb 2025 20:00:22 -0500 | ||
Subject: [PATCH] use std::filesystem::path instead of wstring | ||
|
||
--- | ||
ggml/src/ggml-backend-reg.cpp | 116 ++++++++++++---------------------- | ||
1 file changed, 40 insertions(+), 76 deletions(-) | ||
|
||
diff --git a/ggml/src/ggml-backend-reg.cpp b/ggml/src/ggml-backend-reg.cpp | ||
index 84b21dd8..de78feae 100644 | ||
--- a/ggml/src/ggml-backend-reg.cpp | ||
+++ b/ggml/src/ggml-backend-reg.cpp | ||
@@ -72,16 +72,6 @@ | ||
# pragma clang diagnostic ignored "-Wdeprecated-declarations" | ||
#endif | ||
|
||
-static std::wstring utf8_to_utf16(const std::string & str) { | ||
- std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; | ||
- return converter.from_bytes(str); | ||
-} | ||
- | ||
-static std::string utf16_to_utf8(const std::wstring & str) { | ||
- std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; | ||
- return converter.to_bytes(str); | ||
-} | ||
- | ||
#if defined(__clang__) | ||
# pragma clang diagnostic pop | ||
#endif | ||
@@ -96,12 +86,12 @@ struct dl_handle_deleter { | ||
} | ||
}; | ||
|
||
-static dl_handle * dl_load_library(const std::wstring & path) { | ||
+static dl_handle * dl_load_library(const std::filesystem::path & path) { | ||
// suppress error dialogs for missing DLLs | ||
DWORD old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); | ||
SetErrorMode(old_mode | SEM_FAILCRITICALERRORS); | ||
|
||
- HMODULE handle = LoadLibraryW(path.c_str()); | ||
+ HMODULE handle = LoadLibraryW(path.wstring().c_str()); | ||
|
||
SetErrorMode(old_mode); | ||
|
||
@@ -129,8 +119,8 @@ struct dl_handle_deleter { | ||
} | ||
}; | ||
|
||
-static void * dl_load_library(const std::wstring & path) { | ||
- dl_handle * handle = dlopen(utf16_to_utf8(path).c_str(), RTLD_NOW | RTLD_LOCAL); | ||
+static void * dl_load_library(const std::filesystem::path & path) { | ||
+ dl_handle * handle = dlopen(path.string().c_str(), RTLD_NOW | RTLD_LOCAL); | ||
|
||
return handle; | ||
} | ||
@@ -222,11 +212,11 @@ struct ggml_backend_registry { | ||
); | ||
} | ||
|
||
- ggml_backend_reg_t load_backend(const std::wstring & path, bool silent) { | ||
+ ggml_backend_reg_t load_backend(const std::filesystem::path & path, bool silent) { | ||
dl_handle_ptr handle { dl_load_library(path) }; | ||
if (!handle) { | ||
if (!silent) { | ||
- GGML_LOG_ERROR("%s: failed to load %s\n", __func__, utf16_to_utf8(path).c_str()); | ||
+ GGML_LOG_ERROR("%s: failed to load %s\n", __func__, path.string().c_str()); | ||
} | ||
return nullptr; | ||
} | ||
@@ -234,7 +224,7 @@ struct ggml_backend_registry { | ||
auto score_fn = (ggml_backend_score_t) dl_get_sym(handle.get(), "ggml_backend_score"); | ||
if (score_fn && score_fn() == 0) { | ||
if (!silent) { | ||
- GGML_LOG_INFO("%s: backend %s is not supported on this system\n", __func__, utf16_to_utf8(path).c_str()); | ||
+ GGML_LOG_INFO("%s: backend %s is not supported on this system\n", __func__, path.string().c_str()); | ||
} | ||
return nullptr; | ||
} | ||
@@ -242,7 +232,7 @@ struct ggml_backend_registry { | ||
auto backend_init_fn = (ggml_backend_init_t) dl_get_sym(handle.get(), "ggml_backend_init"); | ||
if (!backend_init_fn) { | ||
if (!silent) { | ||
- GGML_LOG_ERROR("%s: failed to find ggml_backend_init in %s\n", __func__, utf16_to_utf8(path).c_str()); | ||
+ GGML_LOG_ERROR("%s: failed to find ggml_backend_init in %s\n", __func__, path.string().c_str()); | ||
} | ||
return nullptr; | ||
} | ||
@@ -251,16 +241,16 @@ struct ggml_backend_registry { | ||
if (!reg || reg->api_version != GGML_BACKEND_API_VERSION) { | ||
if (!silent) { | ||
if (!reg) { | ||
- GGML_LOG_ERROR("%s: failed to initialize backend from %s: ggml_backend_init returned NULL\n", __func__, utf16_to_utf8(path).c_str()); | ||
+ GGML_LOG_ERROR("%s: failed to initialize backend from %s: ggml_backend_init returned NULL\n", __func__, path.string().c_str()); | ||
} else { | ||
GGML_LOG_ERROR("%s: failed to initialize backend from %s: incompatible API version (backend: %d, current: %d)\n", | ||
- __func__, utf16_to_utf8(path).c_str(), reg->api_version, GGML_BACKEND_API_VERSION); | ||
+ __func__, path.string().c_str(), reg->api_version, GGML_BACKEND_API_VERSION); | ||
} | ||
} | ||
return nullptr; | ||
} | ||
|
||
- GGML_LOG_INFO("%s: loaded %s backend from %s\n", __func__, ggml_backend_reg_name(reg), utf16_to_utf8(path).c_str()); | ||
+ GGML_LOG_INFO("%s: loaded %s backend from %s\n", __func__, ggml_backend_reg_name(reg), path.string().c_str()); | ||
|
||
register_backend(reg, score_fn ? score_fn() : -1, std::move(handle)); | ||
|
||
@@ -396,14 +386,14 @@ ggml_backend_t ggml_backend_init_best(void) { | ||
|
||
// Dynamic loading | ||
ggml_backend_reg_t ggml_backend_load(const char * path) { | ||
- return get_reg().load_backend(utf8_to_utf16(path), false); | ||
+ return get_reg().load_backend(path, false); | ||
} | ||
|
||
void ggml_backend_unload(ggml_backend_reg_t reg) { | ||
get_reg().unload_backend(reg, true); | ||
} | ||
|
||
-static std::wstring get_executable_path() { | ||
+static std::filesystem::path get_executable_path() { | ||
#if defined(__APPLE__) | ||
// get executable path | ||
std::vector<char> path; | ||
@@ -415,15 +405,9 @@ static std::wstring get_executable_path() { | ||
} | ||
path.resize(size); | ||
} | ||
- std::string base_path(path.data(), size); | ||
- // remove executable name | ||
- auto last_slash = base_path.find_last_of('/'); | ||
- if (last_slash != std::string::npos) { | ||
- base_path = base_path.substr(0, last_slash); | ||
- } | ||
- return utf8_to_utf16(base_path + "/"); | ||
+ | ||
+ return std::filesystem::path(path.data()).parent_path(); | ||
#elif defined(__linux__) || defined(__FreeBSD__) | ||
- std::string base_path = "."; | ||
std::vector<char> path(1024); | ||
while (true) { | ||
// get executable path | ||
@@ -436,76 +420,56 @@ static std::wstring get_executable_path() { | ||
break; | ||
} | ||
if (len < (ssize_t) path.size()) { | ||
- base_path = std::string(path.data(), len); | ||
- // remove executable name | ||
- auto last_slash = base_path.find_last_of('/'); | ||
- if (last_slash != std::string::npos) { | ||
- base_path = base_path.substr(0, last_slash); | ||
- } | ||
- break; | ||
+ return std::filesystem::path(path.data()).parent_path(); | ||
} | ||
path.resize(path.size() * 2); | ||
} | ||
- | ||
- return utf8_to_utf16(base_path + "/"); | ||
#elif defined(_WIN32) | ||
std::vector<wchar_t> path(MAX_PATH); | ||
DWORD len = GetModuleFileNameW(NULL, path.data(), path.size()); | ||
if (len == 0) { | ||
return {}; | ||
} | ||
- std::wstring base_path(path.data(), len); | ||
- // remove executable name | ||
- auto last_slash = base_path.find_last_of('\\'); | ||
- if (last_slash != std::string::npos) { | ||
- base_path = base_path.substr(0, last_slash); | ||
- } | ||
- return base_path + L"\\"; | ||
-#else | ||
- return {}; | ||
-#endif | ||
-} | ||
|
||
-static std::wstring backend_filename_prefix() { | ||
-#ifdef _WIN32 | ||
- return L"ggml-"; | ||
+ return std::filesystem::path(path.data()).parent_path(); | ||
#else | ||
- return L"libggml-"; | ||
+ return {}; | ||
#endif | ||
} | ||
|
||
-static std::wstring backend_filename_suffix() { | ||
+static std::string backend_filename_prefix() { | ||
#ifdef _WIN32 | ||
- return L".dll"; | ||
+ return "ggml-"; | ||
#else | ||
- return L".so"; | ||
+ return "libggml-"; | ||
#endif | ||
} | ||
|
||
-static std::wstring path_separator() { | ||
+static std::string backend_filename_suffix() { | ||
#ifdef _WIN32 | ||
- return L"\\"; | ||
+ return ".dll"; | ||
#else | ||
- return L"/"; | ||
+ return ".so"; | ||
#endif | ||
} | ||
|
||
static ggml_backend_reg_t ggml_backend_load_best(const char * name, bool silent, const char * user_search_path) { | ||
// enumerate all the files that match [lib]ggml-name-*.[so|dll] in the search paths | ||
// TODO: search system paths | ||
- std::wstring file_prefix = backend_filename_prefix() + utf8_to_utf16(name) + L"-"; | ||
- std::vector<std::wstring> search_paths; | ||
+ namespace fs = std::filesystem; | ||
+ std::string file_prefix = backend_filename_prefix() + name + "-"; | ||
+ std::vector<fs::path> search_paths; | ||
+ | ||
if (user_search_path == nullptr) { | ||
- search_paths.push_back(L"." + path_separator()); | ||
+ search_paths.push_back(fs::current_path()); | ||
search_paths.push_back(get_executable_path()); | ||
} else { | ||
- search_paths.push_back(utf8_to_utf16(user_search_path) + path_separator()); | ||
+ search_paths.push_back(fs::u8path(user_search_path)); | ||
} | ||
|
||
int best_score = 0; | ||
- std::wstring best_path; | ||
+ fs::path best_path; | ||
|
||
- namespace fs = std::filesystem; | ||
for (const auto & search_path : search_paths) { | ||
if (!fs::exists(search_path)) { | ||
continue; | ||
@@ -514,31 +478,31 @@ static ggml_backend_reg_t ggml_backend_load_best(const char * name, bool silent, | ||
for (const auto & entry : dir_it) { | ||
try { | ||
if (entry.is_regular_file()) { | ||
- std::wstring filename = entry.path().filename().wstring(); | ||
- std::wstring ext = entry.path().extension().wstring(); | ||
+ std::string filename = entry.path().filename().string(); | ||
+ std::string ext = entry.path().extension().string(); | ||
if (filename.find(file_prefix) == 0 && ext == backend_filename_suffix()) { | ||
- dl_handle_ptr handle { dl_load_library(entry.path().wstring()) }; | ||
+ dl_handle_ptr handle { dl_load_library(entry.path()) }; | ||
if (!handle) { | ||
- GGML_LOG_ERROR("%s: failed to load %s\n", __func__, utf16_to_utf8(entry.path().wstring()).c_str()); | ||
+ GGML_LOG_ERROR("%s: failed to load %s\n", __func__, entry.path().string().c_str()); | ||
continue; | ||
} | ||
|
||
auto score_fn = (ggml_backend_score_t) dl_get_sym(handle.get(), "ggml_backend_score"); | ||
if (!score_fn) { | ||
- GGML_LOG_DEBUG("%s: failed to find ggml_backend_score in %s\n", __func__, utf16_to_utf8(entry.path().wstring()).c_str()); | ||
+ GGML_LOG_DEBUG("%s: failed to find ggml_backend_score in %s\n", __func__, entry.path().string().c_str()); | ||
continue; | ||
} | ||
|
||
int s = score_fn(); | ||
- GGML_LOG_DEBUG("%s: %s score: %d\n", __func__, utf16_to_utf8(entry.path().wstring()).c_str(), s); | ||
+ GGML_LOG_DEBUG("%s: %s score: %d\n", __func__, entry.path().string().c_str(), s); | ||
if (s > best_score) { | ||
best_score = s; | ||
- best_path = entry.path().wstring(); | ||
+ best_path = entry.path(); | ||
} | ||
} | ||
} | ||
} catch (const std::exception & e) { | ||
- GGML_LOG_ERROR("%s: failed to load %s: %s\n", __func__, utf16_to_utf8(entry.path().wstring()).c_str(), e.what()); | ||
+ GGML_LOG_ERROR("%s: failed to load %s: %s\n", __func__, entry.path().string().c_str(), e.what()); | ||
} | ||
} | ||
} | ||
@@ -546,7 +510,7 @@ static ggml_backend_reg_t ggml_backend_load_best(const char * name, bool silent, | ||
if (best_score == 0) { | ||
// try to load the base backend | ||
for (const auto & search_path : search_paths) { | ||
- std::wstring path = search_path + backend_filename_prefix() + utf8_to_utf16(name) + backend_filename_suffix(); | ||
+ fs::path path = fs::path(search_path) / (backend_filename_prefix() + name + backend_filename_suffix()); | ||
if (fs::exists(path)) { | ||
return get_reg().load_backend(path, silent); | ||
} |
Oops, something went wrong.