diff --git a/common/arg.cpp b/common/arg.cpp index b70da5e9e..56ca9d3bf 100644 --- a/common/arg.cpp +++ b/common/arg.cpp @@ -717,24 +717,24 @@ void common_models_handler_apply(common_models_handler & handler, common_params // 1. system-wide: /etc/llama.cpp/config.ini (%PROGRAMDATA%\llama.cpp\config.ini on windows) // 2. user-level: ${XDG_CONFIG_HOME:-~/.config}/llama.cpp/config.ini (%APPDATA%\llama.cpp\config.ini on windows) static void common_params_apply_system_config(common_params & params, llama_example ex) { - std::vector paths; + std::vector paths; #if defined(_WIN32) - const std::string program_data = common_get_env("PROGRAMDATA"); + const std::filesystem::path program_data = common_get_path_from_env("PROGRAMDATA"); if (!program_data.empty()) { - paths.push_back(program_data + "\\llama.cpp\\config.ini"); + paths.push_back(program_data / "llama.cpp" / "config.ini"); } #else paths.push_back("/etc/llama.cpp/config.ini"); #endif try { - paths.push_back(fs_get_config_directory() + "config.ini"); + paths.push_back(fs_get_config_directory() / "config.ini"); } catch (const std::exception & e) { LOG_DBG("cannot read user-level config file, skipping: %s\n", e.what()); } - std::vector found; + std::vector found; for (const auto & path : paths) { std::error_code ec; if (std::filesystem::exists(path, ec)) { @@ -748,7 +748,7 @@ static void common_params_apply_system_config(common_params & params, llama_exam common_preset_context ctx(ex); ctx.ignore_unknown_keys = true; // the same config file is shared by all programs for (const auto & path : found) { - LOG_INF("using config file: %s\n", path.c_str()); + LOG_INF("using config file: %s\n", fs_path_to_utf8(path).c_str()); common_preset global; common_presets presets = ctx.load_from_ini(path, global); global.apply_to_params(params); diff --git a/common/common.cpp b/common/common.cpp index d1e7b7e5d..598a97d10 100644 --- a/common/common.cpp +++ b/common/common.cpp @@ -49,7 +49,7 @@ #include #endif -#if !defined(_WIN32) && !defined(__APPLE__) +#if !defined(_WIN32) #include #include #endif @@ -968,86 +968,55 @@ std::filesystem::path common_get_path_from_env(const std::string & name) { #endif } +#if !defined(_WIN32) +static std::filesystem::path get_home_directory() { + std::filesystem::path home = common_get_path_from_env("HOME"); + if (!home.empty()) { + return home; + } + const struct passwd * pw = getpwuid(getuid()); + if (!pw || !pw->pw_dir || !*pw->pw_dir) { + throw std::runtime_error("Failed to find $HOME directory"); + } + return pw->pw_dir; +} +#endif + std::filesystem::path fs_get_cache_directory() { std::filesystem::path cache_directory = common_get_path_from_env("LLAMA_CACHE"); if (!cache_directory.empty()) { return cache_directory; } - #if defined(_WIN32) cache_directory = common_get_path_from_env("LOCALAPPDATA"); if (cache_directory.empty()) { throw std::runtime_error("Failed to find %LOCALAPPDATA% directory"); } #elif defined(__APPLE__) - cache_directory = common_get_path_from_env("HOME"); - if (cache_directory.empty()) { - throw std::runtime_error("Failed to find $HOME directory"); - } - cache_directory /= "Library/Caches"; + cache_directory = get_home_directory() / "Library/Caches"; #else cache_directory = common_get_path_from_env("XDG_CACHE_HOME"); if (cache_directory.empty()) { - cache_directory = common_get_path_from_env("HOME"); - if (!cache_directory.empty()) { - cache_directory /= ".cache"; - } else { - /* no $HOME is defined, fallback to getpwuid */ - const struct passwd * pw = getpwuid(getuid()); - if (!pw || !pw->pw_dir || !*pw->pw_dir) { - throw std::runtime_error("Failed to find $HOME directory"); - } - cache_directory = pw->pw_dir; - cache_directory /= ".cache"; - } + cache_directory = get_home_directory() / ".cache"; } #endif return cache_directory / "llama.cpp"; } -std::string fs_get_config_directory() { - std::string config_directory = ""; - auto ensure_trailing_slash = [](std::string p) { - if (p.empty() || p.back() != DIRECTORY_SEPARATOR) { - p += DIRECTORY_SEPARATOR; - } - return p; - }; -#if defined(__linux__) || defined(__FreeBSD__) || defined(_AIX) || \ - defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) - const std::string xdg_config_home = common_get_env("XDG_CONFIG_HOME"); - const std::string home = common_get_env("HOME"); - if (!xdg_config_home.empty()) { - config_directory = xdg_config_home; - } else if (!home.empty()) { - config_directory = home + "/.config/"; - } else { -#if defined(__linux__) - /* no $HOME is defined, fallback to getpwuid */ - struct passwd *pw = getpwuid(getuid()); - if ((!pw) || (!pw->pw_dir)) { - throw std::runtime_error("Failed to find $HOME directory"); - } - - config_directory = std::string(pw->pw_dir) + std::string("/.config/"); -#else - throw std::runtime_error("Failed to find $HOME directory"); -#endif - } -#elif defined(_WIN32) - config_directory = common_get_env("APPDATA"); +std::filesystem::path fs_get_config_directory() { + std::filesystem::path config_directory; +#if defined(_WIN32) + config_directory = common_get_path_from_env("APPDATA"); if (config_directory.empty()) { throw std::runtime_error("Failed to find %APPDATA% directory"); } -#elif defined(__EMSCRIPTEN__) - // caller decides what to do when there is no config directory - throw std::runtime_error("not implemented on this platform"); #else -# error Unknown architecture + config_directory = common_get_path_from_env("XDG_CONFIG_HOME"); + if (config_directory.empty()) { + config_directory = get_home_directory() / ".config"; + } #endif - config_directory = ensure_trailing_slash(config_directory); - config_directory += "llama.cpp"; - return ensure_trailing_slash(config_directory); + return config_directory / "llama.cpp"; } std::filesystem::path fs_get_cache_file(const std::string & filename) { diff --git a/common/common.h b/common/common.h index 01726247b..e95eb2fd0 100644 --- a/common/common.h +++ b/common/common.h @@ -916,7 +916,7 @@ bool fs_is_directory(const std::string & path); std::filesystem::path fs_get_cache_directory(); std::filesystem::path fs_get_cache_file(const std::string & filename); -std::string fs_get_config_directory(); +std::filesystem::path fs_get_config_directory(); struct common_file_info { std::string path; diff --git a/common/preset.cpp b/common/preset.cpp index 4c61e93ee..7ca24ec38 100644 --- a/common/preset.cpp +++ b/common/preset.cpp @@ -167,16 +167,16 @@ void common_preset::apply_to_params(common_params & params, const std::set> parse_ini_from_file(const std::string & path) { +static std::map> parse_ini_from_file(const std::filesystem::path & path) { std::map> parsed; if (!std::filesystem::exists(path)) { - throw std::runtime_error("preset file does not exist: " + path); + throw std::runtime_error("preset file does not exist: " + fs_path_to_utf8(path)); } std::ifstream file(path); if (!file.good()) { - throw std::runtime_error("failed to open server preset file: " + path); + throw std::runtime_error("failed to open server preset file: " + fs_path_to_utf8(path)); } std::string contents((std::istreambuf_iterator(file)), std::istreambuf_iterator()); @@ -225,7 +225,7 @@ static std::map> parse_ini_from_ common_peg_parse_context ctx(contents); const auto result = parser.parse(ctx); if (!result.success()) { - throw std::runtime_error("failed to parse server config file: " + path); + throw std::runtime_error("failed to parse server config file: " + fs_path_to_utf8(path)); } std::string current_section = COMMON_PRESET_DEFAULT_NAME; @@ -282,7 +282,7 @@ common_preset_context::common_preset_context(llama_example ex) key_to_opt = get_map_key_opt(ctx_params); } -common_presets common_preset_context::load_from_ini(const std::string & path, common_preset & global) const { +common_presets common_preset_context::load_from_ini(const std::filesystem::path & path, common_preset & global) const { common_presets out; auto ini_data = parse_ini_from_file(path); @@ -323,7 +323,7 @@ common_presets common_preset_context::load_from_ini(const std::string & path, co } LOG_DBG("accepted option: %s = %s\n", key.c_str(), preset.options[opt].c_str()); } else if (ignore_unknown_keys) { - LOG_WRN("ignoring option '%s' from %s: not supported by this program\n", key.c_str(), path.c_str()); + LOG_WRN("ignoring option '%s' from %s: not supported by this program\n", key.c_str(), fs_path_to_utf8(path).c_str()); } else { throw std::runtime_error(string_format( "option '%s' not recognized in preset '%s'", diff --git a/common/preset.h b/common/preset.h index d8fc3915b..e03d186f1 100644 --- a/common/preset.h +++ b/common/preset.h @@ -67,7 +67,7 @@ struct common_preset_context { common_preset_context(llama_example ex); // load presets from INI file - common_presets load_from_ini(const std::string & path, common_preset & global) const; + common_presets load_from_ini(const std::filesystem::path & path, common_preset & global) const; // generate presets from cached models common_presets load_from_cache() const; diff --git a/tools/rpc/rpc-server.cpp b/tools/rpc/rpc-server.cpp index 5c30e6fe4..c0c55df59 100644 --- a/tools/rpc/rpc-server.cpp +++ b/tools/rpc/rpc-server.cpp @@ -18,12 +18,13 @@ #include #include -#if !defined(_WIN32) && !defined(__APPLE__) +#if !defined(_WIN32) #include #include #endif +// NOTE: this is copied from common.cpp to avoid linking with libcommon static std::string fs_path_to_utf8(const std::filesystem::path & path) { const auto value = path.u8string(); return std::string(value.begin(), value.end()); @@ -44,39 +45,38 @@ static std::filesystem::path common_get_path_from_env(const std::string & name) #endif } +// NOTE: this is copied from common.cpp to avoid linking with libcommon +#if !defined(_WIN32) +static std::filesystem::path get_home_directory() { + std::filesystem::path home = common_get_path_from_env("HOME"); + if (!home.empty()) { + return home; + } + const struct passwd * pw = getpwuid(getuid()); + if (!pw || !pw->pw_dir || !*pw->pw_dir) { + throw std::runtime_error("Failed to find $HOME directory"); + } + return pw->pw_dir; +} +#endif + // NOTE: this is copied from common.cpp to avoid linking with libcommon static std::filesystem::path fs_get_cache_directory() { std::filesystem::path cache_directory = common_get_path_from_env("LLAMA_CACHE"); if (!cache_directory.empty()) { return cache_directory; } - #if defined(_WIN32) cache_directory = common_get_path_from_env("LOCALAPPDATA"); if (cache_directory.empty()) { throw std::runtime_error("Failed to find %LOCALAPPDATA% directory"); } #elif defined(__APPLE__) - cache_directory = common_get_path_from_env("HOME"); - if (cache_directory.empty()) { - throw std::runtime_error("Failed to find $HOME directory"); - } - cache_directory /= "Library/Caches"; + cache_directory = get_home_directory() / "Library/Caches"; #else cache_directory = common_get_path_from_env("XDG_CACHE_HOME"); if (cache_directory.empty()) { - cache_directory = common_get_path_from_env("HOME"); - if (!cache_directory.empty()) { - cache_directory /= ".cache"; - } else { - /* no $HOME is defined, fallback to getpwuid */ - const struct passwd * pw = getpwuid(getuid()); - if (!pw || !pw->pw_dir || !*pw->pw_dir) { - throw std::runtime_error("Failed to find $HOME directory"); - } - cache_directory = pw->pw_dir; - cache_directory /= ".cache"; - } + cache_directory = get_home_directory() / ".cache"; } #endif return cache_directory / "llama.cpp";