psemek/libs/util/source/executable_path.cpp

47 lines
1.2 KiB
C++

#include <psemek/util/executable_path.hpp>
#include <psemek/util/to_string.hpp>
#include <psemek/util/exception.hpp>
#ifdef _WIN32
#include <libloaderapi.h>
#include <errhandlingapi.h>
#include <winerror.h>
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
namespace psemek::util
{
std::filesystem::path executable_path()
{
#if defined _WIN32
std::wstring result(256, '\0');
while (true)
{
GetModuleFileNameW(NULL, result.data(), result.size());
auto error = GetLastError();
if (error == ERROR_SUCCESS)
break;
else if (error == ERROR_INSUFFICIENT_BUFFER)
result.resize(result.size() * 2);
else
throw exception(util::to_string("failed to retrieve executable path: ", std::hex, error));
}
return std::filesystem::path(result);
#elif defined __linux__
return std::filesystem::canonical("/proc/self/exe");
#elif defined __APPLE__
uint32_t path_length = 0;
_NSGetExecutablePath(nullptr, &path_length);
std::string path(path_length, '\0');
_NSGetExecutablePath(path.data(), &path_length);
return std::filesystem::path(std::move(path));
#else
throw exception("executable_path() is not implemented for this platform");
#endif
}
}