From 988b9a62a4ed15d04773ab461d906a54076d8974 Mon Sep 17 00:00:00 2001 From: JohnsterID <69278611+JohnsterID@users.noreply.github.com> Date: Wed, 21 Jan 2026 20:16:55 +0000 Subject: [PATCH 1/8] build(ci): Add MinGW-w64 i686 cross-compilation to CI workflow (#2163) Add automated MinGW-w64 (i686) build jobs for both Generals and GeneralsMD to the CI pipeline, enabling Linux-hosted cross-compilation with artifact collection matching the MSVC PDB workflow. Changes: - .github/workflows/ci.yml: Add two new matrix build jobs - build-mingw-generals: Builds Generals with mingw-w64-i686 toolchain - build-mingw-generalsmd: Builds GeneralsMD with mingw-w64-i686 toolchain - Matrix: mingw-w64-i686 (Release), mingw-w64-i686-debug (Debug) - Profile preset excluded (uses MSVC inline ASM with no GCC equivalent) Toolchain setup (ubuntu-latest): - MinGW-w64 cross-compiler (i686-w64-mingw32-gcc) - Wine stable + widl for COM interface compilation - CMake with Unix Makefiles generator - Cached toolchain and dependencies Artifact collection: - Stripped executable (.exe) + separate debug symbols (.exe.debug) for Release - Single executable with embedded symbols for Debug - Matches MSVC .exe + .pdb workflow - Static linked (no DLL dependencies) - 30-day retention period Jobs respect detect-changes filter (Generals/**, GeneralsMD/**, Core/**, .github/workflows/**, etc.) for conditional execution, identical to existing VC6 and win32 build triggers. Result: 4 new artifact combinations - Generals-mingw-w64-i686 (76 MB: 12 MB exe + 229 MB debug) - Generals-mingw-w64-i686-debug (56.6 MB: 200 MB exe) - GeneralsMD-mingw-w64-i686 (82.2 MB: 13 MB exe + 248 MB debug) - GeneralsMD-mingw-w64-i686-debug (61.4 MB: 215 MB exe) --- .github/workflows/ci.yml | 194 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 614d06644ee..8c96c988ca4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -267,3 +267,197 @@ jobs: userdata: "GeneralsReplays/GeneralsZH/1.04" preset: ${{ matrix.preset }} secrets: inherit + + build-mingw-generals: + name: Build Generals MinGW-w64 (${{ matrix.preset }}) + needs: detect-changes + if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generals == 'true' || needs.detect-changes.outputs.shared == 'true' }} + runs-on: ubuntu-latest + timeout-minutes: 45 + strategy: + matrix: + preset: ["mingw-w64-i686", "mingw-w64-i686-debug"] + # Note: mingw-w64-i686-profile excluded - profiling uses ASM with no GCC equivalent + fail-fast: false + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Cache MinGW-w64 Dependencies + id: cache-mingw-deps + uses: actions/cache@v4 + with: + path: | + /usr/lib/gcc/i686-w64-mingw32 + /usr/i686-w64-mingw32 + key: mingw-w64-deps-${{ runner.os }}-v1 + + - name: Install MinGW-w64 Toolchain + run: | + sudo apt-get update + sudo apt-get install -y mingw-w64 cmake + + - name: Install Wine and widl + run: | + + # Add Wine repository + sudo dpkg --add-architecture i386 + sudo mkdir -pm755 /etc/apt/keyrings + sudo wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key + + # Determine Ubuntu codename + CODENAME=$(lsb_release -cs) + + # Download appropriate sources file + sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/${CODENAME}/winehq-${CODENAME}.sources || { + sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources + } + + # Update and install Wine + sudo apt-get update + sudo apt-get install -y --install-recommends winehq-stable wine-stable-dev || { + sudo apt-get install -y wine-stable-dev + } + + - name: Cache CMake Dependencies + id: cache-cmake-deps + uses: actions/cache@v4 + with: + path: build/${{ matrix.preset }}/_deps + key: cmake-deps-mingw-${{ matrix.preset }}-${{ hashFiles('CMakePresets.json','cmake/**/*.cmake','**/CMakeLists.txt') }} + + - name: Configure Generals with CMake (${{ matrix.preset }}) + run: | + + # Unset LD_LIBRARY_PATH to avoid library conflicts + unset LD_LIBRARY_PATH + + # Configure with appropriate flags + cmake --preset ${{ matrix.preset }} \ + -DRTS_BUILD_ZEROHOUR=OFF \ + -DRTS_BUILD_GENERALS=ON \ + -DRTS_BUILD_CORE_TOOLS=OFF \ + -DRTS_BUILD_GENERALS_TOOLS=OFF \ + -DRTS_BUILD_ZEROHOUR_TOOLS=OFF \ + -DRTS_BUILD_CORE_EXTRAS=OFF \ + -DRTS_BUILD_GENERALS_EXTRAS=OFF \ + -DRTS_BUILD_ZEROHOUR_EXTRAS=OFF + - name: Build Generals (${{ matrix.preset }}) + run: | + + # Build with parallel jobs + cmake --build build/${{ matrix.preset }} --target g_generals -j$(nproc) + + - name: Collect Generals Artifacts + run: | + ARTIFACTS_DIR="build/${{ matrix.preset }}/Generals/artifacts" + mkdir -p "$ARTIFACTS_DIR" + + # Copy executables, DLLs, and debug symbols + find build/${{ matrix.preset }}/Core build/${{ matrix.preset }}/Generals -type f \( -name "*.exe" -o -name "*.dll" -o -name "*.exe.debug" \) -exec cp {} "$ARTIFACTS_DIR/" \; 2>/dev/null || true + + - name: Upload Generals ${{ matrix.preset }} Artifact + uses: actions/upload-artifact@v4 + with: + name: Generals-${{ matrix.preset }} + path: build/${{ matrix.preset }}/Generals/artifacts + retention-days: 30 + if-no-files-found: error + + build-mingw-generalsmd: + name: Build GeneralsMD MinGW-w64 (${{ matrix.preset }}) + needs: detect-changes + if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generalsmd == 'true' || needs.detect-changes.outputs.shared == 'true' }} + runs-on: ubuntu-latest + timeout-minutes: 45 + strategy: + matrix: + preset: ["mingw-w64-i686", "mingw-w64-i686-debug"] + # Note: mingw-w64-i686-profile excluded - profiling uses ASM with no GCC equivalent + fail-fast: false + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Cache MinGW-w64 Dependencies + id: cache-mingw-deps + uses: actions/cache@v4 + with: + path: | + /usr/lib/gcc/i686-w64-mingw32 + /usr/i686-w64-mingw32 + key: mingw-w64-deps-${{ runner.os }}-v1 + + - name: Install MinGW-w64 Toolchain + run: | + sudo apt-get update + sudo apt-get install -y mingw-w64 cmake + + - name: Install Wine and widl + run: | + + # Add Wine repository + sudo dpkg --add-architecture i386 + sudo mkdir -pm755 /etc/apt/keyrings + sudo wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key + + # Determine Ubuntu codename + CODENAME=$(lsb_release -cs) + + # Download appropriate sources file + sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/${CODENAME}/winehq-${CODENAME}.sources || { + sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources + } + + # Update and install Wine + sudo apt-get update + sudo apt-get install -y --install-recommends winehq-stable wine-stable-dev || { + sudo apt-get install -y wine-stable-dev + } + + - name: Cache CMake Dependencies + id: cache-cmake-deps + uses: actions/cache@v4 + with: + path: build/${{ matrix.preset }}/_deps + key: cmake-deps-mingw-${{ matrix.preset }}-${{ hashFiles('CMakePresets.json','cmake/**/*.cmake','**/CMakeLists.txt') }} + + - name: Configure GeneralsMD with CMake (${{ matrix.preset }}) + run: | + + # Unset LD_LIBRARY_PATH to avoid library conflicts + unset LD_LIBRARY_PATH + + # Configure with appropriate flags + cmake --preset ${{ matrix.preset }} \ + -DRTS_BUILD_ZEROHOUR=ON \ + -DRTS_BUILD_GENERALS=OFF \ + -DRTS_BUILD_CORE_TOOLS=OFF \ + -DRTS_BUILD_GENERALS_TOOLS=OFF \ + -DRTS_BUILD_ZEROHOUR_TOOLS=OFF \ + -DRTS_BUILD_CORE_EXTRAS=OFF \ + -DRTS_BUILD_GENERALS_EXTRAS=OFF \ + -DRTS_BUILD_ZEROHOUR_EXTRAS=OFF + - name: Build GeneralsMD (${{ matrix.preset }}) + run: | + + # Build with parallel jobs + cmake --build build/${{ matrix.preset }} --target z_generals -j$(nproc) + + - name: Collect GeneralsMD Artifacts + run: | + ARTIFACTS_DIR="build/${{ matrix.preset }}/GeneralsMD/artifacts" + mkdir -p "$ARTIFACTS_DIR" + + # Copy executables, DLLs, and debug symbols + find build/${{ matrix.preset }}/Core build/${{ matrix.preset }}/GeneralsMD -type f \( -name "*.exe" -o -name "*.dll" -o -name "*.exe.debug" \) -exec cp {} "$ARTIFACTS_DIR/" \; 2>/dev/null || true + + - name: Upload GeneralsMD ${{ matrix.preset }} Artifact + uses: actions/upload-artifact@v4 + with: + name: GeneralsMD-${{ matrix.preset }} + path: build/${{ matrix.preset }}/GeneralsMD/artifacts + retention-days: 30 + if-no-files-found: error From c48e661ce1864e978b9257b0bd604396ed7e74e2 Mon Sep 17 00:00:00 2001 From: JohnsterID <69278611+JohnsterID@users.noreply.github.com> Date: Sat, 7 Mar 2026 09:07:22 +0000 Subject: [PATCH 2/8] build(ci): Remove ineffective MinGW-w64 system path caching The Cache MinGW-w64 Dependencies step attempted to cache system paths (/usr/lib/gcc/i686-w64-mingw32, /usr/i686-w64-mingw32) which is problematic due to permission issues with actions/cache when handling root-owned paths. Additionally, the Install MinGW-w64 Toolchain step ran unconditionally without checking cache-hit status, making the cache completely redundant. Remove the cache step entirely and rely on apt-get install which is fast enough (~4s at 76MB/s) and reliable. --- .github/workflows/ci.yml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c96c988ca4..21f27374e8c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -284,15 +284,6 @@ jobs: - name: Checkout Code uses: actions/checkout@v4 - - name: Cache MinGW-w64 Dependencies - id: cache-mingw-deps - uses: actions/cache@v4 - with: - path: | - /usr/lib/gcc/i686-w64-mingw32 - /usr/i686-w64-mingw32 - key: mingw-w64-deps-${{ runner.os }}-v1 - - name: Install MinGW-w64 Toolchain run: | sudo apt-get update @@ -381,15 +372,6 @@ jobs: - name: Checkout Code uses: actions/checkout@v4 - - name: Cache MinGW-w64 Dependencies - id: cache-mingw-deps - uses: actions/cache@v4 - with: - path: | - /usr/lib/gcc/i686-w64-mingw32 - /usr/i686-w64-mingw32 - key: mingw-w64-deps-${{ runner.os }}-v1 - - name: Install MinGW-w64 Toolchain run: | sudo apt-get update From 6466fa45cbdf08144d9197387d54eb511ab512e7 Mon Sep 17 00:00:00 2001 From: Omar Aglan Date: Sun, 18 Oct 2026 14:23:02 +0300 Subject: [PATCH 3/8] build(cmake): Fix MinGW-w64 linking of the game engine, engine device and WWDownload libraries --- Core/Libraries/Source/WWVegas/WWDownload/CMakeLists.txt | 1 + Generals/Code/GameEngine/CMakeLists.txt | 6 ++++++ GeneralsMD/Code/GameEngine/CMakeLists.txt | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/Core/Libraries/Source/WWVegas/WWDownload/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WWDownload/CMakeLists.txt index ee2966bc91c..0cd311cb8dd 100644 --- a/Core/Libraries/Source/WWVegas/WWDownload/CMakeLists.txt +++ b/Core/Libraries/Source/WWVegas/WWDownload/CMakeLists.txt @@ -18,4 +18,5 @@ target_sources(corei_wwdownload INTERFACE ${WWDOWNLOAD_SRC}) target_link_libraries(corei_wwdownload INTERFACE core_wwcommon + ws2_32 ) diff --git a/Generals/Code/GameEngine/CMakeLists.txt b/Generals/Code/GameEngine/CMakeLists.txt index 386f87e8937..5b6fdfb6384 100644 --- a/Generals/Code/GameEngine/CMakeLists.txt +++ b/Generals/Code/GameEngine/CMakeLists.txt @@ -1077,6 +1077,12 @@ target_link_libraries(g_gameengine PUBLIC g_wwvegas ) +# The engine calls functions that are implemented in the engine device, such as OSDisplaySetBusyState. +# Declaring this circular dependency lets linkers that read static libraries in order resolve them. +target_link_libraries(g_gameengine INTERFACE + g_gameenginedevice +) + target_precompile_headers(g_gameengine PRIVATE [["Precompiled/BasePrecomp.h"]] # Must be first ) diff --git a/GeneralsMD/Code/GameEngine/CMakeLists.txt b/GeneralsMD/Code/GameEngine/CMakeLists.txt index d2e14c0b5e3..88ebd6a01e4 100644 --- a/GeneralsMD/Code/GameEngine/CMakeLists.txt +++ b/GeneralsMD/Code/GameEngine/CMakeLists.txt @@ -1153,6 +1153,12 @@ target_link_libraries(z_gameengine PUBLIC z_wwvegas ) +# The engine calls functions that are implemented in the engine device, such as OSDisplaySetBusyState. +# Declaring this circular dependency lets linkers that read static libraries in order resolve them. +target_link_libraries(z_gameengine INTERFACE + z_gameenginedevice +) + target_precompile_headers(z_gameengine PRIVATE [["Precompiled/BasePrecomp.h"]] # Must be first ) From 8de43fda5ffa7528318ca211d3d1ef70040062fc Mon Sep 17 00:00:00 2001 From: Omar Aglan Date: Sun, 18 Oct 2026 15:13:39 +0300 Subject: [PATCH 4/8] build(ci): Pin MinGW-w64 job actions to commit SHAs and stop hiding artifact copy errors --- .github/workflows/ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 21f27374e8c..8d08dc78bb3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -282,7 +282,7 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install MinGW-w64 Toolchain run: | @@ -313,7 +313,7 @@ jobs: - name: Cache CMake Dependencies id: cache-cmake-deps - uses: actions/cache@v4 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: build/${{ matrix.preset }}/_deps key: cmake-deps-mingw-${{ matrix.preset }}-${{ hashFiles('CMakePresets.json','cmake/**/*.cmake','**/CMakeLists.txt') }} @@ -346,10 +346,10 @@ jobs: mkdir -p "$ARTIFACTS_DIR" # Copy executables, DLLs, and debug symbols - find build/${{ matrix.preset }}/Core build/${{ matrix.preset }}/Generals -type f \( -name "*.exe" -o -name "*.dll" -o -name "*.exe.debug" \) -exec cp {} "$ARTIFACTS_DIR/" \; 2>/dev/null || true + find build/${{ matrix.preset }}/Core build/${{ matrix.preset }}/Generals -path "$ARTIFACTS_DIR" -prune -o -type f \( -name "*.exe" -o -name "*.dll" -o -name "*.exe.debug" \) -exec cp -t "$ARTIFACTS_DIR" {} + - name: Upload Generals ${{ matrix.preset }} Artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: Generals-${{ matrix.preset }} path: build/${{ matrix.preset }}/Generals/artifacts @@ -370,7 +370,7 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install MinGW-w64 Toolchain run: | @@ -401,7 +401,7 @@ jobs: - name: Cache CMake Dependencies id: cache-cmake-deps - uses: actions/cache@v4 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: build/${{ matrix.preset }}/_deps key: cmake-deps-mingw-${{ matrix.preset }}-${{ hashFiles('CMakePresets.json','cmake/**/*.cmake','**/CMakeLists.txt') }} @@ -434,10 +434,10 @@ jobs: mkdir -p "$ARTIFACTS_DIR" # Copy executables, DLLs, and debug symbols - find build/${{ matrix.preset }}/Core build/${{ matrix.preset }}/GeneralsMD -type f \( -name "*.exe" -o -name "*.dll" -o -name "*.exe.debug" \) -exec cp {} "$ARTIFACTS_DIR/" \; 2>/dev/null || true + find build/${{ matrix.preset }}/Core build/${{ matrix.preset }}/GeneralsMD -path "$ARTIFACTS_DIR" -prune -o -type f \( -name "*.exe" -o -name "*.dll" -o -name "*.exe.debug" \) -exec cp -t "$ARTIFACTS_DIR" {} + - name: Upload GeneralsMD ${{ matrix.preset }} Artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: GeneralsMD-${{ matrix.preset }} path: build/${{ matrix.preset }}/GeneralsMD/artifacts From 79addaa08afd536d65dc8914cdc12e814d701f3e Mon Sep 17 00:00:00 2001 From: Omar Aglan Date: Sun, 8 Nov 2026 14:27:20 +0300 Subject: [PATCH 5/8] build(ci): Move MinGW-w64 jobs into a reusable workflow and build the release preset only --- .github/workflows/ci.yml | 183 ++------------------- .github/workflows/reusable-build-mingw.yml | 96 +++++++++++ 2 files changed, 111 insertions(+), 168 deletions(-) create mode 100644 .github/workflows/reusable-build-mingw.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d08dc78bb3..206879b7ca6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -268,178 +268,25 @@ jobs: preset: ${{ matrix.preset }} secrets: inherit + # Release preset only. mingw-w64-i686-profile is excluded because profiling uses MSVC inline assembly, which GCC does not compile. build-mingw-generals: - name: Build Generals MinGW-w64 (${{ matrix.preset }}) + name: Build Generals MinGW-w64 needs: detect-changes if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generals == 'true' || needs.detect-changes.outputs.shared == 'true' }} - runs-on: ubuntu-latest - timeout-minutes: 45 - strategy: - matrix: - preset: ["mingw-w64-i686", "mingw-w64-i686-debug"] - # Note: mingw-w64-i686-profile excluded - profiling uses ASM with no GCC equivalent - fail-fast: false - - steps: - - name: Checkout Code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Install MinGW-w64 Toolchain - run: | - sudo apt-get update - sudo apt-get install -y mingw-w64 cmake - - - name: Install Wine and widl - run: | - - # Add Wine repository - sudo dpkg --add-architecture i386 - sudo mkdir -pm755 /etc/apt/keyrings - sudo wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key - - # Determine Ubuntu codename - CODENAME=$(lsb_release -cs) - - # Download appropriate sources file - sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/${CODENAME}/winehq-${CODENAME}.sources || { - sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources - } - - # Update and install Wine - sudo apt-get update - sudo apt-get install -y --install-recommends winehq-stable wine-stable-dev || { - sudo apt-get install -y wine-stable-dev - } - - - name: Cache CMake Dependencies - id: cache-cmake-deps - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 - with: - path: build/${{ matrix.preset }}/_deps - key: cmake-deps-mingw-${{ matrix.preset }}-${{ hashFiles('CMakePresets.json','cmake/**/*.cmake','**/CMakeLists.txt') }} - - - name: Configure Generals with CMake (${{ matrix.preset }}) - run: | - - # Unset LD_LIBRARY_PATH to avoid library conflicts - unset LD_LIBRARY_PATH - - # Configure with appropriate flags - cmake --preset ${{ matrix.preset }} \ - -DRTS_BUILD_ZEROHOUR=OFF \ - -DRTS_BUILD_GENERALS=ON \ - -DRTS_BUILD_CORE_TOOLS=OFF \ - -DRTS_BUILD_GENERALS_TOOLS=OFF \ - -DRTS_BUILD_ZEROHOUR_TOOLS=OFF \ - -DRTS_BUILD_CORE_EXTRAS=OFF \ - -DRTS_BUILD_GENERALS_EXTRAS=OFF \ - -DRTS_BUILD_ZEROHOUR_EXTRAS=OFF - - name: Build Generals (${{ matrix.preset }}) - run: | - - # Build with parallel jobs - cmake --build build/${{ matrix.preset }} --target g_generals -j$(nproc) - - - name: Collect Generals Artifacts - run: | - ARTIFACTS_DIR="build/${{ matrix.preset }}/Generals/artifacts" - mkdir -p "$ARTIFACTS_DIR" - - # Copy executables, DLLs, and debug symbols - find build/${{ matrix.preset }}/Core build/${{ matrix.preset }}/Generals -path "$ARTIFACTS_DIR" -prune -o -type f \( -name "*.exe" -o -name "*.dll" -o -name "*.exe.debug" \) -exec cp -t "$ARTIFACTS_DIR" {} + - - - name: Upload Generals ${{ matrix.preset }} Artifact - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 - with: - name: Generals-${{ matrix.preset }} - path: build/${{ matrix.preset }}/Generals/artifacts - retention-days: 30 - if-no-files-found: error + permissions: + contents: read + uses: ./.github/workflows/reusable-build-mingw.yml + with: + game: "Generals" + preset: "mingw-w64-i686" build-mingw-generalsmd: - name: Build GeneralsMD MinGW-w64 (${{ matrix.preset }}) + name: Build GeneralsMD MinGW-w64 needs: detect-changes if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generalsmd == 'true' || needs.detect-changes.outputs.shared == 'true' }} - runs-on: ubuntu-latest - timeout-minutes: 45 - strategy: - matrix: - preset: ["mingw-w64-i686", "mingw-w64-i686-debug"] - # Note: mingw-w64-i686-profile excluded - profiling uses ASM with no GCC equivalent - fail-fast: false - - steps: - - name: Checkout Code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Install MinGW-w64 Toolchain - run: | - sudo apt-get update - sudo apt-get install -y mingw-w64 cmake - - - name: Install Wine and widl - run: | - - # Add Wine repository - sudo dpkg --add-architecture i386 - sudo mkdir -pm755 /etc/apt/keyrings - sudo wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key - - # Determine Ubuntu codename - CODENAME=$(lsb_release -cs) - - # Download appropriate sources file - sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/${CODENAME}/winehq-${CODENAME}.sources || { - sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources - } - - # Update and install Wine - sudo apt-get update - sudo apt-get install -y --install-recommends winehq-stable wine-stable-dev || { - sudo apt-get install -y wine-stable-dev - } - - - name: Cache CMake Dependencies - id: cache-cmake-deps - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 - with: - path: build/${{ matrix.preset }}/_deps - key: cmake-deps-mingw-${{ matrix.preset }}-${{ hashFiles('CMakePresets.json','cmake/**/*.cmake','**/CMakeLists.txt') }} - - - name: Configure GeneralsMD with CMake (${{ matrix.preset }}) - run: | - - # Unset LD_LIBRARY_PATH to avoid library conflicts - unset LD_LIBRARY_PATH - - # Configure with appropriate flags - cmake --preset ${{ matrix.preset }} \ - -DRTS_BUILD_ZEROHOUR=ON \ - -DRTS_BUILD_GENERALS=OFF \ - -DRTS_BUILD_CORE_TOOLS=OFF \ - -DRTS_BUILD_GENERALS_TOOLS=OFF \ - -DRTS_BUILD_ZEROHOUR_TOOLS=OFF \ - -DRTS_BUILD_CORE_EXTRAS=OFF \ - -DRTS_BUILD_GENERALS_EXTRAS=OFF \ - -DRTS_BUILD_ZEROHOUR_EXTRAS=OFF - - name: Build GeneralsMD (${{ matrix.preset }}) - run: | - - # Build with parallel jobs - cmake --build build/${{ matrix.preset }} --target z_generals -j$(nproc) - - - name: Collect GeneralsMD Artifacts - run: | - ARTIFACTS_DIR="build/${{ matrix.preset }}/GeneralsMD/artifacts" - mkdir -p "$ARTIFACTS_DIR" - - # Copy executables, DLLs, and debug symbols - find build/${{ matrix.preset }}/Core build/${{ matrix.preset }}/GeneralsMD -path "$ARTIFACTS_DIR" -prune -o -type f \( -name "*.exe" -o -name "*.dll" -o -name "*.exe.debug" \) -exec cp -t "$ARTIFACTS_DIR" {} + - - - name: Upload GeneralsMD ${{ matrix.preset }} Artifact - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 - with: - name: GeneralsMD-${{ matrix.preset }} - path: build/${{ matrix.preset }}/GeneralsMD/artifacts - retention-days: 30 - if-no-files-found: error + permissions: + contents: read + uses: ./.github/workflows/reusable-build-mingw.yml + with: + game: "GeneralsMD" + preset: "mingw-w64-i686" diff --git a/.github/workflows/reusable-build-mingw.yml b/.github/workflows/reusable-build-mingw.yml new file mode 100644 index 00000000000..41f198d8e6a --- /dev/null +++ b/.github/workflows/reusable-build-mingw.yml @@ -0,0 +1,96 @@ +name: Build MinGW-w64 + +# WARNING: Do not declare permissions in this reusable workflow. +# Declare the required permissions in each calling job: +# contents: read - required for all builds. + +on: + workflow_call: + inputs: + game: + required: true + type: string + description: "Game to build (Generals or GeneralsMD)" + preset: + required: true + type: string + description: "CMake preset" + +jobs: + build: + name: ${{ inputs.preset }} + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - name: Checkout Code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Install MinGW-w64 Toolchain + run: | + sudo apt-get update + sudo apt-get install -y mingw-w64 cmake + + - name: Install Wine and widl + run: | + # Add Wine repository + sudo dpkg --add-architecture i386 + sudo mkdir -pm755 /etc/apt/keyrings + sudo wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key + + # Determine Ubuntu codename + CODENAME=$(lsb_release -cs) + + # Download appropriate sources file + sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/${CODENAME}/winehq-${CODENAME}.sources || { + sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources + } + + # Update and install Wine + sudo apt-get update + sudo apt-get install -y --install-recommends winehq-stable wine-stable-dev || { + sudo apt-get install -y wine-stable-dev + } + + - name: Cache CMake Dependencies + id: cache-cmake-deps + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + path: build/${{ inputs.preset }}/_deps + key: cmake-deps-mingw-${{ inputs.preset }}-${{ hashFiles('CMakePresets.json','cmake/**/*.cmake','**/CMakeLists.txt') }} + + - name: Configure ${{ inputs.game }} with CMake (${{ inputs.preset }}) + run: | + # Unset LD_LIBRARY_PATH to avoid library conflicts + unset LD_LIBRARY_PATH + + # Configure with appropriate flags + cmake --preset ${{ inputs.preset }} \ + -DRTS_BUILD_ZEROHOUR=${{ inputs.game == 'GeneralsMD' && 'ON' || 'OFF' }} \ + -DRTS_BUILD_GENERALS=${{ inputs.game == 'Generals' && 'ON' || 'OFF' }} \ + -DRTS_BUILD_CORE_TOOLS=OFF \ + -DRTS_BUILD_GENERALS_TOOLS=OFF \ + -DRTS_BUILD_ZEROHOUR_TOOLS=OFF \ + -DRTS_BUILD_CORE_EXTRAS=OFF \ + -DRTS_BUILD_GENERALS_EXTRAS=OFF \ + -DRTS_BUILD_ZEROHOUR_EXTRAS=OFF + + - name: Build ${{ inputs.game }} (${{ inputs.preset }}) + run: | + # Build with parallel jobs + cmake --build build/${{ inputs.preset }} --target ${{ inputs.game == 'Generals' && 'g_generals' || 'z_generals' }} -j$(nproc) + + - name: Collect ${{ inputs.game }} Artifacts + run: | + ARTIFACTS_DIR="build/${{ inputs.preset }}/${{ inputs.game }}/artifacts" + mkdir -p "$ARTIFACTS_DIR" + + # Copy executables, DLLs, and debug symbols + find build/${{ inputs.preset }}/Core build/${{ inputs.preset }}/${{ inputs.game }} -path "$ARTIFACTS_DIR" -prune -o -type f \( -name "*.exe" -o -name "*.dll" -o -name "*.exe.debug" \) -exec cp -t "$ARTIFACTS_DIR" {} + + + - name: Upload ${{ inputs.game }} ${{ inputs.preset }} Artifact + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: ${{ inputs.game }}-${{ inputs.preset }} + path: build/${{ inputs.preset }}/${{ inputs.game }}/artifacts + retention-days: 30 + if-no-files-found: error From 8564f5c29f7d48edc4bd3be043eef04e1f424e16 Mon Sep 17 00:00:00 2001 From: Omar Aglan Date: Sun, 8 Nov 2026 14:51:04 +0300 Subject: [PATCH 6/8] build(ci): Pin the MinGW-w64 runner to Ubuntu 24.04 --- .github/workflows/reusable-build-mingw.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-build-mingw.yml b/.github/workflows/reusable-build-mingw.yml index 41f198d8e6a..995a51f8cfb 100644 --- a/.github/workflows/reusable-build-mingw.yml +++ b/.github/workflows/reusable-build-mingw.yml @@ -19,7 +19,7 @@ on: jobs: build: name: ${{ inputs.preset }} - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 45 steps: - name: Checkout Code From b36276cf6e2bc3706c25bc25adb79f50fccae3d3 Mon Sep 17 00:00:00 2001 From: Omar Aglan Date: Sun, 8 Nov 2026 15:39:55 +0300 Subject: [PATCH 7/8] build(cmake): Enable SSE2 for MinGW-w64 builds so GameMath intrinsics compile --- cmake/mingw.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/mingw.cmake b/cmake/mingw.cmake index 0630ba45c6d..9883e0e84a2 100644 --- a/cmake/mingw.cmake +++ b/cmake/mingw.cmake @@ -21,6 +21,7 @@ if(MINGW) # Compatibility flags for legacy code add_compile_options( -fno-strict-aliasing # Avoid type-punning issues with DX8/COM + -msse2 # GameMath uses SSE intrinsics; some i686 toolchains default to no SSE ) # MSVC compatibility macros for MinGW From 7151ff8c0dd12f5724c7d6bc26ac2b413204358d Mon Sep 17 00:00:00 2001 From: Omar Aglan Date: Tue, 10 Nov 2026 13:46:18 +0300 Subject: [PATCH 8/8] build(ci): Install widl from the Ubuntu Wine packages instead of the WineHQ repository in MinGW-w64 jobs --- .github/workflows/reusable-build-mingw.yml | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/.github/workflows/reusable-build-mingw.yml b/.github/workflows/reusable-build-mingw.yml index 995a51f8cfb..bf17b826fed 100644 --- a/.github/workflows/reusable-build-mingw.yml +++ b/.github/workflows/reusable-build-mingw.yml @@ -30,26 +30,10 @@ jobs: sudo apt-get update sudo apt-get install -y mingw-w64 cmake - - name: Install Wine and widl + - name: Install widl run: | - # Add Wine repository - sudo dpkg --add-architecture i386 - sudo mkdir -pm755 /etc/apt/keyrings - sudo wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key - - # Determine Ubuntu codename - CODENAME=$(lsb_release -cs) - - # Download appropriate sources file - sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/${CODENAME}/winehq-${CODENAME}.sources || { - sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources - } - - # Update and install Wine - sudo apt-get update - sudo apt-get install -y --install-recommends winehq-stable wine-stable-dev || { - sudo apt-get install -y wine-stable-dev - } + # widl compiles the IDL files. wine64-tools has widl and depends on libwine-dev, which has the system IDL files. + sudo apt-get install -y --no-install-recommends wine64-tools - name: Cache CMake Dependencies id: cache-cmake-deps