diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 614d06644ee..206879b7ca6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -267,3 +267,26 @@ jobs: userdata: "GeneralsReplays/GeneralsZH/1.04" 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 + needs: detect-changes + if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generals == 'true' || needs.detect-changes.outputs.shared == 'true' }} + 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 + needs: detect-changes + if: ${{ github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.generalsmd == 'true' || needs.detect-changes.outputs.shared == 'true' }} + 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..995a51f8cfb --- /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-24.04 + 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 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 ) 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