From e9a691101985ec1c43be2064e07670f2ad43f716 Mon Sep 17 00:00:00 2001 From: Hacksign Date: Thu, 29 May 2025 18:48:04 +0800 Subject: [PATCH] NEW: Add cross compile support on X86_64 Linux with MinGW toolchain. --- cmake/compiler-env.cmake | 6 +++- cmake/toolchain/mingw-w64.cmake | 38 ++++++++++++++++++++ src/analyzer/CMakeLists.txt | 4 +++ src/backends/icicle-emulator/CMakeLists.txt | 4 +++ src/backends/unicorn-emulator/CMakeLists.txt | 4 +++ src/common/CMakeLists.txt | 17 ++++++--- src/common/network/address.hpp | 6 ++++ src/common/utils/win.hpp | 4 +++ src/fuzzer/CMakeLists.txt | 4 +++ src/samples/test-sample/CMakeLists.txt | 5 +++ src/samples/test-sample/test.cpp | 15 ++++++++ src/tools/dump-apiset/CMakeLists.txt | 4 +++ src/windows-emulator-test/CMakeLists.txt | 8 +++++ 13 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 cmake/toolchain/mingw-w64.cmake diff --git a/cmake/compiler-env.cmake b/cmake/compiler-env.cmake index 4d897103..fe06487d 100644 --- a/cmake/compiler-env.cmake +++ b/cmake/compiler-env.cmake @@ -25,7 +25,11 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) ########################################## -if(NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten") +# MinGW LTO will cause errors in compile stage +# We just disable it +if(CMAKE_C_COMPILER MATCHES "/.*/x86_64-w64-mingw32-gcc$") + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF) +elseif(NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten") set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) endif() diff --git a/cmake/toolchain/mingw-w64.cmake b/cmake/toolchain/mingw-w64.cmake new file mode 100644 index 00000000..58f07813 --- /dev/null +++ b/cmake/toolchain/mingw-w64.cmake @@ -0,0 +1,38 @@ +# cross compile +set(CMAKE_SYSTEM_NAME Windows) + +set(MINGW_C_COMPILER_NAME "x86_64-w64-mingw32-gcc") +set(MINGW_CXX_COMPILER_NAME "x86_64-w64-mingw32-g++") +set(MINGW_WINDRES_COMPILER_NAME "x86_64-w64-mingw32-windres") + +find_file(MINGW_C_COMPILER ${MINGW_C_COMPILER_NAME}) +find_file(MINGW_CXX_COMPILER ${MINGW_CXX_COMPILER_NAME}) +find_file(MINGW_WINDRES_COMPILER ${MINGW_WINDRES_COMPILER_NAME}) + +if (${MINGW_C_COMPILER} STREQUAL "MINGW_C_COMPILER-NOTFOUND") + message(FATAL_ERROR "mingw-w64 compiler not found: ${MINGW_C_COMPILER_NAME}") +endif() +if (${MINGW_CXX_COMPILER} STREQUAL "MINGW_CXX_COMPILER-NOTFOUND") + message(FATAL_ERROR "mingw-w64 compiler not found: ${MINGW_CXX_COMPILER_NAME}") +endif() +if (${MINGW_WINDRES_COMPILER} STREQUAL "MINGW_WINDRES_COMPILER-NOTFOUND") + message(FATAL_ERROR "mingw-w64 compiler not found: ${MINGW_WINDRES_COMPILER_NAME}") +endif() + +# this macro is needed when compile `libwindows-emulator.a` +add_compile_definitions(NTDDI_VERSION=NTDDI_WIN10_MN) + +# set the compiler +set(CMAKE_C_COMPILER ${MINGW_C_COMPILER}) +set(CMAKE_CXX_COMPILER ${MINGW_CXX_COMPILER}) +set(CMAKE_RC_COMPILER ${MINGW_WINDRES_COMPILER}) + +# set the compiler search path +set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) + +# adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/src/analyzer/CMakeLists.txt b/src/analyzer/CMakeLists.txt index 036e614e..c04e57ae 100644 --- a/src/analyzer/CMakeLists.txt +++ b/src/analyzer/CMakeLists.txt @@ -14,6 +14,10 @@ if(NOT MOMO_ENABLE_CLANG_TIDY) target_precompile_headers(analyzer PRIVATE std_include.hpp) endif() +if(CMAKE_C_COMPILER MATCHES "/.*/x86_64-w64-mingw32-gcc$") + target_link_options(analyzer PRIVATE -static-libstdc++ -static -lwinpthread) +endif() + target_link_libraries(analyzer PRIVATE reflect debugger diff --git a/src/backends/icicle-emulator/CMakeLists.txt b/src/backends/icicle-emulator/CMakeLists.txt index da62e3af..138cecab 100644 --- a/src/backends/icicle-emulator/CMakeLists.txt +++ b/src/backends/icicle-emulator/CMakeLists.txt @@ -16,5 +16,9 @@ endif() target_include_directories(icicle-emulator INTERFACE "${CMAKE_CURRENT_LIST_DIR}") +if(CMAKE_C_COMPILER MATCHES "/.*/x86_64-w64-mingw32-gcc$") + target_link_options(icicle-emulator PRIVATE -static-libstdc++ -static -lwinpthread) +endif() + target_link_libraries(icicle-emulator PUBLIC emulator) target_link_libraries(icicle-emulator PRIVATE emulator-common icicle-bridge) diff --git a/src/backends/unicorn-emulator/CMakeLists.txt b/src/backends/unicorn-emulator/CMakeLists.txt index 8b44e286..e3ae081a 100644 --- a/src/backends/unicorn-emulator/CMakeLists.txt +++ b/src/backends/unicorn-emulator/CMakeLists.txt @@ -14,6 +14,10 @@ endif() target_include_directories(unicorn-emulator INTERFACE "${CMAKE_CURRENT_LIST_DIR}") +if(CMAKE_C_COMPILER MATCHES "/.*/x86_64-w64-mingw32-gcc$") + target_link_options(unicorn-emulator PRIVATE -static-libstdc++ -static -lwinpthread) +endif() + target_link_libraries(unicorn-emulator PUBLIC emulator) target_link_libraries(unicorn-emulator PRIVATE unicorn emulator-common) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index dfc64b78..6a3a0fee 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -11,7 +11,16 @@ target_include_directories(emulator-common INTERFACE "${CMAKE_CURRENT_LIST_DIR}" set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) -target_link_libraries(emulator-common PUBLIC - Threads::Threads - zlibstatic -) + +if(CMAKE_C_COMPILER MATCHES "/.*/x86_64-w64-mingw32-gcc$") + target_link_libraries(emulator-common PUBLIC + Threads::Threads + zlibstatic + ws2_32 + ) +else() + target_link_libraries(emulator-common PUBLIC + Threads::Threads + zlibstatic + ) +endif() diff --git a/src/common/network/address.hpp b/src/common/network/address.hpp index 363b91bc..6546bee5 100644 --- a/src/common/network/address.hpp +++ b/src/common/network/address.hpp @@ -2,8 +2,14 @@ #if _WIN32 #include "../utils/win.hpp" +#ifdef __MINGW64__ +#include +#include +#include +#else #include #include +#endif #else #include diff --git a/src/common/utils/win.hpp b/src/common/utils/win.hpp index 89dd09c9..0b917460 100644 --- a/src/common/utils/win.hpp +++ b/src/common/utils/win.hpp @@ -18,6 +18,10 @@ #define WIN32_LEAN_AND_MEAN #endif +#ifdef __MINGW64__ +#include +#else #include +#endif #endif diff --git a/src/fuzzer/CMakeLists.txt b/src/fuzzer/CMakeLists.txt index 2ffc31a0..d5158de6 100644 --- a/src/fuzzer/CMakeLists.txt +++ b/src/fuzzer/CMakeLists.txt @@ -14,6 +14,10 @@ if(NOT MOMO_ENABLE_CLANG_TIDY) target_precompile_headers(fuzzer PRIVATE std_include.hpp) endif() +if(CMAKE_C_COMPILER MATCHES "/.*/x86_64-w64-mingw32-gcc$") + target_link_options(fuzzer PRIVATE -static-libstdc++ -static -lwinpthread) +endif() + target_link_libraries(fuzzer PRIVATE fuzzing-engine windows-emulator diff --git a/src/samples/test-sample/CMakeLists.txt b/src/samples/test-sample/CMakeLists.txt index 6a131eff..f5772be4 100644 --- a/src/samples/test-sample/CMakeLists.txt +++ b/src/samples/test-sample/CMakeLists.txt @@ -8,4 +8,9 @@ list(SORT SRC_FILES) add_executable(test-sample ${SRC_FILES}) +if(CMAKE_C_COMPILER MATCHES "/.*/x86_64-w64-mingw32-gcc$") + target_link_options(test-sample PRIVATE -static-libstdc++ -static -lwinpthread) + target_link_libraries(test-sample PRIVATE ws2_32) +endif() + momo_assign_source_group(${SRC_FILES}) diff --git a/src/samples/test-sample/test.cpp b/src/samples/test-sample/test.cpp index 67634c58..a3ec47ca 100644 --- a/src/samples/test-sample/test.cpp +++ b/src/samples/test-sample/test.cpp @@ -12,9 +12,16 @@ #define NOMINMAX #define WIN32_LEAN_AND_MEAN #include + +#ifdef __MINGW64__ +#include +#include +#include +#else #include #include #include +#endif #pragma comment(lib, "ws2_32.lib") @@ -594,6 +601,7 @@ namespace } } +#ifndef __MINGW64__ bool test_access_violation_exception() { __try @@ -641,6 +649,7 @@ namespace { return test_access_violation_exception() && test_illegal_instruction_exception(); } +#endif bool trap_flag_cleared = false; constexpr DWORD TRAP_FLAG_MASK = 0x100; @@ -665,7 +674,11 @@ namespace __writeeflags(__readeflags() | TRAP_FLAG_MASK); +#ifdef __MINGW64__ + asm("nop"); +#else __nop(); +#endif RemoveVectoredExceptionHandler(veh_handle); @@ -736,7 +749,9 @@ int main(const int argc, const char* argv[]) RUN_TEST(test_threads, "Threads") RUN_TEST(test_env, "Environment") RUN_TEST(test_exceptions, "Exceptions") +#ifndef __MINGW64__ RUN_TEST(test_native_exceptions, "Native Exceptions") +#endif if (!getenv("EMULATOR_ICICLE")) { RUN_TEST(test_interrupts, "Interrupts") diff --git a/src/tools/dump-apiset/CMakeLists.txt b/src/tools/dump-apiset/CMakeLists.txt index 9a3bf180..e676abec 100644 --- a/src/tools/dump-apiset/CMakeLists.txt +++ b/src/tools/dump-apiset/CMakeLists.txt @@ -10,6 +10,10 @@ add_executable(dump-apiset ${SRC_FILES}) momo_assign_source_group(${SRC_FILES}) +if(CMAKE_C_COMPILER MATCHES "/.*/x86_64-w64-mingw32-gcc$") + target_link_options(dump-apiset PRIVATE -static-libstdc++ -static -lwinpthread) +endif() + target_link_libraries(dump-apiset PRIVATE emulator-common ) diff --git a/src/windows-emulator-test/CMakeLists.txt b/src/windows-emulator-test/CMakeLists.txt index 8bea4b26..7c30f4d4 100644 --- a/src/windows-emulator-test/CMakeLists.txt +++ b/src/windows-emulator-test/CMakeLists.txt @@ -10,6 +10,14 @@ add_executable(windows-emulator-test ${SRC_FILES}) momo_assign_source_group(${SRC_FILES}) +if(CMAKE_C_COMPILER MATCHES "/.*/x86_64-w64-mingw32-gcc$") + target_link_options(windows-emulator-test PRIVATE -static-libstdc++ -static -lwinpthread) +endif() + +if(CMAKE_C_COMPILER MATCHES "/.*/x86_64-w64-mingw32-gcc$") + target_link_options(windows-emulator-test PRIVATE -static-libstdc++ -static -lwinpthread) +endif() + target_link_libraries(windows-emulator-test PRIVATE gtest gtest_main