}
{
- fs::path argv0 =
+ const auto exe_path = util::get_executable_path();
+ fs::path ccache_exe_dir;
+ if (!exe_path.empty()) {
+ ccache_exe_dir = exe_path.parent_path();
+ } else {
+ fs::path argv0 =
#ifdef _WIN32
- util::add_exe_suffix(argv[0]);
+ util::add_exe_suffix(argv[0]);
#else
- argv[0];
+ argv[0];
#endif
- const auto ccache_exe_dir =
- fs::canonical(argv0).value_or(argv0).parent_path();
+ ccache_exe_dir = fs::canonical(argv0).value_or(argv0).parent_path();
+ }
+
Context ctx(ccache_exe_dir);
ctx.initialize(std::move(argv_parts.compiler_and_args),
argv_parts.config_settings);
-// Copyright (C) 2023-2024 Joel Rosdahl and other contributors
+// Copyright (C) 2023-2026 Joel Rosdahl and other contributors
//
// See doc/authors.adoc for a complete list of contributors.
//
#include "process.hpp"
+#include <ccache/util/filesystem.hpp>
#include <ccache/util/wincompat.hpp>
-#include <cstring>
-
-#ifdef HAVE_UNISTD_H
+#ifdef _WIN32
+# include <windows.h>
+#else
# include <unistd.h>
+# ifdef __APPLE__
+# include <mach-o/dyld.h>
+# endif
#endif
+#include <climits>
+#include <cstring>
+#include <vector>
+
+namespace fs = util::filesystem;
+
namespace {
// Process umask, read and written by get_umask and set_umask.
namespace util {
+fs::path
+get_executable_path()
+{
+#ifdef _WIN32
+ std::vector<wchar_t> buf(MAX_PATH);
+ while (true) {
+ DWORD len =
+ GetModuleFileNameW(nullptr, buf.data(), static_cast<DWORD>(buf.size()));
+ if (len == 0) {
+ return {};
+ }
+ if (len < static_cast<DWORD>(buf.size())) {
+ return fs::path(std::wstring(buf.data(), len));
+ }
+ buf.resize(buf.size() * 2);
+ }
+#elif defined(__APPLE__)
+ uint32_t size = PATH_MAX;
+ std::vector<char> buf(size);
+ if (_NSGetExecutablePath(buf.data(), &size) != 0) {
+ buf.resize(size);
+ if (_NSGetExecutablePath(buf.data(), &size) != 0) {
+ return {};
+ }
+ }
+ return fs::path(buf.data());
+#else
+ char buf[PATH_MAX];
+ ssize_t len = readlink("/proc/self/exe", buf, PATH_MAX - 1);
+ if (len < 0) {
+ return {};
+ }
+ buf[len] = '\0';
+ return fs::path(buf);
+#endif
+}
+
const char*
get_hostname()
{
#include <sys/stat.h>
+#include <filesystem>
+
namespace util {
+// Return the absolute path to the current executable using OS-specific methods.
+// Returns an empty path on failure.
+std::filesystem::path get_executable_path();
+
// Return a static string with the current hostname.
const char* get_hostname();