From d4197764ab1af262b589abf5e5dfc53965b0c802 Mon Sep 17 00:00:00 2001
From: dpasukhi <dpasukhi@opencascade.com>
Date: Fri, 10 Jan 2025 23:29:32 +0000
Subject: [PATCH] Testing - MinGW build validation #253

Add MinGW build validation workflow for Windows
Fix MinGW freetype linkings
---
 .github/workflows/build-multiconfig-mingw.yml | 216 ++++++++++++++++++
 adm/cmake/3rdparty_macro.cmake                |   2 +-
 adm/cmake/freetype.cmake                      |   8 +
 adm/cmake/jemalloc.cmake                      |   2 +-
 adm/cmake/occt_defs_flags.cmake               |   2 +
 5 files changed, 228 insertions(+), 2 deletions(-)
 create mode 100644 .github/workflows/build-multiconfig-mingw.yml

diff --git a/.github/workflows/build-multiconfig-mingw.yml b/.github/workflows/build-multiconfig-mingw.yml
new file mode 100644
index 0000000000..373ab38562
--- /dev/null
+++ b/.github/workflows/build-multiconfig-mingw.yml
@@ -0,0 +1,216 @@
+# This workflow validates the build on Windows using MinGW and MSYS2.
+# It is triggered on pushes to the master branch.
+# The workflow includes steps to install dependencies, configure, build, and clean up the project.
+
+name: MinGW build validation
+
+on:
+  push:
+    branches:
+      - 'master'
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
+  cancel-in-progress: true
+
+jobs:
+  main_job:
+    name: Windows MinGW validation
+    runs-on: windows-2022
+
+    strategy:
+      matrix:
+        config:
+          - {
+              name: "GCC",
+              cc: "x86_64-w64-mingw32-gcc",
+              cxx: "x86_64-w64-mingw32-g++",
+              package: "mingw-w64-x86_64-toolchain",
+              thirdparty_dir: "/mingw64",
+              dependencies: "mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-rapidjson mingw-w64-x86_64-freetype mingw-w64-x86_64-draco mingw-w64-x86_64-freeimage mingw-w64-x86_64-tbb mingw-w64-x86_64-tk mingw-w64-x86_64-tcl mingw-w64-x86_64-openvr mingw-w64-x86_64-jemalloc mingw-w64-x86_64-mesa mingw-w64-x86_64-angleproject mingw-w64-x86_64-llvm-openmp mingw-w64-x86_64-winpthreads-git mingw-w64-x86_64-libwinpthread-git mingw-w64-cross-mingwarm64-winpthreads"
+            }
+          - {
+              name: "Clang",
+              cc: "clang",
+              cxx: "clang++",
+              package: "mingw-w64-clang-x86_64-toolchain",
+              thirdparty_dir: "/clang64",
+              dependencies: "mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-ninja mingw-w64-clang-x86_64-rapidjson mingw-w64-clang-x86_64-freetype mingw-w64-clang-x86_64-draco mingw-w64-clang-x86_64-freeimage mingw-w64-clang-x86_64-tbb mingw-w64-clang-x86_64-tk mingw-w64-clang-x86_64-tcl mingw-w64-clang-x86_64-openvr mingw-w64-clang-x86_64-jemalloc mingw-w64-clang-x86_64-mesa mingw-w64-clang-x86_64-angleproject mingw-w64-clang-x86_64-llvm-openmp mingw-w64-clang-x86_64-winpthreads-git mingw-w64-clang-x86_64-libwinpthread-git mingw-w64-cross-mingwarm64-winpthreads"
+            }
+          - {
+              name: "UCRT",
+              cc: "x86_64-w64-mingw32-gcc",
+              cxx: "x86_64-w64-mingw32-g++",
+              package: "mingw-w64-ucrt-x86_64-toolchain",
+              thirdparty_dir: "/ucrt64",
+              dependencies: "mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-gcc-libs mingw-w64-ucrt-x86_64-omp mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-ninja mingw-w64-ucrt-x86_64-rapidjson mingw-w64-ucrt-x86_64-freetype mingw-w64-ucrt-x86_64-draco mingw-w64-ucrt-x86_64-freeimage mingw-w64-ucrt-x86_64-tbb mingw-w64-ucrt-x86_64-tk mingw-w64-ucrt-x86_64-tcl mingw-w64-ucrt-x86_64-openvr mingw-w64-ucrt-x86_64-jemalloc mingw-w64-ucrt-x86_64-mesa mingw-w64-ucrt-x86_64-angleproject mingw-w64-ucrt-x86_64-llvm-openmp mingw-w64-ucrt-x86_64-winpthreads-git mingw-w64-ucrt-x86_64-libwinpthread-git mingw-w64-cross-mingwarm64-winpthreads"
+            }
+
+    steps:
+    - name: Checkout repository
+      uses: actions/checkout@v4.1.7
+
+    - name: Set up MSYS2
+      uses: msys2/setup-msys2@v2
+      with:
+        msystem: ${{ matrix.config.name == 'Clang' && 'CLANG64' || matrix.config.name == 'UCRT' && 'UCRT64' || 'MINGW64' }}
+        update: true
+        install: ${{ matrix.config.package }} ${{ matrix.config.dependencies }}
+
+    - name: Setup environment
+      shell: msys2 {0}
+      run: |
+        echo "Checking compiler version:"
+        ${{ matrix.config.cc }} --version
+        echo "Checking CMake version:"
+        cmake --version
+        echo "Setting up environment variables..."
+        echo "$MSYSTEM_PREFIX/bin" >> $GITHUB_PATH
+        echo "CMAKE_PREFIX_PATH=$MSYSTEM_PREFIX" >> $GITHUB_ENV
+
+    - name: Configure basic
+      shell: msys2 {0}
+      run: |
+        mkdir -p build
+        cd build
+        cmake -G "Ninja" \
+              -D CMAKE_C_COMPILER=${{ matrix.config.cc }} \
+              -D CMAKE_CXX_COMPILER=${{ matrix.config.cxx }} \
+              -D CMAKE_PREFIX_PATH=$MSYSTEM_PREFIX \
+              -D CMAKE_CXX_FLAGS="-Wall -Wextra" \
+              -D CMAKE_C_FLAGS="-Wall -Wextra" ..
+
+    - name: Build basic
+      shell: msys2 {0}
+      run: |
+        cd build
+        cmake --build . -- -j 4
+
+    - name: Clear up after build
+      shell: pwsh
+      run: |
+        Remove-Item -Recurse -Force build
+
+    - name: Configure full shared
+      shell: msys2 {0}
+      run: |
+        mkdir -p build
+        cd build
+        cmake -G "Ninja" \
+              -D CMAKE_C_COMPILER=${{ matrix.config.cc }} \
+              -D CMAKE_CXX_COMPILER=${{ matrix.config.cxx }} \
+              -D CMAKE_PREFIX_PATH=$MSYSTEM_PREFIX \
+              -D BUILD_USE_PCH=OFF \
+              -D BUILD_INCLUDE_SYMLINK=ON \
+              -D BUILD_OPT_PROFILE=Production \
+              -D BUILD_LIBRARY_TYPE=Shared \
+              -D USE_TK=ON \
+              -D CMAKE_BUILD_TYPE=Debug \
+              -D USE_MMGR_TYPE=JEMALLOC \
+              -D INSTALL_DIR="${{ github.workspace }}/install" \
+              -D USE_FREETYPE=ON \
+              -D USE_DRACO=ON \
+              -D USE_FFMPEG=OFF \
+              -D USE_FREEIMAGE=ON \
+              -D USE_GLES2=ON \
+              -D USE_OPENVR=ON \
+              -D USE_VTK=OFF \
+              -D USE_TBB=OFF \
+              -D USE_RAPIDJSON=ON \
+              -D USE_OPENGL=ON \
+              -D CMAKE_CXX_FLAGS="-Wall -Wextra" \
+              -D CMAKE_C_FLAGS="-Wall -Wextra" ..
+
+    - name: Build full shared
+      shell: msys2 {0}
+      run: |
+        cd build
+        cmake --build . --target install --config Debug -- -j 4
+    
+    - name: Clear up after build
+      shell: pwsh
+      run: |
+        Remove-Item -Recurse -Force build
+        Remove-Item -Recurse -Force ${{ github.workspace }}/install
+
+    - name: Configure full static
+      shell: msys2 {0}
+      run: |
+        mkdir -p build
+        cd build
+        cmake -G "Ninja" \
+              -D CMAKE_C_COMPILER=${{ matrix.config.cc }} \
+              -D CMAKE_CXX_COMPILER=${{ matrix.config.cxx }} \
+              -D CMAKE_PREFIX_PATH=$MSYSTEM_PREFIX \
+              -D BUILD_USE_PCH=OFF \
+              -D BUILD_INCLUDE_SYMLINK=ON \
+              -D BUILD_OPT_PROFILE=Production \
+              -D BUILD_LIBRARY_TYPE=Static \
+              -D USE_TK=ON \
+              -D CMAKE_BUILD_TYPE=Debug \
+              -D USE_MMGR_TYPE=JEMALLOC \
+              -D INSTALL_DIR="${{ github.workspace }}/install" \
+              -D USE_FREETYPE=ON \
+              -D USE_DRACO=ON \
+              -D USE_FFMPEG=OFF \
+              -D USE_FREEIMAGE=ON \
+              -D USE_GLES2=ON \
+              -D USE_OPENVR=ON \
+              -D USE_VTK=OFF \
+              -D USE_TBB=OFF \
+              -D USE_RAPIDJSON=ON \
+              -D USE_OPENGL=ON \
+              -D CMAKE_CXX_FLAGS="-Wall -Wextra" \
+              -D CMAKE_C_FLAGS="-Wall -Wextra" ..
+
+    - name: Build full static
+      shell: msys2 {0}
+      run: |
+        cd build
+        cmake --build . --target install --config Debug -- -j 4
+
+    - name: Clear up after build
+      shell: pwsh
+      run: |
+        Remove-Item -Recurse -Force build
+        Remove-Item -Recurse -Force ${{ github.workspace }}/install
+
+    - name: Configure full with DEBUG define
+      shell: msys2 {0}
+      run: |
+        mkdir -p build
+        cd build
+        cmake -G "Ninja" \
+              -D CMAKE_C_COMPILER=${{ matrix.config.cc }} \
+              -D CMAKE_CXX_COMPILER=${{ matrix.config.cxx }} \
+              -D CMAKE_PREFIX_PATH=$MSYSTEM_PREFIX \
+              -D BUILD_WITH_DEBUG=ON \
+              -D BUILD_USE_PCH=OFF \
+              -D BUILD_INCLUDE_SYMLINK=ON \
+              -D BUILD_OPT_PROFILE=Production \
+              -D BUILD_LIBRARY_TYPE=Shared \
+              -D USE_TK=ON \
+              -D CMAKE_BUILD_TYPE=Debug \
+              -D INSTALL_DIR="${{ github.workspace }}/install" \
+              -D USE_FREETYPE=ON \
+              -D USE_DRACO=ON \
+              -D USE_FFMPEG=OFF \
+              -D USE_FREEIMAGE=ON \
+              -D USE_GLES2=ON \
+              -D USE_OPENVR=ON \
+              -D USE_VTK=OFF \
+              -D USE_TBB=OFF \
+              -D USE_RAPIDJSON=ON \
+              -D USE_OPENGL=ON ..
+
+    - name: Build full with DEBUG define
+      shell: msys2 {0}
+      run: |
+        cd build
+        cmake --build . --target install --config Debug -- -j 4
+      
+    - name: Clear up after build
+      shell: pwsh
+      run: |
+        Remove-Item -Recurse -Force build
+        Remove-Item -Recurse -Force ${{ github.workspace }}/install
diff --git a/adm/cmake/3rdparty_macro.cmake b/adm/cmake/3rdparty_macro.cmake
index 263c139143..5ce4860db5 100644
--- a/adm/cmake/3rdparty_macro.cmake
+++ b/adm/cmake/3rdparty_macro.cmake
@@ -121,7 +121,7 @@ macro (THIRDPARTY_PRODUCT PRODUCT_NAME HEADER_NAME LIBRARY_CSF_NAME LIBRARY_NAME
 #    if (BUILD_SHARED_LIBS)
       # library
       if (NOT 3RDPARTY_${PRODUCT_NAME}_LIBRARY_${LIBRARY_NAME_SUFFIX} OR NOT EXISTS "${3RDPARTY_${PRODUCT_NAME}_LIBRARY_${LIBRARY_NAME_SUFFIX}}")
-        set (CMAKE_FIND_LIBRARY_SUFFIXES .lib .so .dylib .a)
+        set (CMAKE_FIND_LIBRARY_SUFFIXES .dll.a .lib .so .dylib .a)
 
         set (${PRODUCT_NAME}_PATH_SUFFIXES lib)
         if (WIN32)
diff --git a/adm/cmake/freetype.cmake b/adm/cmake/freetype.cmake
index 498ee11e9a..010c5c268b 100644
--- a/adm/cmake/freetype.cmake
+++ b/adm/cmake/freetype.cmake
@@ -177,6 +177,14 @@ if (IS_BUILTIN_SEARCH_REQUIRED)
       set (3RDPARTY_FREETYPE_LIBRARY_DIR "" CACHE PATH "The directory containing freetype library" FORCE)
     endif()
   endif()
+
+  # In case of MinGW some libraries can have .dll.a extension, so we should check it and use instead of .a
+  if (MINGW AND 3RDPARTY_FREETYPE_LIBRARY AND EXISTS "${3RDPARTY_FREETYPE_LIBRARY}")
+    string (REPLACE ".a" ".dll.a" 3RDPARTY_FREETYPE_LIBRARY_TEST "${3RDPARTY_FREETYPE_LIBRARY}")
+    if (EXISTS "${3RDPARTY_FREETYPE_LIBRARY_TEST}")
+      set (3RDPARTY_FREETYPE_LIBRARY "${3RDPARTY_FREETYPE_LIBRARY_TEST}" CACHE FILEPATH "The path to freetype library" FORCE)
+    endif()
+  endif()
 endif()
 
 # the SECOND step in search for freetype library and header folders (additional search algorithms)
diff --git a/adm/cmake/jemalloc.cmake b/adm/cmake/jemalloc.cmake
index 752de06385..4642c54226 100644
--- a/adm/cmake/jemalloc.cmake
+++ b/adm/cmake/jemalloc.cmake
@@ -68,7 +68,7 @@ endfunction()
 
 macro (SEARCH_JEMALLOC)
   # find static jemalloc lib
-  SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a")
+  SET(CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a" ".lib" ".a")
   if (WIN32)
     JEMALLOC_LIB_SEARCH ("jemalloc" "STATIC")
   elseif(NOT WIN32)
diff --git a/adm/cmake/occt_defs_flags.cmake b/adm/cmake/occt_defs_flags.cmake
index 8018cc4a0c..fe11da2ccd 100644
--- a/adm/cmake/occt_defs_flags.cmake
+++ b/adm/cmake/occt_defs_flags.cmake
@@ -193,6 +193,8 @@ if(MINGW)
   #set (CMAKE_SYSTEM_VERSION "6.1")
   # workaround bugs in mingw with vtable export
   set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--export-all-symbols")
+  set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wattributes")
+  set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wattributes")
 endif()
 if (CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE)
   # Optimize size of binaries