Working cross-compilation (#494)

* feat: working cross-compilation

* feat: CI for Cross-compilation

* fix: non-reproducible builds are failing when cross-compiling

* fix: update ImGui

Fixed compilation under some MinGW versions.

* feat: Add .clangd configuration for C and C++ compilers

* fix: link correct d3dcompiler library conditionally

* fix: usage of deprecated `FetchContent` function in CMake

* chore: denote difference in CI artifacts
This commit is contained in:
PlayDay
2025-06-24 20:42:39 +02:00
committed by GitHub
parent 7c48d52b71
commit 0beb0d1c72
7 changed files with 308 additions and 54 deletions
+67
View File
@@ -0,0 +1,67 @@
# Use `zig cc` as the compiler for C files
If:
PathMatch: [
.*\.c,
.*\.h,
]
CompileFlags:
Compiler: zig cc
---
# Use `clang` as the compiler for C files
If:
PathMatch: [
.*\.c,
.*\.h,
]
CompileFlags:
Compiler: clang
---
# Use `zig c++` as the compiler for C++ files
If:
PathMatch: [
.*\.cpp,
.*\.c\+\+,
.*\.cc,
.*\.cp,
.*\.cppm,
.*\.cxx,
.*\.h\+\+,
.*\.hh,
.*\.hpp,
.*\.hxx,
.*\.inc,
.*\.inl,
.*\.ino,
.*\.ipp,
.*\.ixx,
.*\.re,
.*\.tcc,
.*\.tpp,
]
CompileFlags:
Compiler: zig c++
---
# Use `clang++` as the compiler for C++ files
If:
PathMatch: [
.*\.cpp,
.*\.c\+\+,
.*\.cc,
.*\.cp,
.*\.cppm,
.*\.cxx,
.*\.h\+\+,
.*\.hh,
.*\.hpp,
.*\.hxx,
.*\.inc,
.*\.inl,
.*\.ino,
.*\.ipp,
.*\.ixx,
.*\.re,
.*\.tcc,
.*\.tpp,
]
CompileFlags:
Compiler: clang++
+48 -3
View File
@@ -3,9 +3,9 @@ name: CI
on: [ push, pull_request ]
jobs:
ci:
native-compilation:
runs-on: [ self-hosted, Windows ]
name: CI
name: Native Compilation
steps:
- uses: actions/checkout@v4
@@ -37,7 +37,52 @@ jobs:
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: RelWithDebInfo-Clang
name: RelWithDebInfo-Native-Clang
path: |
build/YimMenuV2-dev-*.dll
build/YimMenuV2-dev-*.pdb
cross-compilation:
runs-on: ubuntu-latest
name: Cross-compilation
strategy:
matrix:
compiler: ["Zig", "Clang"]
steps:
- uses: actions/checkout@v4
- name: Setup Zig
if: matrix.compiler == 'Zig'
uses: mlugg/setup-zig@v2
- name: Setup MinGW
if: matrix.compiler == 'Clang'
run: |
sudo apt-get update
sudo apt-get install -y clang lld binutils-mingw-w64-x86-64 mingw-w64-x86-64-dev gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64
- name: Check CMake version
run: cmake --version
- name: Generate CMake project
run: cmake -DUSE_CROSSCOMPILER=${{ matrix.compiler }} -DCMAKE_BUILD_TYPE=RelWithDebInfo -S . -B build -G Ninja
- name: Build 64bit RelWithDebInfo DLL
run: cmake --build ./build --config RelWithDebInfo --target YimMenuV2 --
- name: Check if DLL got built
run: if [ ! -f build/libYimMenuV2.dll ]; then exit 1; fi
- name: Rename DLL to libYimMenuV2-dev-{GITHUB_SHA}.dll
run: |
mv libYimMenuV2.dll libYimMenuV2-dev-${{github.sha}}.dll
mv libYimMenuV2.pdb libYimMenuV2-dev-${{github.sha}}.pdb || true
working-directory: build/
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: RelWithDebInfo-Cross-${{ matrix.compiler }}
path: |
build/libYimMenuV2-dev-*.dll
build/libYimMenuV2-dev-*.pdb
+4 -1
View File
@@ -1,6 +1,9 @@
{
"cmake.configureSettings": {
"CMAKE_GENERATOR": "Ninja"
},
"files.associations": {
"*.c": "c",
".clangd": "yaml",
"string_view": "cpp",
"algorithm": "cpp",
"atomic": "cpp",
+19 -1
View File
@@ -38,4 +38,22 @@ target_include_directories(${PROJECT_NAME} PRIVATE
)
message(STATUS "Setting up linked libraries")
target_link_libraries(${PROJECT_NAME} PRIVATE AsyncLogger imgui minhook nlohmann_json::nlohmann_json dbghelp d3dcompiler dwmapi)
target_link_libraries(${PROJECT_NAME} PRIVATE
# Project dependencies
AsyncLogger
imgui
minhook
nlohmann_json::nlohmann_json
dbghelp
# ImGui dependencies
$<IF:$<BOOL:${CROSSCOMPILE}>,d3dcompiler_47,d3dcompiler>
dwmapi
gdi32
)
target_compile_options(${PROJECT_NAME} PRIVATE
# Do not warn about non-reproducible code
$<$<COMPILE_LANG_AND_ID:C,Clang>:-Wno-date-time>
$<$<COMPILE_LANG_AND_ID:CXX,Clang>:-Wno-date-time>
)
+153 -27
View File
@@ -1,46 +1,172 @@
# credits to @tupoy-ya for this
option(USE_GCC "Use MinGW toolchain with gcc compiler and uasm assembler.")
option(USE_CLANG "Use MinGW toolchain with clang compiler and uasm assembler. Clang support is experimental.")
if(WIN32 OR CYGWIN)
set(CROSSCOMPILE_DEFAULT OFF)
else()
set(CROSSCOMPILE_DEFAULT ON)
endif()
if(USE_GCC OR USE_CLANG)
message(STATUS "Cross-compile is enabled. Using MinGW and uasm.")
option(CROSSCOMPILE "Enable cross-compilation by using Zig/Clang(with MinGW) toolchain." ${CROSSCOMPILE_DEFAULT})
set(TOOLCHAIN_PREFIX "x86_64-w64-mingw32" CACHE STRING "Set toolchain. Default: x86_64-w64-mingw32")
message(STATUS "Using ${TOOLCHAIN_PREFIX} toolchain")
set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32)
set(CMAKE_ASM_MASM_COMPILER "uasm")
if(CROSSCOMPILE)
message(STATUS "Cross-compile is enabled.")
set(CMAKE_Fortran_COMPILER ${TOOLCHAIN_PREFIX}-gfortran)
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
# Set the CMake system name to Windows for cross-compilation
set(CMAKE_SYSTEM_NAME Windows)
# modify default behavior of FIND_XXX() commands
# adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# search headers and libraries in the target environment
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
add_compile_options("$<$<COMPILE_LANGUAGE:ASM_MASM>:-win64${ASM_MASM_FLAGS}>")
# Link statically to avoid runtime dependencies
add_link_options(-static)
add_compile_definitions(CROSSCOMPILING)
if(USE_GCC)
# Disable RTTI to work around libstdc++ issue https://stackoverflow.com/a/77025827
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:-fpermissive;-fno-rtti${CXX_FLAGS}>")
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
set(CMAKE_C_COMPILER_TARGET x86_64-windows-gnu)
set(CMAKE_CXX_COMPILER_TARGET x86_64-windows-gnu)
# Detect available compilers
message(STATUS "Searching for compiler...")
# Force specific compiler by using CMake cache variables
set(USE_CROSSCOMPILER "Auto" CACHE STRING "Cross-compiler to use (default: Auto)")
set_property(CACHE USE_CROSSCOMPILER PROPERTY STRINGS "Auto" "Zig" "Clang")
# Seach for Zig
find_program(ZIG_EXECUTABLE zig)
if(ZIG_EXECUTABLE AND (USE_CROSSCOMPILER STREQUAL "Auto" OR USE_CROSSCOMPILER STREQUAL "Zig"))
set(USE_CROSSCOMPILER "Zig")
elseif(NOT ZIG_EXECUTABLE)
message(STATUS "Zig compiler not found.")
endif()
if(USE_CLANG)
message(STATUS "Using clang compiler.")
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_C_COMPILER_TARGET x86_64-windows-msvc)
set(CMAKE_CXX_COMPILER_TARGET x86_64-windows-msvc)
# Search for Clang
find_program(CLANG_EXECUTABLE clang)
if(CLANG_EXECUTABLE AND (USE_CROSSCOMPILER STREQUAL "Auto" OR USE_CROSSCOMPILER STREQUAL "Clang"))
set(USE_CROSSCOMPILER "Clang")
elseif(NOT CLANG_EXECUTABLE)
message(STATUS "Clang compiler not found.")
endif()
# Configure the toolchain based on the selected compiler
if(USE_CROSSCOMPILER STREQUAL "Zig")
message(STATUS "Using Zig for cross-compilation.")
# Set Zig target triple
set(ZIG_ARCH "x86_64")
set(ZIG_SYS "windows")
set(ZIG_ENV "gnu") # "msvc" will not work, as it lacks libc support
set(ZIG_TARGET "${ZIG_ARCH}-${ZIG_SYS}-${ZIG_ENV}")
# Define Zig toolchain commands
# Some of them intentionally are not in double quotes
set(ZIG_AR "${ZIG_EXECUTABLE} ar")
set(ZIG_CC ${ZIG_EXECUTABLE} cc)
set(ZIG_CXX ${ZIG_EXECUTABLE} c++)
#set(ZIG_DLLTOOL "${ZIG_EXECUTABLE} dlltool")
set(ZIG_LD "${ZIG_EXECUTABLE} ld.lld")
#set(ZIG_LIB "${ZIG_EXECUTABLE} lib")
set(ZIG_RANLIB "${ZIG_EXECUTABLE} ranlib")
#set(ZIG_OBJCOPY "${ZIG_EXECUTABLE} objcopy")
set(ZIG_RC "${ZIG_EXECUTABLE} rc")
# Setup archive commands
# We're not using `CMAKE_AR` and `CMAKE_RANLIB` because they expect path without arguments
# and `ar` and `ranlib` are arguments of `zig` command
set(CMAKE_C_ARCHIVE_CREATE "${ZIG_AR} qc <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_CREATE "${ZIG_AR} qc <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_C_ARCHIVE_APPEND "${ZIG_AR} q <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_APPEND "${ZIG_AR} q <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_C_ARCHIVE_FINISH "${ZIG_RANLIB} <TARGET>")
set(CMAKE_CXX_ARCHIVE_FINISH "${ZIG_RANLIB} <TARGET>")
# Setup compiler
set(CMAKE_C_COMPILER ${ZIG_CC} -target ${ZIG_TARGET})
set(CMAKE_CXX_COMPILER ${ZIG_CXX} -target ${ZIG_TARGET})
set(CMAKE_C_COMPILER_TARGET ${ZIG_TARGET})
set(CMAKE_CXX_COMPILER_TARGET ${ZIG_TARGET})
# Setup linker
set(CMAKE_LINKER_TYPE LLD)
if (CMAKE_VERSION VERSION_LESS "4.0.0")
set(CMAKE_C_USING_LINKER_MODE TOOL)
set(CMAKE_CXX_USING_LINKER_MODE TOOL)
else()
set(CMAKE_C_LINK_MODE LINKER)
set(CMAKE_CXX_LINK_MODE LINKER)
endif()
set(CMAKE_C_USING_LINKER_LLD ${ZIG_LD})
set(CMAKE_CXX_USING_LINKER_LLD ${ZIG_LD})
# Setup resource compiler
set(CMAKE_RC_COMPILER ${ZIG_RC})
# Enable Microsoft Extensions for Zig (__try/__except/__finally, etc.)
add_compile_options("$<$<COMPILE_LANGUAGE:C>:-fms-extensions${C_FLAGS}>")
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:-fms-extensions${CXX_FLAGS}>")
elseif(USE_CROSSCOMPILER STREQUAL "Clang")
message(STATUS "Using Clang(MinGW) compiler.")
set(TOOLCHAIN_PREFIX "auto" CACHE STRING "Set toolchain. Default: auto")
if(TOOLCHAIN_PREFIX STREQUAL "auto")
# Define list of possible toolchain prefixes to try
set(POSSIBLE_TOOLCHAIN_PREFIXES
"x86_64-w64-mingw32ucrt"
"x86_64-w64-mingw32"
)
# Probe each prefix to find the first existing one
foreach(PREFIX ${POSSIBLE_TOOLCHAIN_PREFIXES})
if(EXISTS "/usr/${PREFIX}")
set(TOOLCHAIN_PREFIX ${PREFIX})
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
message(STATUS "Found toolchain: ${TOOLCHAIN_PREFIX}")
break()
endif()
endforeach()
# Check if we found a valid toolchain
if(TOOLCHAIN_PREFIX STREQUAL "auto")
message(FATAL_ERROR "No MinGW toolchain found in /usr/. Tried: ${POSSIBLE_TOOLCHAIN_PREFIXES}")
endif()
message(STATUS "Using auto-detected toolchain.")
else()
# Use the specified by user toolchain prefix
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
message(STATUS "Using specified toolchain prefix: ${TOOLCHAIN_PREFIX}")
endif()
set(CMAKE_C_COMPILER ${CLANG_EXECUTABLE})
set(CMAKE_CXX_COMPILER ${CLANG_EXECUTABLE}++)
set(CMAKE_C_COMPILER_TARGET ${TOOLCHAIN_PREFIX})
set(CMAKE_CXX_COMPILER_TARGET ${TOOLCHAIN_PREFIX})
# Enable Microsoft Extensions for Clang (__try/__except/__finally, etc.)
add_compile_options("$<$<COMPILE_LANGUAGE:C>:-fms-extensions${C_FLAGS}>")
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:-fms-extensions${CXX_FLAGS}>")
# Emulate TLS for Clang
# This is needed for compatibility with MinGW's libstdc++.
# See https://github.com/msys2/MINGW-packages/issues/5786
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:-femulated-tls${CXX_FLAGS}>")
# Disable RTTI to work around libstdc++ issue https://stackoverflow.com/a/77025827
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:-fuse-ld=lld;-fno-rtti${CXX_FLAGS}>")
add_link_options(-fuse-ld=lld -fno-rtti)
else()
message(FATAL_ERROR
"No suitable cross-compilation toolchain found."
"\nInstall either:"
"\n - Zig:"
"\n - Just install Zig and make sure it is in PATH."
"\n - Clang:"
"\n - Install Clang and MinGW toolchain (recommended: x86_64-w64-mingw32ucrt)."
)
endif()
endif()
+8 -13
View File
@@ -6,28 +6,23 @@ message(STATUS "Setting up ${LIB_NAME}")
FetchContent_Declare(
${LIB_NAME}
GIT_REPOSITORY https://github.com/ocornut/imgui
GIT_TAG v1.91.9
GIT_TAG 725d185a31f860b74014aba167aa69003d12c01a
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(${LIB_NAME})
FetchContent_GetProperties(${LIB_NAME})
if(NOT imgui_POPULATED)
FetchContent_Populate(${LIB_NAME})
file(GLOB SRC_IMGUI
file(GLOB SRC_IMGUI
"${imgui_SOURCE_DIR}/*.cpp"
"${imgui_SOURCE_DIR}/*.h"
"${imgui_SOURCE_DIR}/backends/imgui_impl_win32.*"
"${imgui_SOURCE_DIR}/backends/imgui_impl_dx12.*"
"${imgui_SOURCE_DIR}/misc/cpp/imgui_stdlib.*"
)
)
add_library(imgui STATIC ${SRC_IMGUI})
source_group(TREE ${imgui_SOURCE_DIR} PREFIX "imgui" FILES ${SRC_IMGUI})
target_include_directories(imgui PRIVATE
add_library(imgui STATIC ${SRC_IMGUI})
source_group(TREE ${imgui_SOURCE_DIR} PREFIX "imgui" FILES ${SRC_IMGUI})
target_include_directories(imgui PRIVATE
"${imgui_SOURCE_DIR}"
"${imgui_SOURCE_DIR}/backends"
"${imgui_SOURCE_DIR}/misc/cpp"
)
endif()
)
+1 -1
View File
@@ -153,7 +153,7 @@ namespace YimMenu::Submenus
});
}
if (*Pointers.IsSessionStarted && selectedWeaponHash != NULL)
if (*Pointers.IsSessionStarted && selectedWeaponHash != 0)
{
ImGui::Text("Kills With: %d", kills);
ImGui::Text("Deaths By: %d", deaths);