add linux support to runtime build

This commit is contained in:
theofficialgman
2026-08-25 19:50:37 -04:00
parent 6d836dab3e
commit f63d0c84b5
5 changed files with 83 additions and 26 deletions
+18 -5
View File
@@ -1,10 +1,13 @@
cmake_minimum_required(VERSION 3.16)
project(mkw_recompiled)
if(NOT WIN32 OR NOT MINGW OR NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
if((NOT (WIN32 AND MINGW)) AND (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux"))
message(FATAL_ERROR "WiiCompiled requires Windows (LLVM-MinGW) or native Linux")
endif()
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
NOT CMAKE_SIZEOF_VOID_P EQUAL 8 OR
NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^(AMD64|amd64|x86_64|X86_64)$")
message(FATAL_ERROR "WiiCompiled requires 64-bit LLVM-MinGW Clang on Windows")
message(FATAL_ERROR "WiiCompiled requires 64-bit Clang targeting x86_64")
endif()
if(NOT CMAKE_BUILD_TYPE STREQUAL "Release")
message(FATAL_ERROR "WiiCompiled only supports Release builds")
@@ -110,12 +113,22 @@ else()
message(FATAL_ERROR "Requested aurora-main but ${MKW_AURORA_DIR} is missing")
endif()
set(DAWN_ENABLE_D3D11 OFF CACHE BOOL "" FORCE)
set(DAWN_ENABLE_D3D12 ON CACHE BOOL "" FORCE)
if(WIN32)
set(DAWN_ENABLE_D3D12 ON CACHE BOOL "" FORCE)
set(TINT_BUILD_HLSL_WRITER ON CACHE BOOL "" FORCE)
set(DAWN_USE_WINDOWS_UI OFF CACHE BOOL "" FORCE)
else()
# Non-Windows (Linux): mirrors aurora-main's own
# _aurora_dawn_set_platform_backends() choice for this platform - Vulkan only, no
# D3D/HLSL. Kept in sync here because this project's own CMake FORCEs these cache
# variables before aurora-main's add_subdirectory() runs, which pre-empts aurora's
# auto-detection (CACHE ... INTERNAL "" without FORCE never overrides an existing value).
set(DAWN_ENABLE_D3D12 OFF CACHE BOOL "" FORCE)
set(TINT_BUILD_HLSL_WRITER OFF CACHE BOOL "" FORCE)
endif()
set(DAWN_ENABLE_VULKAN ON CACHE BOOL "" FORCE)
set(TINT_BUILD_HLSL_WRITER ON CACHE BOOL "" FORCE)
set(DAWN_BUILD_SAMPLES OFF CACHE BOOL "" FORCE)
set(DAWN_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(DAWN_USE_WINDOWS_UI OFF CACHE BOOL "" FORCE)
# Provide a tiny stub for DXProgrammableCapture when the SDK/PIX headers are
# missing (common on MinGW). Dawn only includes the header; no symbols are
+24 -20
View File
@@ -77,7 +77,9 @@ target_compile_definitions(mkw_runtime_common PRIVATE
target_link_libraries(mkw_runtime_common PRIVATE
aurora::gx aurora::pad aurora::si aurora::vi aurora::mtx)
target_link_libraries(mkw_runtime_common PRIVATE mkw::pugixml mkw::toml11 mkw::cryptopp)
target_link_libraries(mkw_runtime_common PRIVATE shell32 windowsapp)
if(WIN32)
target_link_libraries(mkw_runtime_common PRIVATE shell32 windowsapp)
endif()
if(MKW_CPPWINRT_INCLUDE_DIR)
if(NOT EXISTS "${MKW_CPPWINRT_INCLUDE_DIR}/winrt/base.h")
message(FATAL_ERROR
@@ -204,26 +206,28 @@ function(mkw_configure_product target)
$<TARGET_FILE:sqlite3> $<TARGET_FILE_DIR:${target}>)
endif()
target_link_libraries(${target} PRIVATE
dbghelp user32 winmm ws2_32 iphlpapi secur32 crypt32 windowsapp setupapi winusb)
if(WIN32)
target_link_libraries(${target} PRIVATE
dbghelp user32 winmm ws2_32 iphlpapi secur32 crypt32 windowsapp setupapi winusb)
set_target_properties(${target} PROPERTIES WIN32_EXECUTABLE TRUE)
foreach(runtime_dll libc++.dll libunwind.dll)
execute_process(
COMMAND "${CMAKE_CXX_COMPILER}" "--print-file-name=${runtime_dll}"
OUTPUT_VARIABLE runtime_dll_path
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT EXISTS "${runtime_dll_path}")
get_filename_component(mkw_compiler_bin "${CMAKE_CXX_COMPILER}" DIRECTORY)
set(runtime_dll_path "${mkw_compiler_bin}/${runtime_dll}")
endif()
if(NOT EXISTS "${runtime_dll_path}")
message(FATAL_ERROR "llvm-mingw runtime DLL not found: ${runtime_dll}")
endif()
add_custom_command(TARGET ${target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${runtime_dll_path}" $<TARGET_FILE_DIR:${target}>)
endforeach()
set_target_properties(${target} PROPERTIES WIN32_EXECUTABLE TRUE)
foreach(runtime_dll libc++.dll libunwind.dll)
execute_process(
COMMAND "${CMAKE_CXX_COMPILER}" "--print-file-name=${runtime_dll}"
OUTPUT_VARIABLE runtime_dll_path
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT EXISTS "${runtime_dll_path}")
get_filename_component(mkw_compiler_bin "${CMAKE_CXX_COMPILER}" DIRECTORY)
set(runtime_dll_path "${mkw_compiler_bin}/${runtime_dll}")
endif()
if(NOT EXISTS "${runtime_dll_path}")
message(FATAL_ERROR "llvm-mingw runtime DLL not found: ${runtime_dll}")
endif()
add_custom_command(TARGET ${target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${runtime_dll_path}" $<TARGET_FILE_DIR:${target}>)
endforeach()
endif()
set(MKW_WII_BOOTSTRAP_SOURCE_DIR "${MKW_RUNTIME_SOURCE_DIR}/assets/wii")
if(NOT EXISTS "${MKW_WII_BOOTSTRAP_SOURCE_DIR}/shared2/wc24")
+12 -1
View File
@@ -11,11 +11,22 @@ inline constexpr bool MkwStateFreeAbiEnabled(uint32_t) noexcept
return true;
}
#if defined(_WIN32)
#define MKW_PPC_FORCE_INLINE __forceinline
#define MKW_PPC_NO_INLINE __declspec(noinline)
#define MKW_PPC_INTERNAL_CALL __regcall
#else
// __forceinline/__declspec are MS-extension keywords Clang only recognizes when targeting
// Windows (MSVC or mingw); native Linux Clang needs the GNU-attribute spellings instead.
// __regcall has no portable non-Windows equivalent worth chasing here - the extra register
// args it saves matter for the hot PPC interpreter loop on Windows, but plain calls are fine
// elsewhere.
#define MKW_PPC_FORCE_INLINE __attribute__((always_inline)) inline
#define MKW_PPC_NO_INLINE __attribute__((noinline))
#define MKW_PPC_INTERNAL_CALL
#endif
#define MKW_PPC_ALWAYS_INLINE_BODY __attribute__((always_inline))
#define MKW_PPC_COLD __attribute__((cold))
#define MKW_PPC_INTERNAL_CALL __regcall
using MkwStateFreeResult2 = uint64_t __attribute__((ext_vector_type(2)));
+7
View File
@@ -18,8 +18,15 @@ extern "C" {
}
namespace MemoryInline {
#if defined(_WIN32)
#define MKW_MEMORY_FORCE_INLINE __forceinline
#define MKW_MEMORY_NO_INLINE __declspec(noinline)
#else
// See runtime/include/isa/ppc_isa_config.h for why non-Windows Clang needs the GNU-attribute
// spellings instead of the MS-extension keywords.
#define MKW_MEMORY_FORCE_INLINE __attribute__((always_inline)) inline
#define MKW_MEMORY_NO_INLINE __attribute__((noinline))
#endif
#define MKW_MEMORY_COLD __attribute__((cold))
inline constexpr uint32_t kPageShift = 20;
inline constexpr uint32_t kPageSize = 1u << kPageShift;
+22
View File
@@ -10,7 +10,11 @@
#include <cstdlib>
#include <cpuid.h>
#if defined(_WIN32)
#include <windows.h>
#else
#include <unistd.h>
#endif
namespace {
@@ -137,7 +141,12 @@ bool CollectMissingBaselineFeatures(TextBuffer& missing) {
// up yet, and fprintf(stderr, ...) faults there. Verified on this toolchain:
// WriteFile on the raw standard-error handle and MessageBoxA both work, printf
// does not. Anything added to this reporting path has to respect that.
//
// The POSIX path runs from an __attribute__((constructor)) instead, ahead of libc's own startup
// guarantees; ::write() on the raw fd is the same kind of allocation-free, libc-init-independent
// primitive as WriteFile is on Windows, so the same restriction is honored here.
void WriteStdErrEarly(const char* text) {
#if defined(_WIN32)
const HANDLE handle = ::GetStdHandle(STD_ERROR_HANDLE);
if (handle == nullptr || handle == INVALID_HANDLE_VALUE) {
return;
@@ -148,6 +157,13 @@ void WriteStdErrEarly(const char* text) {
}
DWORD written = 0;
::WriteFile(handle, text, static_cast<DWORD>(length), &written, nullptr);
#else
size_t length = 0;
while (text[length] != '\0') {
++length;
}
(void)::write(STDERR_FILENO, text, length);
#endif
}
[[noreturn]] void ReportUnsupportedCpu(const char* missing) {
@@ -168,12 +184,18 @@ void WriteStdErrEarly(const char* text) {
WriteStdErrEarly(message.data);
WriteStdErrEarly("\n");
#if defined(_WIN32)
::MessageBoxA(nullptr, message.data, "WiiCompiled - Unsupported Processor",
MB_OK | MB_ICONERROR | MB_SETFOREGROUND | MB_TASKMODAL);
// Leave through the OS rather than exit(): the C++ dynamic initializers
// have not run yet, so there is no constructed program state to unwind and
// the teardown path itself lives in AVX2 translation units.
::ExitProcess(1u);
#else
// Same reasoning as the Windows path above: no C++ dynamic initializer has run yet, so
// _exit() (skips atexit/global destructors, unlike exit()) is the correct way out.
::_exit(1);
#endif
}
} // namespace