diff --git a/common/common.cpp b/common/common.cpp index cc423d3439..2429ea052e 100644 --- a/common/common.cpp +++ b/common/common.cpp @@ -2,6 +2,9 @@ #include "gguf.h" #include "common.h" + +#define COMMON_EXPORT +#include "fs-impl.h" #include "log.h" #include "llama.h" #include "sampling.h" @@ -738,153 +741,11 @@ bool fs_validate_filename(const std::string & filename, bool allow_subdirs) { #include - -#ifdef _WIN32 -static std::wstring utf8_to_wstring(const std::string & str) { - if (str.empty()) { - return std::wstring(); - } - - int size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), NULL, 0); - - if (size <= 0) { - return std::wstring(); - } - - std::wstring wstr(size, 0); - MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), &wstr[0], size); - - return wstr; -} -#endif - -// returns true if successful, false otherwise -bool fs_create_directory_with_parents(const std::string & path) { -#ifdef _WIN32 - std::wstring wpath = utf8_to_wstring(path); - - // if the path already exists, check whether it's a directory - const DWORD attributes = GetFileAttributesW(wpath.c_str()); - if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) { - return true; - } - - size_t pos_slash = 0; - - // process path from front to back, procedurally creating directories - while ((pos_slash = path.find('\\', pos_slash)) != std::string::npos) { - const std::wstring subpath = wpath.substr(0, pos_slash); - - pos_slash += 1; - - // skip the drive letter, in some systems it can return an access denied error - if (subpath.length() == 2 && subpath[1] == ':') { - continue; - } - - const bool success = CreateDirectoryW(subpath.c_str(), NULL); - - if (!success) { - const DWORD error = GetLastError(); - - // if the path already exists, ensure that it's a directory - if (error == ERROR_ALREADY_EXISTS) { - const DWORD attributes = GetFileAttributesW(subpath.c_str()); - if (attributes == INVALID_FILE_ATTRIBUTES || !(attributes & FILE_ATTRIBUTE_DIRECTORY)) { - return false; - } - } else { - return false; - } - } - } - - return true; -#else - // if the path already exists, check whether it's a directory - struct stat info; - if (stat(path.c_str(), &info) == 0) { - return S_ISDIR(info.st_mode); - } - - size_t pos_slash = 1; // skip leading slashes for directory creation - - // process path from front to back, procedurally creating directories - while ((pos_slash = path.find('/', pos_slash)) != std::string::npos) { - const std::string subpath = path.substr(0, pos_slash); - struct stat info; - - // if the path already exists, ensure that it's a directory - if (stat(subpath.c_str(), &info) == 0) { - if (!S_ISDIR(info.st_mode)) { - return false; - } - } else { - // create parent directories - const int ret = mkdir(subpath.c_str(), 0755); - if (ret != 0) { - return false; - } - } - - pos_slash += 1; - } - - return true; -#endif // _WIN32 -} - bool fs_is_directory(const std::string & path) { std::filesystem::path dir(path); return std::filesystem::exists(dir) && std::filesystem::is_directory(dir); } -std::string fs_get_cache_directory() { - std::string cache_directory = ""; - auto ensure_trailing_slash = [](std::string p) { - // Make sure to add trailing slash - if (p.back() != DIRECTORY_SEPARATOR) { - p += DIRECTORY_SEPARATOR; - } - return p; - }; - if (getenv("LLAMA_CACHE")) { - cache_directory = std::getenv("LLAMA_CACHE"); - } else { -#if defined(__linux__) || defined(__FreeBSD__) || defined(_AIX) || \ - defined(__OpenBSD__) || defined(__NetBSD__) - if (std::getenv("XDG_CACHE_HOME")) { - cache_directory = std::getenv("XDG_CACHE_HOME"); - } else if (std::getenv("HOME")) { - cache_directory = std::getenv("HOME") + std::string("/.cache/"); - } 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"); - } - - cache_directory = std::string(pw->pw_dir) + std::string("/.cache/"); -#else /* defined(__linux__) */ - throw std::runtime_error("Failed to find $HOME directory"); -#endif /* defined(__linux__) */ - } -#elif defined(__APPLE__) - cache_directory = std::getenv("HOME") + std::string("/Library/Caches/"); -#elif defined(_WIN32) - cache_directory = std::getenv("LOCALAPPDATA"); -#elif defined(__EMSCRIPTEN__) - GGML_ABORT("not implemented on this platform"); -#else -# error Unknown architecture -#endif - cache_directory = ensure_trailing_slash(cache_directory); - cache_directory += "llama.cpp"; - } - return ensure_trailing_slash(cache_directory); -} - std::string fs_get_cache_file(const std::string & filename) { GGML_ASSERT(filename.find(DIRECTORY_SEPARATOR) == std::string::npos); std::string cache_directory = fs_get_cache_directory(); diff --git a/common/fs-impl.h b/common/fs-impl.h new file mode 100644 index 0000000000..4b578337bf --- /dev/null +++ b/common/fs-impl.h @@ -0,0 +1,173 @@ +#pragma once + +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#else +#include +#include +#endif + +#if defined(__linux__) +#include +#include +#endif + +#ifndef DIRECTORY_SEPARATOR +#ifdef _WIN32 +#define DIRECTORY_SEPARATOR '\\' +#else +#define DIRECTORY_SEPARATOR '/' +#endif +#endif + +#ifdef _WIN32 +inline std::wstring utf8_to_wstring(const std::string & str) { + if (str.empty()) { + return std::wstring(); + } + + int size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), NULL, 0); + + if (size <= 0) { + return std::wstring(); + } + + std::wstring wstr(size, 0); + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), &wstr[0], size); + + return wstr; +} +#endif + +#ifndef COMMON_EXPORT +#define COMMON_EXPORT inline +#endif + +COMMON_EXPORT bool fs_create_directory_with_parents(const std::string & path) { +#ifdef _WIN32 + std::wstring wpath = utf8_to_wstring(path); + + // if the path already exists, check whether it's a directory + const DWORD attributes = GetFileAttributesW(wpath.c_str()); + if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) { + return true; + } + + size_t pos_slash = 0; + + // process path from front to back, procedurally creating directories + while ((pos_slash = path.find('\\', pos_slash)) != std::string::npos) { + const std::wstring subpath = wpath.substr(0, pos_slash); + + pos_slash += 1; + + // skip the drive letter, in some systems it can return an access denied error + if (subpath.length() == 2 && subpath[1] == ':') { + continue; + } + + const bool success = CreateDirectoryW(subpath.c_str(), NULL); + + if (!success) { + const DWORD error = GetLastError(); + + // if the path already exists, ensure that it's a directory + if (error == ERROR_ALREADY_EXISTS) { + const DWORD attributes = GetFileAttributesW(subpath.c_str()); + if (attributes == INVALID_FILE_ATTRIBUTES || !(attributes & FILE_ATTRIBUTE_DIRECTORY)) { + return false; + } + } else { + return false; + } + } + } + + return true; +#else + // if the path already exists, check whether it's a directory + struct stat info; + if (stat(path.c_str(), &info) == 0) { + return S_ISDIR(info.st_mode); + } + + size_t pos_slash = 1; // skip leading slashes for directory creation + + // process path from front to back, procedurally creating directories + while ((pos_slash = path.find('/', pos_slash)) != std::string::npos) { + const std::string subpath = path.substr(0, pos_slash); + struct stat info; + + // if the path already exists, ensure that it's a directory + if (stat(subpath.c_str(), &info) == 0) { + if (!S_ISDIR(info.st_mode)) { + return false; + } + } else { + // create parent directories + const int ret = mkdir(subpath.c_str(), 0755); + if (ret != 0) { + return false; + } + } + + pos_slash += 1; + } + + return true; +#endif // _WIN32 +} + +COMMON_EXPORT std::string fs_get_cache_directory() { + std::string cache_directory = ""; + auto ensure_trailing_slash = [](std::string p) { + // Make sure to add trailing slash + if (p.back() != DIRECTORY_SEPARATOR) { + p += DIRECTORY_SEPARATOR; + } + return p; + }; + if (getenv("LLAMA_CACHE")) { + cache_directory = std::getenv("LLAMA_CACHE"); + } else { +#if defined(__linux__) || defined(__FreeBSD__) || defined(_AIX) || \ + defined(__OpenBSD__) || defined(__NetBSD__) + if (std::getenv("XDG_CACHE_HOME")) { + cache_directory = std::getenv("XDG_CACHE_HOME"); + } else if (std::getenv("HOME")) { + cache_directory = std::getenv("HOME") + std::string("/.cache/"); + } 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"); + } + + cache_directory = std::string(pw->pw_dir) + std::string("/.cache/"); +#else /* defined(__linux__) */ + throw std::runtime_error("Failed to find $HOME directory"); +#endif /* defined(__linux__) */ + } +#elif defined(__APPLE__) + cache_directory = std::getenv("HOME") + std::string("/Library/Caches/"); +#elif defined(_WIN32) + cache_directory = std::getenv("LOCALAPPDATA"); +#elif defined(__EMSCRIPTEN__) + throw std::runtime_error("fs_get_cache_directory not implemented on this platform"); +#else +# error Unknown architecture +#endif + cache_directory = ensure_trailing_slash(cache_directory); + cache_directory += "llama.cpp"; + } + return ensure_trailing_slash(cache_directory); +} + +#undef COMMON_EXPORT diff --git a/tools/rpc/CMakeLists.txt b/tools/rpc/CMakeLists.txt index 20f114ad9b..4401edc5f7 100644 --- a/tools/rpc/CMakeLists.txt +++ b/tools/rpc/CMakeLists.txt @@ -1,5 +1,6 @@ set(TARGET rpc-server) add_executable(${TARGET} rpc-server.cpp) +target_include_directories(${TARGET} PRIVATE ${CMAKE_SOURCE_DIR}/common) target_link_libraries(${TARGET} PRIVATE ggml) target_compile_features(${TARGET} PRIVATE cxx_std_17) diff --git a/tools/rpc/rpc-server.cpp b/tools/rpc/rpc-server.cpp index 03ab78e5f0..dfeef981eb 100644 --- a/tools/rpc/rpc-server.cpp +++ b/tools/rpc/rpc-server.cpp @@ -1,174 +1,14 @@ #include "ggml-rpc.h" -#ifdef _WIN32 -# define NOMINMAX -# define DIRECTORY_SEPARATOR '\\' -# include -# include -# include -#else -# define DIRECTORY_SEPARATOR '/' -# include -# include -#endif +#include "fs-impl.h" + #include #include -#include -#include #include #include #include #include #include -#if defined(__linux__) -#include -#include -#endif - -// NOTE: this is copied from common.cpp to avoid linking with libcommon -#ifdef _WIN32 -static std::wstring utf8_to_wstring(const std::string & str) { - if (str.empty()) { - return std::wstring(); - } - - int size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), NULL, 0); - - if (size <= 0) { - return std::wstring(); - } - - std::wstring wstr(size, 0); - MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), &wstr[0], size); - - return wstr; -} -#endif - -// NOTE: this is copied from common.cpp to avoid linking with libcommon -// returns true if successful, false otherwise -static bool fs_create_directory_with_parents(const std::string & path) { -#ifdef _WIN32 - std::wstring wpath = utf8_to_wstring(path); - - // if the path already exists, check whether it's a directory - const DWORD attributes = GetFileAttributesW(wpath.c_str()); - if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) { - return true; - } - - size_t pos_slash = 0; - - // process path from front to back, procedurally creating directories - while ((pos_slash = path.find('\\', pos_slash)) != std::string::npos) { - const std::wstring subpath = wpath.substr(0, pos_slash); - - pos_slash += 1; - - // skip the drive letter, in some systems it can return an access denied error - if (subpath.length() == 2 && subpath[1] == ':') { - continue; - } - - const bool success = CreateDirectoryW(subpath.c_str(), NULL); - - if (!success) { - const DWORD error = GetLastError(); - - // if the path already exists, ensure that it's a directory - if (error == ERROR_ALREADY_EXISTS) { - const DWORD attributes = GetFileAttributesW(subpath.c_str()); - if (attributes == INVALID_FILE_ATTRIBUTES || !(attributes & FILE_ATTRIBUTE_DIRECTORY)) { - return false; - } - } else { - return false; - } - } - } - - return true; -#else - // if the path already exists, check whether it's a directory - struct stat info; - if (stat(path.c_str(), &info) == 0) { - return S_ISDIR(info.st_mode); - } - - size_t pos_slash = 1; // skip leading slashes for directory creation - - // process path from front to back, procedurally creating directories - while ((pos_slash = path.find('/', pos_slash)) != std::string::npos) { - const std::string subpath = path.substr(0, pos_slash); - struct stat info; - - // if the path already exists, ensure that it's a directory - if (stat(subpath.c_str(), &info) == 0) { - if (!S_ISDIR(info.st_mode)) { - return false; - } - } else { - // create parent directories - const int ret = mkdir(subpath.c_str(), 0755); - if (ret != 0) { - return false; - } - } - - pos_slash += 1; - } - - return true; -#endif // _WIN32 -} - -// NOTE: this is copied from common.cpp to avoid linking with libcommon -static std::string fs_get_cache_directory() { - std::string cache_directory = ""; - auto ensure_trailing_slash = [](std::string p) { - // Make sure to add trailing slash - if (p.back() != DIRECTORY_SEPARATOR) { - p += DIRECTORY_SEPARATOR; - } - return p; - }; - if (getenv("LLAMA_CACHE")) { - cache_directory = std::getenv("LLAMA_CACHE"); - } else { -#if defined(__linux__) || defined(__FreeBSD__) || defined(_AIX) || \ - defined(__OpenBSD__) || defined(__NetBSD__) - if (std::getenv("XDG_CACHE_HOME")) { - cache_directory = std::getenv("XDG_CACHE_HOME"); - } else if (std::getenv("HOME")) { - cache_directory = std::getenv("HOME") + std::string("/.cache/"); - } 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"); - } - - cache_directory = std::string(pw->pw_dir) + std::string("/.cache/"); -#else /* defined(__linux__) */ - throw std::runtime_error("Failed to find $HOME directory"); -#endif /* defined(__linux__) */ - } -#elif defined(__APPLE__) - cache_directory = std::getenv("HOME") + std::string("/Library/Caches/"); -#elif defined(_WIN32) - cache_directory = std::getenv("LOCALAPPDATA"); -#elif defined(__EMSCRIPTEN__) - GGML_ABORT("not implemented on this platform"); -#else -# error Unknown architecture -#endif - cache_directory = ensure_trailing_slash(cache_directory); - cache_directory += "llama.cpp"; - } - return ensure_trailing_slash(cache_directory); -} - struct rpc_server_params { std::string host = "127.0.0.1"; int port = 50052;