22#include  " ggml-backend.h" 
33#include  " ggml-impl.h" 
44#include  < algorithm> 
5- #include  < codecvt> 
65#include  < cstring> 
76#include  < filesystem> 
8- #include  < locale> 
97#include  < memory> 
108#include  < string> 
119#include  < type_traits> 
7270#    pragma  clang diagnostic ignored "-Wdeprecated-declarations"
7371#endif 
7472
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- }
73+ namespace  fs  =  std::filesystem;
7974
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);
75+ static  std::string path_str (const  fs::path & path) {
76+     std::string u8path;
77+     try  {
78+         u8path = path.u8string ();
79+     } catch  (...) {
80+     }
81+     return  u8path;
8382}
8483
8584#if  defined(__clang__)
@@ -96,12 +95,12 @@ struct dl_handle_deleter {
9695    }
9796};
9897
99- static  dl_handle * dl_load_library (const  std::wstring  & path) {
98+ static  dl_handle * dl_load_library (const  fs::path  & path) {
10099    //  suppress error dialogs for missing DLLs
101100    DWORD old_mode = SetErrorMode (SEM_FAILCRITICALERRORS);
102101    SetErrorMode (old_mode | SEM_FAILCRITICALERRORS);
103102
104-     HMODULE handle = LoadLibraryW (path.c_str ());
103+     HMODULE handle = LoadLibraryW (path.wstring (). c_str ());
105104
106105    SetErrorMode (old_mode);
107106
@@ -129,8 +128,8 @@ struct dl_handle_deleter {
129128    }
130129};
131130
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);
131+ static  void  * dl_load_library (const  fs::path  & path) {
132+     dl_handle * handle = dlopen (path. string ( ).c_str (), RTLD_NOW | RTLD_LOCAL);
134133
135134    return  handle;
136135}
@@ -217,27 +216,27 @@ struct ggml_backend_registry {
217216        devices.push_back (device);
218217    }
219218
220-     ggml_backend_reg_t  load_backend (const  std::wstring  & path, bool  silent) {
219+     ggml_backend_reg_t  load_backend (const  fs::path  & path, bool  silent) {
221220        dl_handle_ptr handle { dl_load_library (path) };
222221        if  (!handle) {
223222            if  (!silent) {
224-                 GGML_LOG_ERROR (" %s: failed to load %s\n " utf16_to_utf8 (path).c_str ());
223+                 GGML_LOG_ERROR (" %s: failed to load %s\n " path_str (path).c_str ());
225224            }
226225            return  nullptr ;
227226        }
228227
229228        auto  score_fn = (ggml_backend_score_t ) dl_get_sym (handle.get (), " ggml_backend_score" 
230229        if  (score_fn && score_fn () == 0 ) {
231230            if  (!silent) {
232-                 GGML_LOG_INFO (" %s: backend %s is not supported on this system\n " utf16_to_utf8 (path).c_str ());
231+                 GGML_LOG_INFO (" %s: backend %s is not supported on this system\n " path_str (path).c_str ());
233232            }
234233            return  nullptr ;
235234        }
236235
237236        auto  backend_init_fn = (ggml_backend_init_t ) dl_get_sym (handle.get (), " ggml_backend_init" 
238237        if  (!backend_init_fn) {
239238            if  (!silent) {
240-                 GGML_LOG_ERROR (" %s: failed to find ggml_backend_init in %s\n " utf16_to_utf8 (path).c_str ());
239+                 GGML_LOG_ERROR (" %s: failed to find ggml_backend_init in %s\n " path_str (path).c_str ());
241240            }
242241            return  nullptr ;
243242        }
@@ -246,16 +245,17 @@ struct ggml_backend_registry {
246245        if  (!reg || reg->api_version  != GGML_BACKEND_API_VERSION) {
247246            if  (!silent) {
248247                if  (!reg) {
249-                     GGML_LOG_ERROR (" %s: failed to initialize backend from %s: ggml_backend_init returned NULL\n " utf16_to_utf8 (path).c_str ());
248+                     GGML_LOG_ERROR (" %s: failed to initialize backend from %s: ggml_backend_init returned NULL\n " 
249+                         __func__, path_str (path).c_str ());
250250                } else  {
251251                    GGML_LOG_ERROR (" %s: failed to initialize backend from %s: incompatible API version (backend: %d, current: %d)\n " 
252-                         __func__, utf16_to_utf8 (path).c_str (), reg->api_version , GGML_BACKEND_API_VERSION);
252+                         __func__, path_str (path).c_str (), reg->api_version , GGML_BACKEND_API_VERSION);
253253                }
254254            }
255255            return  nullptr ;
256256        }
257257
258-         GGML_LOG_INFO (" %s: loaded %s backend from %s\n " ggml_backend_reg_name (reg), utf16_to_utf8 (path).c_str ());
258+         GGML_LOG_INFO (" %s: loaded %s backend from %s\n " ggml_backend_reg_name (reg), path_str (path).c_str ());
259259
260260        register_backend (reg, std::move (handle));
261261
@@ -391,14 +391,14 @@ ggml_backend_t ggml_backend_init_best(void) {
391391
392392//  Dynamic loading
393393ggml_backend_reg_t  ggml_backend_load (const  char  * path) {
394-     return  get_reg ().load_backend (utf8_to_utf16 ( path) , false );
394+     return  get_reg ().load_backend (path, false );
395395}
396396
397397void  ggml_backend_unload (ggml_backend_reg_t  reg) {
398398    get_reg ().unload_backend (reg, true );
399399}
400400
401- static  std::wstring  get_executable_path () {
401+ static  fs::path  get_executable_path () {
402402#if  defined(__APPLE__)
403403    //  get executable path
404404    std::vector<char > path;
@@ -416,7 +416,7 @@ static std::wstring get_executable_path() {
416416    if  (last_slash != std::string::npos) {
417417        base_path = base_path.substr (0 , last_slash);
418418    }
419-     return  utf8_to_utf16 ( base_path + " /" ) ;
419+     return  base_path + " /" 
420420#elif  defined(__linux__) || defined(__FreeBSD__)
421421    std::string base_path = " ." 
422422    std::vector<char > path (1024 );
@@ -442,7 +442,7 @@ static std::wstring get_executable_path() {
442442        path.resize (path.size () * 2 );
443443    }
444444
445-     return  utf8_to_utf16 ( base_path + " /" ) ;
445+     return  base_path + " /" 
446446#elif  defined(_WIN32)
447447    std::vector<wchar_t > path (MAX_PATH);
448448    DWORD len = GetModuleFileNameW (NULL , path.data (), path.size ());
@@ -461,74 +461,69 @@ static std::wstring get_executable_path() {
461461#endif 
462462}
463463
464- static  std::wstring backend_filename_prefix () {
465- #ifdef  _WIN32
466-     return  L" ggml-" 
467- #else 
468-     return  L" libggml-" 
469- #endif 
470- }
471- 
472- static  std::wstring backend_filename_suffix () {
464+ static  fs::path backend_filename_prefix () {
473465#ifdef  _WIN32
474-     return  L" .dll " 
466+     return  fs::u8path ( " ggml- " ) ;
475467#else 
476-     return  L" .so " 
468+     return  fs::u8path ( " libggml- " ) ;
477469#endif 
478470}
479471
480- static  std::wstring  path_separator () {
472+ static  fs::path  backend_filename_extension () {
481473#ifdef  _WIN32
482-     return  L" \\ " 
474+     return  fs::u8path ( " .dll " ) ;
483475#else 
484-     return  L" / " 
476+     return  fs::u8path ( " .so " ) ;
485477#endif 
486478}
487479
488480static  ggml_backend_reg_t  ggml_backend_load_best (const  char  * name, bool  silent, const  char  * user_search_path) {
489481    //  enumerate all the files that match [lib]ggml-name-*.[so|dll] in the search paths
490-      //  TODO: search system paths
491-     std::wstring file_prefix = backend_filename_prefix () + utf8_to_utf16 (name) + L" -" 
492-     std::vector<std::wstring> search_paths;
482+     const  fs::path name_path = fs::u8path (name);
483+     const  fs::path file_prefix = backend_filename_prefix ().native () + name_path.native () + fs::u8path (" -" native ();
484+     const  fs::path file_extension = backend_filename_extension ();
485+ 
486+     std::vector<fs::path> search_paths;
493487    if  (user_search_path == nullptr ) {
494-         search_paths. push_back ( L" . "  +  path_separator ()); 
488+         //  default search paths: executable directory, current directory 
495489        search_paths.push_back (get_executable_path ());
490+         search_paths.push_back (fs::current_path ());
496491    } else  {
497-         search_paths.push_back (utf8_to_utf16 ( user_search_path) +  path_separator () );
492+         search_paths.push_back (user_search_path);
498493    }
499494
500495    int  best_score = 0 ;
501-     std::wstring  best_path;
496+     fs::path  best_path;
502497
503-     namespace  fs  =  std::filesystem;
504498    for  (const  auto  & search_path : search_paths) {
505499        if  (!fs::exists (search_path)) {
500+             GGML_LOG_DEBUG (" %s: search path %s does not exist\n " path_str (search_path).c_str ());
506501            continue ;
507502        }
508503        fs::directory_iterator dir_it (search_path, fs::directory_options::skip_permission_denied);
509504        for  (const  auto  & entry : dir_it) {
510505            if  (entry.is_regular_file ()) {
511-                 std::wstring  filename = entry.path ().filename ().wstring ();
512-                 std::wstring  ext = entry.path ().extension ().wstring ();
513-                 if  (filename.find (file_prefix) == 0  && ext == backend_filename_suffix () ) {
514-                     dl_handle_ptr handle { dl_load_library (entry. path (). wstring () ) };
506+                 auto  filename = entry.path ().filename ().native ();
507+                 auto  ext = entry.path ().extension ().native ();
508+                 if  (filename.find (file_prefix) == 0  && ext == file_extension ) {
509+                     dl_handle_ptr handle { dl_load_library (entry) };
515510                    if  (!handle && !silent) {
516-                         GGML_LOG_ERROR (" %s: failed to load %s\n " utf16_to_utf8 (entry.path (). wstring ()).c_str ());
511+                         GGML_LOG_ERROR (" %s: failed to load %s\n " path_str (entry.path ()).c_str ());
517512                    }
518513                    if  (handle) {
519514                        auto  score_fn = (ggml_backend_score_t ) dl_get_sym (handle.get (), " ggml_backend_score" 
520515                        if  (score_fn) {
521516                            int  s = score_fn ();
522517#ifndef  NDEBUG
523-                             GGML_LOG_DEBUG (" %s: %s score: %d\n " utf16_to_utf8 (entry.path (). wstring ()).c_str (), s);
518+                             GGML_LOG_DEBUG (" %s: %s score: %d\n " path_str (entry.path ()).c_str (), s);
524519#endif 
525520                            if  (s > best_score) {
526521                                best_score = s;
527-                                 best_path = entry.path (). wstring () ;
522+                                 best_path = entry.path ();
528523                            }
529524                        } else  {
530525                            if  (!silent) {
531-                                 GGML_LOG_INFO (" %s: failed to find ggml_backend_score in %s\n " utf16_to_utf8 (entry.path (). wstring ()).c_str ());
526+                                 GGML_LOG_INFO (" %s: failed to find ggml_backend_score in %s\n " path_str (entry.path ()).c_str ());
532527                            }
533528                        }
534529                    }
@@ -540,7 +535,8 @@ static ggml_backend_reg_t ggml_backend_load_best(const char * name, bool silent,
540535    if  (best_score == 0 ) {
541536        //  try to load the base backend
542537        for  (const  auto  & search_path : search_paths) {
543-             std::wstring path = search_path + backend_filename_prefix () + utf8_to_utf16 (name) + backend_filename_suffix ();
538+             fs::path filename = backend_filename_prefix ().native () + name_path.native () + backend_filename_extension ().native ();
539+             fs::path path = search_path.native () + filename.native ();
544540            if  (fs::exists (path)) {
545541                return  get_reg ().load_backend (path, silent);
546542            }
0 commit comments