From 9f799fe12bdf1bb9f039dac174780fd923b8bce4 Mon Sep 17 00:00:00 2001 From: theofficialgman <28281419+theofficialgman@users.noreply.github.com> Date: Tue, 25 Aug 2026 21:36:24 -0400 Subject: [PATCH] final linux support necessary changes to build a working application --- runtime/cmake/PublicProducts.cmake | 10 +++++++ runtime/include/runtime_config.h | 29 ++++++++++++++++++- runtime/src/memory.cpp | 2 ++ .../Translator.Core/IO/AssemblyBlobWriter.cs | 9 +++++- 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/runtime/cmake/PublicProducts.cmake b/runtime/cmake/PublicProducts.cmake index 5391420..d1fff5e 100644 --- a/runtime/cmake/PublicProducts.cmake +++ b/runtime/cmake/PublicProducts.cmake @@ -213,6 +213,16 @@ function(mkw_configure_product target) dbghelp user32 winmm ws2_32 iphlpapi secur32 crypt32 windowsapp setupapi winusb) set_target_properties(${target} PROPERTIES WIN32_EXECUTABLE TRUE) + else() + # mkw_runtime_common is an OBJECT library: WiiCompiled/RetroRewind only pull in its .o + # files via $, which does not propagate mkw_runtime_common's own + # target_link_libraries (object libraries don't carry usage requirements to a consumer + # that isn't itself linked against as a target). fiber_manager.cpp's co_* calls live in + # those objects, so the actual executable link needs mkw::libco directly, same as it + # needs it independently of that first `if(WIN32)` branch above. + target_link_libraries(${target} PRIVATE mkw::libco) + endif() + if(WIN32) foreach(runtime_dll libc++.dll libunwind.dll) execute_process( COMMAND "${CMAKE_CXX_COMPILER}" "--print-file-name=${runtime_dll}" diff --git a/runtime/include/runtime_config.h b/runtime/include/runtime_config.h index b86b723..f8a3bae 100644 --- a/runtime/include/runtime_config.h +++ b/runtime/include/runtime_config.h @@ -23,6 +23,9 @@ #endif #include #include +#else +#include +#include #endif struct RuntimeUserConfig { @@ -168,7 +171,22 @@ inline std::optional ExecutableDirectory() { buffer.resize(buffer.size() * 2); } #else - return std::nullopt; + // /proc/self/exe is a Linux-specific magic symlink to the running executable; readlink() + // does not NUL-terminate and silently truncates if the buffer is too small, so this grows + // the buffer until the result no longer fills it completely, the same doubling strategy as + // the Windows branch above uses for GetModuleFileNameW. + std::string buffer(256, '\0'); + for (;;) { + const ssize_t length = readlink("/proc/self/exe", buffer.data(), buffer.size()); + if (length < 0) { + return std::nullopt; + } + if (static_cast(length) < buffer.size()) { + buffer.resize(static_cast(length)); + return std::filesystem::path(buffer).parent_path(); + } + buffer.resize(buffer.size() * 2); + } #endif } @@ -209,6 +227,15 @@ inline std::filesystem::path ApplicationDataDirectory() { CoTaskMemFree(rawPath); return directory; } +#else + // XDG Base Directory spec equivalent of FOLDERID_LocalAppData: $XDG_DATA_HOME if set and + // non-empty, otherwise its default of $HOME/.local/share. + if (const char* xdgDataHome = std::getenv("XDG_DATA_HOME"); xdgDataHome && *xdgDataHome) { + return std::filesystem::path(xdgDataHome) / kApplicationDirectoryName; + } + if (const char* home = std::getenv("HOME"); home && *home) { + return std::filesystem::path(home) / ".local" / "share" / kApplicationDirectoryName; + } #endif return std::filesystem::current_path() / kApplicationDirectoryName; } diff --git a/runtime/src/memory.cpp b/runtime/src/memory.cpp index 63f5825..88a484e 100644 --- a/runtime/src/memory.cpp +++ b/runtime/src/memory.cpp @@ -20,11 +20,13 @@ #include #include +#if defined(_WIN32) #ifndef NOMINMAX #define NOMINMAX #endif #include #include +#endif MemoryInline::PageEntry MemoryInline::g_pageTable[MemoryInline::kPageCount]{}; uintptr_t MemoryInline::g_fullPageBias[MemoryInline::kPageCount]{}; diff --git a/translator/src/Translator.Core/IO/AssemblyBlobWriter.cs b/translator/src/Translator.Core/IO/AssemblyBlobWriter.cs index 2b515dc..b871f83 100644 --- a/translator/src/Translator.Core/IO/AssemblyBlobWriter.cs +++ b/translator/src/Translator.Core/IO/AssemblyBlobWriter.cs @@ -22,7 +22,14 @@ internal static class AssemblyBlobWriter var expectedFiles = new HashSet(StringComparer.OrdinalIgnoreCase); var assembly = new StringBuilder(); foreach (var header in headerLines) assembly.AppendLine(header); - assembly.AppendLine(".section .rdata,\"dr\""); + // PE/COFF (Windows) and ELF (Linux) spell a read-only data section differently in GNU-as + // syntax - COFF section flags ("dr" = data, read-only) versus an ELF section needing an + // allocatable-only flag plus an explicit @progbits type. The build always targets + // whichever platform the translator itself runs on (there is no cross-compilation + // support), so that's what this picks the section syntax from. + assembly.AppendLine(OperatingSystem.IsWindows() + ? ".section .rdata,\"dr\"" + : ".section .rodata,\"a\",@progbits"); assembly.AppendLine(); foreach (var blob in blobs)