66
66
#include " ggml-kompute.h"
67
67
#endif
68
68
69
+ // disable C++17 deprecation warning for std::codecvt_utf8
70
+ #if defined(__clang__)
71
+ # pragma clang diagnostic push
72
+ # pragma clang diagnostic ignored "-Wdeprecated-declarations"
73
+ #endif
74
+
75
+ static std::wstring utf8_to_utf16 (const std::string & str) {
76
+ std::wstring_convert<std::codecvt_utf8_utf16<wchar_t >> converter;
77
+ return converter.from_bytes (str);
78
+ }
79
+
80
+ static std::string utf16_to_utf8 (const std::wstring & str) {
81
+ std::wstring_convert<std::codecvt_utf8_utf16<wchar_t >> converter;
82
+ return converter.to_bytes (str);
83
+ }
84
+
85
+ #if defined(__clang__)
86
+ # pragma clang diagnostic pop
87
+ #endif
88
+
69
89
#ifdef _WIN32
70
90
71
91
using dl_handle = std::remove_pointer_t <HMODULE>;
@@ -88,11 +108,6 @@ static dl_handle * dl_load_library(const std::wstring & path) {
88
108
return handle;
89
109
}
90
110
91
- static dl_handle * dl_load_library (const std::string & path) {
92
- std::wstring_convert<std::codecvt_utf8_utf16<wchar_t >> converter;
93
- return dl_load_library (converter.from_bytes (path));
94
- }
95
-
96
111
static void * dl_get_sym (dl_handle * handle, const char * name) {
97
112
DWORD old_mode = SetErrorMode (SEM_FAILCRITICALERRORS);
98
113
SetErrorMode (old_mode | SEM_FAILCRITICALERRORS);
@@ -114,8 +129,8 @@ struct dl_handle_deleter {
114
129
}
115
130
};
116
131
117
- static void * dl_load_library (const std::string & path) {
118
- dl_handle * handle = dlopen (path.c_str (), RTLD_NOW | RTLD_LOCAL);
132
+ static void * dl_load_library (const std::wstring & path) {
133
+ dl_handle * handle = dlopen (utf16_to_utf8 ( path) .c_str (), RTLD_NOW | RTLD_LOCAL);
119
134
120
135
return handle;
121
136
}
@@ -202,27 +217,27 @@ struct ggml_backend_registry {
202
217
devices.push_back (device);
203
218
}
204
219
205
- ggml_backend_reg_t load_backend (const char * path, bool silent) {
220
+ ggml_backend_reg_t load_backend (const std::wstring & path, bool silent) {
206
221
dl_handle_ptr handle { dl_load_library (path) };
207
222
if (!handle) {
208
223
if (!silent) {
209
- GGML_LOG_ERROR (" %s: failed to load %s\n " , __func__, path);
224
+ GGML_LOG_ERROR (" %s: failed to load %s\n " , __func__, utf16_to_utf8 ( path). c_str () );
210
225
}
211
226
return nullptr ;
212
227
}
213
228
214
229
auto score_fn = (ggml_backend_score_t ) dl_get_sym (handle.get (), " ggml_backend_score" );
215
230
if (score_fn && score_fn () == 0 ) {
216
231
if (!silent) {
217
- GGML_LOG_INFO (" %s: backend %s is not supported on this system\n " , __func__, path);
232
+ GGML_LOG_INFO (" %s: backend %s is not supported on this system\n " , __func__, utf16_to_utf8 ( path). c_str () );
218
233
}
219
234
return nullptr ;
220
235
}
221
236
222
237
auto backend_init_fn = (ggml_backend_init_t ) dl_get_sym (handle.get (), " ggml_backend_init" );
223
238
if (!backend_init_fn) {
224
239
if (!silent) {
225
- GGML_LOG_ERROR (" %s: failed to find ggml_backend_init in %s\n " , __func__, path);
240
+ GGML_LOG_ERROR (" %s: failed to find ggml_backend_init in %s\n " , __func__, utf16_to_utf8 ( path). c_str () );
226
241
}
227
242
return nullptr ;
228
243
}
@@ -231,16 +246,16 @@ struct ggml_backend_registry {
231
246
if (!reg || reg->api_version != GGML_BACKEND_API_VERSION) {
232
247
if (!silent) {
233
248
if (!reg) {
234
- GGML_LOG_ERROR (" %s: failed to initialize backend from %s: ggml_backend_init returned NULL\n " , __func__, path);
249
+ GGML_LOG_ERROR (" %s: failed to initialize backend from %s: ggml_backend_init returned NULL\n " , __func__, utf16_to_utf8 ( path). c_str () );
235
250
} else {
236
251
GGML_LOG_ERROR (" %s: failed to initialize backend from %s: incompatible API version (backend: %d, current: %d)\n " ,
237
- __func__, path, reg->api_version , GGML_BACKEND_API_VERSION);
252
+ __func__, utf16_to_utf8 ( path). c_str () , reg->api_version , GGML_BACKEND_API_VERSION);
238
253
}
239
254
}
240
255
return nullptr ;
241
256
}
242
257
243
- GGML_LOG_INFO (" %s: loaded %s backend from %s\n " , __func__, ggml_backend_reg_name (reg), path);
258
+ GGML_LOG_INFO (" %s: loaded %s backend from %s\n " , __func__, ggml_backend_reg_name (reg), utf16_to_utf8 ( path). c_str () );
244
259
245
260
register_backend (reg, std::move (handle));
246
261
@@ -376,14 +391,14 @@ ggml_backend_t ggml_backend_init_best(void) {
376
391
377
392
// Dynamic loading
378
393
ggml_backend_reg_t ggml_backend_load (const char * path) {
379
- return get_reg ().load_backend (path, false );
394
+ return get_reg ().load_backend (utf8_to_utf16 ( path) , false );
380
395
}
381
396
382
397
void ggml_backend_unload (ggml_backend_reg_t reg) {
383
398
get_reg ().unload_backend (reg, true );
384
399
}
385
400
386
- static std::string get_executable_path () {
401
+ static std::wstring get_executable_path () {
387
402
#if defined(__APPLE__)
388
403
// get executable path
389
404
std::vector<char > path;
@@ -401,7 +416,7 @@ static std::string get_executable_path() {
401
416
if (last_slash != std::string::npos) {
402
417
base_path = base_path.substr (0 , last_slash);
403
418
}
404
- return base_path + " /" ;
419
+ return utf8_to_utf16 ( base_path + " /" ) ;
405
420
#elif defined(__linux__) || defined(__FreeBSD__)
406
421
std::string base_path = " ." ;
407
422
std::vector<char > path (1024 );
@@ -427,57 +442,63 @@ static std::string get_executable_path() {
427
442
path.resize (path.size () * 2 );
428
443
}
429
444
430
- return base_path + " /" ;
445
+ return utf8_to_utf16 ( base_path + " /" ) ;
431
446
#elif defined(_WIN32)
432
- std::vector<char > path (MAX_PATH);
433
- DWORD len = GetModuleFileNameA (NULL , path.data (), path.size ());
447
+ std::vector<wchar_t > path (MAX_PATH);
448
+ DWORD len = GetModuleFileNameW (NULL , path.data (), path.size ());
434
449
if (len == 0 ) {
435
- return " " ;
450
+ return {} ;
436
451
}
437
- std::string base_path (path.data (), len);
452
+ std::wstring base_path (path.data (), len);
438
453
// remove executable name
439
454
auto last_slash = base_path.find_last_of (' \\ ' );
440
455
if (last_slash != std::string::npos) {
441
456
base_path = base_path.substr (0 , last_slash);
442
457
}
443
- return base_path + " \\ " ;
458
+ return base_path + L" \\ " ;
459
+ #else
460
+ return {};
461
+ #endif
462
+ }
463
+
464
+ static std::wstring backend_filename_prefix () {
465
+ #ifdef _WIN32
466
+ return L" ggml-" ;
467
+ #else
468
+ return L" libggml-" ;
444
469
#endif
445
470
}
446
471
447
- static std::string backend_filename_prefix () {
472
+ static std::wstring backend_filename_suffix () {
448
473
#ifdef _WIN32
449
- return " ggml- " ;
474
+ return L" .dll " ;
450
475
#else
451
- return " libggml- " ;
476
+ return L" .so " ;
452
477
#endif
453
478
}
454
479
455
- static std::string backend_filename_suffix () {
480
+ static std::wstring path_separator () {
456
481
#ifdef _WIN32
457
- return " .dll " ;
482
+ return L" \\ " ;
458
483
#else
459
- return " .so " ;
484
+ return L" / " ;
460
485
#endif
461
486
}
462
487
463
488
static ggml_backend_reg_t ggml_backend_load_best (const char * name, bool silent, const char * user_search_path) {
464
489
// enumerate all the files that match [lib]ggml-name-*.[so|dll] in the search paths
465
490
// TODO: search system paths
466
- std::string file_prefix = backend_filename_prefix () + name + " -" ;
467
- std::vector<std::string > search_paths;
491
+ std::wstring file_prefix = backend_filename_prefix () + utf8_to_utf16 ( name) + L " -" ;
492
+ std::vector<std::wstring > search_paths;
468
493
if (user_search_path == nullptr ) {
469
- search_paths.push_back (" ./ " );
494
+ search_paths.push_back (L" . " + path_separator () );
470
495
search_paths.push_back (get_executable_path ());
471
496
} else {
472
- #if defined(_WIN32)
473
- search_paths.push_back (std::string (user_search_path) + " \\ " );
474
- #else
475
- search_paths.push_back (std::string (user_search_path) + " /" );
476
- #endif
497
+ search_paths.push_back (utf8_to_utf16 (user_search_path) + path_separator ());
477
498
}
478
499
479
500
int best_score = 0 ;
480
- std::string best_path;
501
+ std::wstring best_path;
481
502
482
503
namespace fs = std::filesystem;
483
504
for (const auto & search_path : search_paths) {
@@ -487,27 +508,27 @@ static ggml_backend_reg_t ggml_backend_load_best(const char * name, bool silent,
487
508
fs::directory_iterator dir_it (search_path, fs::directory_options::skip_permission_denied);
488
509
for (const auto & entry : dir_it) {
489
510
if (entry.is_regular_file ()) {
490
- std::string filename = entry.path ().filename ().string ();
491
- std::string ext = entry.path ().extension ().string ();
511
+ std::wstring filename = entry.path ().filename ().wstring ();
512
+ std::wstring ext = entry.path ().extension ().wstring ();
492
513
if (filename.find (file_prefix) == 0 && ext == backend_filename_suffix ()) {
493
- dl_handle_ptr handle { dl_load_library (entry.path ().c_str ()) };
514
+ dl_handle_ptr handle { dl_load_library (entry.path ().wstring ()) };
494
515
if (!handle && !silent) {
495
- GGML_LOG_ERROR (" %s: failed to load %s\n " , __func__, entry.path ().string ( ).c_str ());
516
+ GGML_LOG_ERROR (" %s: failed to load %s\n " , __func__, utf16_to_utf8 ( entry.path ().wstring () ).c_str ());
496
517
}
497
518
if (handle) {
498
519
auto score_fn = (ggml_backend_score_t ) dl_get_sym (handle.get (), " ggml_backend_score" );
499
520
if (score_fn) {
500
521
int s = score_fn ();
501
522
#ifndef NDEBUG
502
- GGML_LOG_DEBUG (" %s: %s score: %d\n " , __func__, entry.path ().string ( ).c_str (), s);
523
+ GGML_LOG_DEBUG (" %s: %s score: %d\n " , __func__, utf16_to_utf8 ( entry.path ().wstring () ).c_str (), s);
503
524
#endif
504
525
if (s > best_score) {
505
526
best_score = s;
506
- best_path = entry.path ().string ();
527
+ best_path = entry.path ().wstring ();
507
528
}
508
529
} else {
509
530
if (!silent) {
510
- GGML_LOG_INFO (" %s: failed to find ggml_backend_score in %s\n " , __func__, entry.path ().string ( ).c_str ());
531
+ GGML_LOG_INFO (" %s: failed to find ggml_backend_score in %s\n " , __func__, utf16_to_utf8 ( entry.path ().wstring () ).c_str ());
511
532
}
512
533
}
513
534
}
@@ -519,15 +540,15 @@ static ggml_backend_reg_t ggml_backend_load_best(const char * name, bool silent,
519
540
if (best_score == 0 ) {
520
541
// try to load the base backend
521
542
for (const auto & search_path : search_paths) {
522
- std::string path = search_path + backend_filename_prefix () + name + backend_filename_suffix ();
543
+ std::wstring path = search_path + backend_filename_prefix () + utf8_to_utf16 ( name) + backend_filename_suffix ();
523
544
if (fs::exists (path)) {
524
- return get_reg ().load_backend (path. c_str () , silent);
545
+ return get_reg ().load_backend (path, silent);
525
546
}
526
547
}
527
548
return nullptr ;
528
549
}
529
550
530
- return get_reg ().load_backend (best_path. c_str () , silent);
551
+ return get_reg ().load_backend (best_path, silent);
531
552
}
532
553
533
554
void ggml_backend_load_all () {
0 commit comments