macOS port: build, rendering, daemon, and mining fixes

Build & setup:
- Fix setup.sh and build.sh for macOS (bundle daemon, xmrig, sapling params, asmap.dat into .app)
- Fix CMakeLists.txt libsodium linking for macOS
- Fix incbin.h to use __DATA,__const section on macOS
- Remove vendored libsodium-1.0.18 source tree (use fetch script instead)
- Remove prebuilt-binaries/xmrig (replaced by xmrig-hac)
- Add .DS_Store to .gitignore

Rendering & UI:
- Use GLSL #version 150 and OpenGL 3.2 Core Profile on macOS
- Force dpiScale=1.0 on macOS to fix Retina double-scaling
- Set default window/UI opacity to 100% on Mac/Linux
- Add scroll fade shader guard for macOS GL compatibility
- Add ImGui error recovery around render loop and mining tab

Daemon & bootstrap:
- Fix getDragonXDataDir() to return ~/Library/Application Support/Hush/DRAGONX/ on macOS
- Fix isPortInUse() with connect() fallback (no /proc/net/tcp on macOS)
- Increase daemon watchdog timeout from 3s to 15s
- Add daemon status indicator (colored dot + label) in wizard bootstrap phases

Mining tab:
- Fix EmbeddedDaemon::getMemoryUsageMB() crash on macOS (was using Linux /proc)
- Fix XmrigManager::getMemoryUsageMB() to use ps on macOS instead of /proc
- Restructure RenderMiningTab with wrapper pattern for exception safety
- Fix default pool URL to include port (pool.dragonx.is:3433)
This commit is contained in:
2026-03-19 14:26:04 -05:00
parent d79d013060
commit 2b3277529e
572 changed files with 284 additions and 146732 deletions

View File

@@ -1958,13 +1958,29 @@ bool App::startEmbeddedDaemon()
if (!exe_dir.empty()) {
std::error_code ec;
fs::create_directories(daemon_dir, ec);
// On macOS .app bundles, params are in Contents/Resources/
// while the executable is in Contents/MacOS/
std::vector<std::string> searchDirs = { exe_dir };
#ifdef __APPLE__
{
fs::path resourcesDir = fs::path(exe_dir).parent_path() / "Resources";
if (fs::is_directory(resourcesDir))
searchDirs.insert(searchDirs.begin(), resourcesDir.string());
}
#endif
for (const char* name : paramFiles) {
fs::path src = fs::path(exe_dir) / name;
fs::path dst = fs::path(daemon_dir) / name;
if (fs::exists(src) && !fs::exists(dst)) {
DEBUG_LOGF("Copying bundled %s from exe dir to %s\n", name, daemon_dir.c_str());
fs::copy_file(src, dst, ec);
if (!ec) copied = true;
if (fs::exists(dst)) continue;
for (const auto& dir : searchDirs) {
fs::path src = fs::path(dir) / name;
if (fs::exists(src)) {
DEBUG_LOGF("Copying bundled %s from %s to %s\n", name, dir.c_str(), daemon_dir.c_str());
fs::copy_file(src, dst, ec);
if (!ec) copied = true;
break;
}
}
}
}
@@ -1979,6 +1995,40 @@ bool App::startEmbeddedDaemon()
}
}
// Ensure asmap.dat and daemon binaries are copied from the bundle
// to the daemon directory even if sapling params already existed.
{
namespace fs = std::filesystem;
std::string exe_dir = util::Platform::getExecutableDirectory();
std::string daemon_dir = resources::getDaemonDirectory();
if (!exe_dir.empty()) {
std::error_code ec;
fs::create_directories(daemon_dir, ec);
std::vector<std::string> searchDirs = { exe_dir };
#ifdef __APPLE__
{
fs::path resourcesDir = fs::path(exe_dir).parent_path() / "Resources";
if (fs::is_directory(resourcesDir))
searchDirs.insert(searchDirs.begin(), resourcesDir.string());
}
#endif
const char* extraFiles[] = { "asmap.dat", "dragonxd", "dragonx-cli", "dragonx-tx" };
for (const char* name : extraFiles) {
fs::path dst = fs::path(daemon_dir) / name;
if (fs::exists(dst)) continue;
for (const auto& dir : searchDirs) {
fs::path src = fs::path(dir) / name;
if (fs::exists(src)) {
DEBUG_LOGF("Copying bundled %s from %s to %s\n", name, dir.c_str(), daemon_dir.c_str());
fs::copy_file(src, dst, ec);
break;
}
}
}
}
}
// Create daemon manager if needed
if (!embedded_daemon_) {
embedded_daemon_ = std::make_unique<daemon::EmbeddedDaemon>();