Commit 00af63567 for llama.cpp
commit 00af63567a3ac073919be039db8492f229de5ffc
Author: Adrien Gallouët <angt@huggingface.co>
Date: Tue Sep 29 17:22:49 2026 +0200
common : use fs::path for config dir (#29649)
Signed-off-by: Adrien Gallouët <angt@huggingface.co>
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<std::string> paths;
+ std::vector<std::filesystem::path> 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<std::string> found;
+ std::vector<std::filesystem::path> 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 <unistd.h>
#endif
-#if !defined(_WIN32) && !defined(__APPLE__)
+#if !defined(_WIN32)
#include <sys/types.h>
#include <pwd.h>
#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<std::
}
}
-static std::map<std::string, std::map<std::string, std::string>> parse_ini_from_file(const std::string & path) {
+static std::map<std::string, std::map<std::string, std::string>> parse_ini_from_file(const std::filesystem::path & path) {
std::map<std::string, std::map<std::string, std::string>> 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<char>(file)), std::istreambuf_iterator<char>());
@@ -225,7 +225,7 @@ static std::map<std::string, std::map<std::string, std::string>> 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 <thread>
#include <vector>
-#if !defined(_WIN32) && !defined(__APPLE__)
+#if !defined(_WIN32)
#include <sys/types.h>
#include <pwd.h>
#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";