ObsidianDragon - DragonX ImGui Wallet
Full-node GUI wallet for DragonX cryptocurrency. Built with Dear ImGui, SDL3, and OpenGL3/DX11. Features: - Send/receive shielded and transparent transactions - Autoshield with merged transaction display - Built-in CPU mining (xmrig) - Peer management and network monitoring - Wallet encryption with PIN lock - QR code generation for receive addresses - Transaction history with pagination - Console for direct RPC commands - Cross-platform (Linux, Windows)
This commit is contained in:
564
src/resources/embedded_resources.cpp
Normal file
564
src/resources/embedded_resources.cpp
Normal file
@@ -0,0 +1,564 @@
|
||||
#include "embedded_resources.h"
|
||||
#include "../util/platform.h"
|
||||
#include "../util/logger.h"
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
// Include generated resource data if available
|
||||
#if __has_include("embedded_data.h")
|
||||
#include "embedded_data.h"
|
||||
#define HAS_EMBEDDED_RESOURCES 1
|
||||
#else
|
||||
#define HAS_EMBEDDED_RESOURCES 0
|
||||
#endif
|
||||
|
||||
namespace dragonx {
|
||||
namespace resources {
|
||||
|
||||
#if HAS_EMBEDDED_RESOURCES
|
||||
// Resource table - populated by embedded_data.h (INCBIN symbols: g_NAME_data / g_NAME_size)
|
||||
static const EmbeddedResource s_resources[] = {
|
||||
{ g_sapling_spend_params_data, g_sapling_spend_params_size, RESOURCE_SAPLING_SPEND },
|
||||
{ g_sapling_output_params_data, g_sapling_output_params_size, RESOURCE_SAPLING_OUTPUT },
|
||||
{ g_asmap_dat_data, g_asmap_dat_size, RESOURCE_ASMAP },
|
||||
#ifdef HAS_EMBEDDED_DAEMON
|
||||
{ g_hushd_exe_data, g_hushd_exe_size, RESOURCE_HUSHD },
|
||||
{ g_hush_cli_exe_data, g_hush_cli_exe_size, RESOURCE_HUSH_CLI },
|
||||
{ g_hush_tx_exe_data, g_hush_tx_exe_size, RESOURCE_HUSH_TX },
|
||||
{ g_dragonxd_bat_data, g_dragonxd_bat_size, RESOURCE_DRAGONXD_BAT },
|
||||
{ g_dragonx_cli_bat_data, g_dragonx_cli_bat_size, RESOURCE_DRAGONX_CLI_BAT },
|
||||
#endif
|
||||
#ifdef HAS_EMBEDDED_XMRIG
|
||||
{ g_xmrig_exe_data, g_xmrig_exe_size, RESOURCE_XMRIG },
|
||||
#endif
|
||||
#ifdef HAS_EMBEDDED_GRADIENT
|
||||
{ g_dark_gradient_png_data, g_dark_gradient_png_size, RESOURCE_DARK_GRADIENT },
|
||||
#endif
|
||||
#ifdef HAS_EMBEDDED_LOGO
|
||||
{ g_logo_ObsidianDragon_dark_png_data, g_logo_ObsidianDragon_dark_png_size, RESOURCE_LOGO },
|
||||
#endif
|
||||
{ nullptr, 0, nullptr } // Sentinel
|
||||
};
|
||||
// Embedded themes table is generated by s_embedded_themes[] in embedded_data.h
|
||||
#else
|
||||
static const EmbeddedResource s_resources[] = {
|
||||
{ nullptr, 0, nullptr } // No embedded resources
|
||||
};
|
||||
// No embedded themes on non-Windows builds (themes live on disk)
|
||||
struct EmbeddedThemeEntry { const uint8_t* data; unsigned int size; const char* filename; };
|
||||
static const EmbeddedThemeEntry s_embedded_themes[] = {
|
||||
{ nullptr, 0, nullptr }
|
||||
};
|
||||
// No embedded images on non-Windows builds (images live on disk)
|
||||
struct EmbeddedImageEntry { const uint8_t* data; unsigned int size; const char* filename; };
|
||||
static const EmbeddedImageEntry s_embedded_images[] = {
|
||||
{ nullptr, 0, nullptr }
|
||||
};
|
||||
#endif
|
||||
|
||||
bool hasEmbeddedResources()
|
||||
{
|
||||
#if HAS_EMBEDDED_RESOURCES
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
const EmbeddedResource* getEmbeddedResource(const std::string& name)
|
||||
{
|
||||
// Search static resource table (params, daemon binaries, etc.)
|
||||
for (const auto* res = s_resources; res->data != nullptr; ++res) {
|
||||
if (name == res->filename) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
// Search dynamically generated image table (backgrounds + logos)
|
||||
// These are generated by build.sh from res/img/ contents.
|
||||
for (const auto* img = s_embedded_images; img->data != nullptr; ++img) {
|
||||
if (name == img->filename) {
|
||||
static thread_local EmbeddedResource imageResult;
|
||||
imageResult = { img->data, img->size, img->filename };
|
||||
return &imageResult;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const EmbeddedTheme* getEmbeddedThemes()
|
||||
{
|
||||
// Map from generated table to public struct
|
||||
// s_embedded_themes is generated by build.sh (or empty fallback)
|
||||
static std::vector<EmbeddedTheme> themes;
|
||||
static bool init = false;
|
||||
if (!init) {
|
||||
for (const auto* t = s_embedded_themes; t->data != nullptr; ++t) {
|
||||
themes.push_back({ t->data, t->size, t->filename });
|
||||
}
|
||||
themes.push_back({ nullptr, 0, nullptr }); // Sentinel
|
||||
init = true;
|
||||
}
|
||||
return themes.data();
|
||||
}
|
||||
|
||||
int extractBundledThemes(const std::string& destDir)
|
||||
{
|
||||
namespace fs = std::filesystem;
|
||||
int count = 0;
|
||||
|
||||
const auto* themes = getEmbeddedThemes();
|
||||
if (!themes || !themes->data) return 0;
|
||||
|
||||
// Ensure destination exists
|
||||
std::error_code ec;
|
||||
fs::create_directories(destDir, ec);
|
||||
if (ec) {
|
||||
DEBUG_LOGF("[ERROR] EmbeddedResources: Failed to create theme dir: %s\n", destDir.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (const auto* t = themes; t->data != nullptr; ++t) {
|
||||
fs::path dest = fs::path(destDir) / t->filename;
|
||||
// Always overwrite — bundled themes should match the binary version
|
||||
std::ofstream f(dest, std::ios::binary);
|
||||
if (f.is_open()) {
|
||||
f.write(reinterpret_cast<const char*>(t->data), t->size);
|
||||
f.close();
|
||||
DEBUG_LOGF("[INFO] EmbeddedResources: Extracted theme: %s (%zu bytes)\n",
|
||||
t->filename, t->size);
|
||||
count++;
|
||||
} else {
|
||||
DEBUG_LOGF("[ERROR] EmbeddedResources: Failed to write theme: %s\n", dest.string().c_str());
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
std::string getParamsDirectory()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
char appdata[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, 0, appdata))) {
|
||||
return std::string(appdata) + "\\ZcashParams";
|
||||
}
|
||||
return "";
|
||||
#elif defined(__APPLE__)
|
||||
const char* home = getenv("HOME");
|
||||
if (!home) {
|
||||
struct passwd* pw = getpwuid(getuid());
|
||||
home = pw ? pw->pw_dir : "/tmp";
|
||||
}
|
||||
return std::string(home) + "/Library/Application Support/ZcashParams";
|
||||
#else
|
||||
const char* home = getenv("HOME");
|
||||
if (!home) {
|
||||
struct passwd* pw = getpwuid(getuid());
|
||||
home = pw ? pw->pw_dir : "/tmp";
|
||||
}
|
||||
return std::string(home) + "/.zcash-params";
|
||||
#endif
|
||||
}
|
||||
|
||||
bool needsParamsExtraction()
|
||||
{
|
||||
if (!hasEmbeddedResources()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check daemon directory (hush3/) — the only extraction target
|
||||
std::string daemonDir = getDaemonDirectory();
|
||||
std::string spendPath = daemonDir +
|
||||
#ifdef _WIN32
|
||||
"\\sapling-spend.params";
|
||||
#else
|
||||
"/sapling-spend.params";
|
||||
#endif
|
||||
std::string outputPath = daemonDir +
|
||||
#ifdef _WIN32
|
||||
"\\sapling-output.params";
|
||||
#else
|
||||
"/sapling-output.params";
|
||||
#endif
|
||||
|
||||
// Check if both params exist in daemon directory
|
||||
return !std::filesystem::exists(spendPath) || !std::filesystem::exists(outputPath);
|
||||
}
|
||||
|
||||
static bool extractResource(const EmbeddedResource* res, const std::string& destPath)
|
||||
{
|
||||
if (!res || !res->data || res->size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create parent directories
|
||||
std::filesystem::path path(destPath);
|
||||
if (path.has_parent_path()) {
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(path.parent_path(), ec);
|
||||
if (ec) {
|
||||
DEBUG_LOGF("[ERROR] Failed to create directory %s: %s\n",
|
||||
path.parent_path().string().c_str(), ec.message().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Write file
|
||||
std::ofstream file(destPath, std::ios::binary);
|
||||
if (!file) {
|
||||
DEBUG_LOGF("[ERROR] Failed to open %s for writing\n", destPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
file.write(reinterpret_cast<const char*>(res->data), res->size);
|
||||
if (!file) {
|
||||
DEBUG_LOGF("[ERROR] Failed to write %zu bytes to %s\n", res->size, destPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_LOGF("[INFO] Extracted %s (%zu bytes)\n", destPath.c_str(), res->size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool extractEmbeddedResources()
|
||||
{
|
||||
if (!hasEmbeddedResources()) {
|
||||
DEBUG_LOGF("[ERROR] No embedded resources available\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
|
||||
#ifdef _WIN32
|
||||
const char pathSep = '\\';
|
||||
#else
|
||||
const char pathSep = '/';
|
||||
#endif
|
||||
|
||||
// All files go to <ObsidianDragonDir>/hush3/
|
||||
std::string daemonDir = getDaemonDirectory();
|
||||
|
||||
// Extract Sapling params to daemon directory alongside hushd
|
||||
const EmbeddedResource* spendRes = getEmbeddedResource(RESOURCE_SAPLING_SPEND);
|
||||
if (spendRes) {
|
||||
std::string dest = daemonDir + pathSep + RESOURCE_SAPLING_SPEND;
|
||||
if (!std::filesystem::exists(dest)) {
|
||||
DEBUG_LOGF("[INFO] Extracting sapling-spend.params (%zu MB)...\n", spendRes->size / (1024*1024));
|
||||
if (!extractResource(spendRes, dest)) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const EmbeddedResource* outputRes = getEmbeddedResource(RESOURCE_SAPLING_OUTPUT);
|
||||
if (outputRes) {
|
||||
std::string dest = daemonDir + pathSep + RESOURCE_SAPLING_OUTPUT;
|
||||
if (!std::filesystem::exists(dest)) {
|
||||
DEBUG_LOGF("[INFO] Extracting sapling-output.params (%zu MB)...\n", outputRes->size / (1024*1024));
|
||||
if (!extractResource(outputRes, dest)) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract asmap.dat to daemon directory
|
||||
const EmbeddedResource* asmapRes = getEmbeddedResource(RESOURCE_ASMAP);
|
||||
if (asmapRes) {
|
||||
std::string dest = daemonDir + pathSep + RESOURCE_ASMAP;
|
||||
if (!std::filesystem::exists(dest)) {
|
||||
DEBUG_LOGF("[INFO] Extracting asmap.dat...\n");
|
||||
if (!extractResource(asmapRes, dest)) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract daemon binaries — NOT the data directory.
|
||||
// Running hushd.exe from inside the data directory (where it writes blockchain
|
||||
// data, debug.log, lock files, etc.) causes crashes on some Windows machines.
|
||||
#ifdef HAS_EMBEDDED_DAEMON
|
||||
DEBUG_LOGF("[INFO] Daemon extraction directory: %s\n", daemonDir.c_str());
|
||||
|
||||
const EmbeddedResource* hushdRes = getEmbeddedResource(RESOURCE_HUSHD);
|
||||
if (hushdRes) {
|
||||
std::string dest = daemonDir + pathSep + RESOURCE_HUSHD;
|
||||
if (!std::filesystem::exists(dest)) {
|
||||
DEBUG_LOGF("[INFO] Extracting hushd.exe (%zu MB)...\n", hushdRes->size / (1024*1024));
|
||||
if (!extractResource(hushdRes, dest)) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const EmbeddedResource* cliRes = getEmbeddedResource(RESOURCE_HUSH_CLI);
|
||||
if (cliRes) {
|
||||
std::string dest = daemonDir + pathSep + RESOURCE_HUSH_CLI;
|
||||
if (!std::filesystem::exists(dest)) {
|
||||
DEBUG_LOGF("[INFO] Extracting hush-cli.exe (%zu MB)...\n", cliRes->size / (1024*1024));
|
||||
if (!extractResource(cliRes, dest)) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const EmbeddedResource* batRes = getEmbeddedResource(RESOURCE_DRAGONXD_BAT);
|
||||
if (batRes) {
|
||||
std::string dest = daemonDir + pathSep + RESOURCE_DRAGONXD_BAT;
|
||||
if (!std::filesystem::exists(dest)) {
|
||||
DEBUG_LOGF("[INFO] Extracting dragonxd.bat...\n");
|
||||
if (!extractResource(batRes, dest)) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const EmbeddedResource* txRes = getEmbeddedResource(RESOURCE_HUSH_TX);
|
||||
if (txRes) {
|
||||
std::string dest = daemonDir + pathSep + RESOURCE_HUSH_TX;
|
||||
if (!std::filesystem::exists(dest)) {
|
||||
DEBUG_LOGF("[INFO] Extracting hush-tx.exe (%zu MB)...\n", txRes->size / (1024*1024));
|
||||
if (!extractResource(txRes, dest)) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const EmbeddedResource* cliBatRes = getEmbeddedResource(RESOURCE_DRAGONX_CLI_BAT);
|
||||
if (cliBatRes) {
|
||||
std::string dest = daemonDir + pathSep + RESOURCE_DRAGONX_CLI_BAT;
|
||||
if (!std::filesystem::exists(dest)) {
|
||||
DEBUG_LOGF("[INFO] Extracting dragonx-cli.bat...\n");
|
||||
if (!extractResource(cliBatRes, dest)) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_EMBEDDED_XMRIG
|
||||
const EmbeddedResource* xmrigRes = getEmbeddedResource(RESOURCE_XMRIG);
|
||||
if (xmrigRes) {
|
||||
std::string dest = daemonDir + pathSep + RESOURCE_XMRIG;
|
||||
if (!std::filesystem::exists(dest)) {
|
||||
DEBUG_LOGF("[INFO] Extracting xmrig.exe (%zu MB)...\n", xmrigRes->size / (1024*1024));
|
||||
if (!extractResource(xmrigRes, dest)) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
std::string getDaemonDirectory()
|
||||
{
|
||||
// Daemon binaries live in %APPDATA%/ObsidianDragon/hush3/ (Windows) or
|
||||
// ~/.config/ObsidianDragon/hush3/ (Linux) — separate from the blockchain
|
||||
// data directory to avoid lock-file conflicts.
|
||||
std::string obsidianDir = util::Platform::getObsidianDragonDir();
|
||||
#ifdef _WIN32
|
||||
return obsidianDir + "\\hush3";
|
||||
#else
|
||||
return obsidianDir + "/hush3";
|
||||
#endif
|
||||
}
|
||||
|
||||
bool needsDaemonExtraction()
|
||||
{
|
||||
#ifdef HAS_EMBEDDED_DAEMON
|
||||
std::string daemonDir = getDaemonDirectory();
|
||||
#ifdef _WIN32
|
||||
std::string hushdPath = daemonDir + "\\hushd.exe";
|
||||
#else
|
||||
std::string hushdPath = daemonDir + "/hushd";
|
||||
#endif
|
||||
return !std::filesystem::exists(hushdPath);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool hasDaemonAvailable()
|
||||
{
|
||||
#ifdef HAS_EMBEDDED_DAEMON
|
||||
return true;
|
||||
#else
|
||||
// Check if daemon exists alongside the executable
|
||||
#ifdef _WIN32
|
||||
return std::filesystem::exists("hushd.exe") || std::filesystem::exists("dragonxd.bat");
|
||||
#else
|
||||
return std::filesystem::exists("hushd") || std::filesystem::exists("dragonxd");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string getDaemonPath()
|
||||
{
|
||||
std::string daemonDir = getDaemonDirectory();
|
||||
#ifdef _WIN32
|
||||
const char pathSep = '\\';
|
||||
const char* daemonName = "hushd.exe";
|
||||
#else
|
||||
const char pathSep = '/';
|
||||
const char* daemonName = "hushd";
|
||||
#endif
|
||||
|
||||
DEBUG_LOGF("[DEBUG] getDaemonPath: daemonDir=%s\n", daemonDir.c_str());
|
||||
|
||||
#ifdef HAS_EMBEDDED_DAEMON
|
||||
// Extract if needed
|
||||
std::string embeddedPath = daemonDir + pathSep + daemonName;
|
||||
DEBUG_LOGF("[DEBUG] getDaemonPath: checking embedded path %s\n", embeddedPath.c_str());
|
||||
if (!std::filesystem::exists(embeddedPath)) {
|
||||
DEBUG_LOGF("[INFO] getDaemonPath: daemon not found, extracting embedded resources...\n");
|
||||
extractEmbeddedResources();
|
||||
}
|
||||
if (std::filesystem::exists(embeddedPath)) {
|
||||
DEBUG_LOGF("[INFO] getDaemonPath: found at %s\n", embeddedPath.c_str());
|
||||
return embeddedPath;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check local directory
|
||||
if (std::filesystem::exists(daemonName)) {
|
||||
DEBUG_LOGF("[INFO] getDaemonPath: found in local directory\n");
|
||||
return daemonName;
|
||||
}
|
||||
|
||||
DEBUG_LOGF("[ERROR] getDaemonPath: daemon binary not found anywhere\n");
|
||||
return "";
|
||||
}
|
||||
|
||||
bool needsXmrigExtraction()
|
||||
{
|
||||
#ifdef HAS_EMBEDDED_XMRIG
|
||||
std::string daemonDir = getDaemonDirectory();
|
||||
#ifdef _WIN32
|
||||
std::string xmrigPath = daemonDir + "\\xmrig.exe";
|
||||
#else
|
||||
std::string xmrigPath = daemonDir + "/xmrig";
|
||||
#endif
|
||||
return !std::filesystem::exists(xmrigPath);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool hasXmrigAvailable()
|
||||
{
|
||||
#ifdef HAS_EMBEDDED_XMRIG
|
||||
return true;
|
||||
#else
|
||||
// Check if xmrig exists alongside the executable
|
||||
#ifdef _WIN32
|
||||
return std::filesystem::exists("xmrig.exe");
|
||||
#else
|
||||
return std::filesystem::exists("xmrig");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool forceExtractXmrig()
|
||||
{
|
||||
#ifdef HAS_EMBEDDED_XMRIG
|
||||
std::string daemonDir = getDaemonDirectory();
|
||||
#ifdef _WIN32
|
||||
std::string dest = daemonDir + "\\" + RESOURCE_XMRIG;
|
||||
#else
|
||||
std::string dest = daemonDir + "/" + RESOURCE_XMRIG;
|
||||
#endif
|
||||
const EmbeddedResource* xmrigRes = getEmbeddedResource(RESOURCE_XMRIG);
|
||||
if (!xmrigRes) {
|
||||
DEBUG_LOGF("[ERROR] forceExtractXmrig: no embedded xmrig resource\n");
|
||||
return false;
|
||||
}
|
||||
DEBUG_LOGF("[INFO] forceExtractXmrig: extracting xmrig (%zu MB) to %s\n",
|
||||
xmrigRes->size / (1024*1024), dest.c_str());
|
||||
if (!extractResource(xmrigRes, dest)) {
|
||||
DEBUG_LOGF("[ERROR] forceExtractXmrig: extraction failed\n");
|
||||
return false;
|
||||
}
|
||||
#ifndef _WIN32
|
||||
// Set executable permission on Linux
|
||||
chmod(dest.c_str(), 0755);
|
||||
#endif
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string getXmrigPath()
|
||||
{
|
||||
std::string daemonDir = getDaemonDirectory();
|
||||
#ifdef _WIN32
|
||||
const char pathSep = '\\';
|
||||
const char* xmrigName = "xmrig.exe";
|
||||
#else
|
||||
const char pathSep = '/';
|
||||
const char* xmrigName = "xmrig";
|
||||
#endif
|
||||
|
||||
DEBUG_LOGF("[DEBUG] getXmrigPath: daemonDir=%s\n", daemonDir.c_str());
|
||||
|
||||
#ifdef HAS_EMBEDDED_XMRIG
|
||||
// Extract if needed — force re-extract in case Defender deleted it
|
||||
std::string embeddedPath = daemonDir + pathSep + xmrigName;
|
||||
DEBUG_LOGF("[DEBUG] getXmrigPath: checking embedded path %s\n", embeddedPath.c_str());
|
||||
if (!std::filesystem::exists(embeddedPath)) {
|
||||
DEBUG_LOGF("[DEBUG] getXmrigPath: not found, force re-extracting xmrig\n");
|
||||
forceExtractXmrig();
|
||||
}
|
||||
if (std::filesystem::exists(embeddedPath)) {
|
||||
DEBUG_LOGF("[INFO] getXmrigPath: found at %s\n", embeddedPath.c_str());
|
||||
return embeddedPath;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check local directory
|
||||
if (std::filesystem::exists(xmrigName)) {
|
||||
DEBUG_LOGF("[INFO] getXmrigPath: found in local directory\n");
|
||||
return xmrigName;
|
||||
}
|
||||
|
||||
// Check development paths
|
||||
#ifdef _WIN32
|
||||
// Not applicable for cross-compiled Windows builds
|
||||
#else
|
||||
// Linux development build — resolve relative to executable directory
|
||||
// (build/bin/), not CWD which may differ at runtime
|
||||
std::string exeDir = util::Platform::getExecutableDirectory();
|
||||
std::vector<std::string> devPaths = {
|
||||
exeDir + "/../../external/xmrig-HAC/xmrig/build/xmrig", // from build/linux/bin/
|
||||
exeDir + "/../external/xmrig-HAC/xmrig/build/xmrig", // from build/linux/
|
||||
"../external/xmrig-HAC/xmrig/build/xmrig", // CWD = build/linux/
|
||||
"../../external/xmrig-HAC/xmrig/build/xmrig", // CWD = build/linux/bin/
|
||||
"external/xmrig-HAC/xmrig/build/xmrig", // CWD = project root
|
||||
};
|
||||
for (const auto& dp : devPaths) {
|
||||
if (std::filesystem::exists(dp)) {
|
||||
std::string resolved = std::filesystem::canonical(dp).string();
|
||||
DEBUG_LOGF("[INFO] getXmrigPath: found dev binary at %s\n", resolved.c_str());
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG_LOGF("[ERROR] getXmrigPath: xmrig binary not found anywhere\n");
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace resources
|
||||
} // namespace dragonx
|
||||
Reference in New Issue
Block a user