name: Build

on:
  push:
    branches: [ master ]
    paths-ignore:
      - 'Docs/**'
      - '**.md'
  pull_request:
    branches: [ master ]
    paths-ignore:
      - 'Docs/**'
      - '**.md'

env:
  EMSCRIPTEN_VERSION: 3.1.64
  UBUNTU_CLANG_VERSION: clang++-18
  UBUNTU_GCC_VERSION: g++-14

jobs:
  linux-clang:
    runs-on: ubuntu-24.04
    name: Linux Clang
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Release, Distribution]
            double_precision: [No, Yes]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Install Vulkan
      run: ${{github.workspace}}/Build/ubuntu24_install_vulkan_sdk.sh
    - name: Configure CMake
      working-directory: ${{github.workspace}}/Build
      run: ./cmake_linux_clang_gcc.sh ${{matrix.build_type}} ${{env.UBUNTU_CLANG_VERSION}} -DDOUBLE_PRECISION=${{matrix.double_precision}}
    - name: Build
      run: cmake --build ${{github.workspace}}/Build/Linux_${{matrix.build_type}} -j $(nproc)
    - name: Test
      working-directory: ${{github.workspace}}/Build/Linux_${{matrix.build_type}}
      run: ctest --output-on-failure --verbose

  linux_clang_tsan:
    runs-on: ubuntu-24.04
    name: Linux Clang Sanitizers
    strategy:
        fail-fast: false
        matrix:
            build_type: [ReleaseASAN, ReleaseUBSAN, ReleaseTSAN]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Configure CMake
      working-directory: ${{github.workspace}}/Build
      run: ./cmake_linux_clang_gcc.sh ${{matrix.build_type}} ${{env.UBUNTU_CLANG_VERSION}} -DTARGET_VIEWER=OFF -DTARGET_SAMPLES=OFF -DTARGET_HELLO_WORLD=OFF -DTARGET_UNIT_TESTS=ON -DTARGET_PERFORMANCE_TEST=ON
    - name: Build
      run: cmake --build ${{github.workspace}}/Build/Linux_${{matrix.build_type}} -j $(nproc)
    - name: Unit Tests
      working-directory: ${{github.workspace}}/Build/Linux_${{matrix.build_type}}
      run: ctest --output-on-failure --verbose
    - name: Test ConvexVsMesh
      working-directory: ${{github.workspace}}/Build/Linux_${{matrix.build_type}}
      run: ./PerformanceTest -q=LinearCast -t=max -s=ConvexVsMesh
    - name: Test Ragdoll
      working-directory: ${{github.workspace}}/Build/Linux_${{matrix.build_type}}
      run: ./PerformanceTest -q=LinearCast -t=max -s=Ragdoll

  linux-clang-so:
    runs-on: ubuntu-24.04
    name: Linux Clang Shared Library
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Release, Distribution]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Configure CMake
      working-directory: ${{github.workspace}}/Build
      run: ./cmake_linux_clang_gcc.sh ${{matrix.build_type}} ${{env.UBUNTU_CLANG_VERSION}} -DBUILD_SHARED_LIBS=YES
    - name: Build
      run: cmake --build ${{github.workspace}}/Build/Linux_${{matrix.build_type}} -j $(nproc)
    - name: Test
      working-directory: ${{github.workspace}}/Build/Linux_${{matrix.build_type}}
      run: ctest --output-on-failure --verbose

  linux-clang-32-bit:
    runs-on: ubuntu-24.04
    name: Linux Clang 32-bit
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Release, Distribution]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Update APT
      run: sudo apt update
    - name: Install G++-Multilib
      run: sudo apt -y install g++-multilib
    - name: Configure CMake
      working-directory: ${{github.workspace}}/Build
      run: ./cmake_linux_clang_gcc.sh ${{matrix.build_type}} ${{env.UBUNTU_CLANG_VERSION}} -DCMAKE_CXX_FLAGS=-m32 -DUSE_SSE4_1=OFF -DUSE_SSE4_2=OFF -DUSE_AVX=OFF -DUSE_AVX2=OFF -DUSE_AVX512=OFF -DUSE_LZCNT=OFF -DUSE_TZCNT=OFF -DUSE_F16C=OFF -DUSE_FMADD=OFF
    - name: Build
      run: cmake --build ${{github.workspace}}/Build/Linux_${{matrix.build_type}} -j $(nproc)
    - name: Test
      working-directory: ${{github.workspace}}/Build/Linux_${{matrix.build_type}}
      run: ctest --output-on-failure --verbose

  linux-clang-use-std-vector:
    runs-on: ubuntu-24.04
    name: Linux Clang using std::vector
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, ReleaseASAN]
            double_precision: [Yes]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Configure CMake
      working-directory: ${{github.workspace}}/Build
      run: ./cmake_linux_clang_gcc.sh ${{matrix.build_type}} ${{env.UBUNTU_CLANG_VERSION}} -DDOUBLE_PRECISION=${{matrix.double_precision}} -DUSE_STD_VECTOR=ON
    - name: Build
      run: cmake --build ${{github.workspace}}/Build/Linux_${{matrix.build_type}} -j $(nproc)
    - name: Test
      working-directory: ${{github.workspace}}/Build/Linux_${{matrix.build_type}}
      run: ctest --output-on-failure --verbose

  linux-gcc:
    runs-on: ubuntu-24.04
    name: Linux GCC
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Release, Distribution]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Install Vulkan
      run: ${{github.workspace}}/Build/ubuntu24_install_vulkan_sdk.sh
    - name: Configure CMake
      working-directory: ${{github.workspace}}/Build
      run: ./cmake_linux_clang_gcc.sh ${{matrix.build_type}} ${{env.UBUNTU_GCC_VERSION}}
    - name: Build
      run: cmake --build ${{github.workspace}}/Build/Linux_${{matrix.build_type}} -j $(nproc)
    - name: Test
      working-directory: ${{github.workspace}}/Build/Linux_${{matrix.build_type}}
      run: ctest --output-on-failure --verbose

  linux-gcc-so:
    runs-on: ubuntu-24.04
    name: Linux GCC Shared Library
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Release, Distribution]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Configure CMake
      working-directory: ${{github.workspace}}/Build
      run: ./cmake_linux_clang_gcc.sh ${{matrix.build_type}} ${{env.UBUNTU_GCC_VERSION}} -DBUILD_SHARED_LIBS=Yes
    - name: Build
      run: cmake --build ${{github.workspace}}/Build/Linux_${{matrix.build_type}} -j $(nproc)
    - name: Test
      working-directory: ${{github.workspace}}/Build/Linux_${{matrix.build_type}}
      run: ctest --output-on-failure --verbose

  msys2_mingw_gcc:
    runs-on: windows-latest
    defaults:
      run:
        shell: msys2 {0}
    name: MSYS2 MinGW GCC
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Release]
            shared_lib: [No, Yes]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Setup MSYS2
      uses: msys2/setup-msys2@v2
      with:
        msystem: mingw64
        install: mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake
        update: true
    - name: Configure CMake
      working-directory: ${{github.workspace}}/Build
      run: ./cmake_linux_mingw.sh ${{matrix.build_type}} -DBUILD_SHARED_LIBS=${{matrix.shared_lib}}
    - name: Build
      run: cmake --build Build/MinGW_${{matrix.build_type}} -j $(nproc)
    - name: Test
      working-directory: Build/MinGW_${{matrix.build_type}}
      run: ctest --output-on-failure --verbose
      
  msvc_cl:
    runs-on: windows-latest
    name: Visual Studio CL
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Release, Distribution]
            double_precision: [No, Yes]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Add msbuild to PATH
      uses: microsoft/setup-msbuild@v2
    - name: Configure CMake
      run: cmake -B ${{github.workspace}}/Build/VS2022_CL -G "Visual Studio 17 2022" -A x64 Build -DDOUBLE_PRECISION=${{matrix.double_precision}}
    - name: Build
      run: msbuild Build\VS2022_CL\JoltPhysics.sln /property:Configuration=${{matrix.build_type}} -m
    - name: Test
      working-directory: ${{github.workspace}}/Build/VS2022_CL/${{matrix.build_type}}
      run: ./UnitTests.exe

  msvc_cl_no_object_stream:
    runs-on: windows-latest
    name: Visual Studio CL - No Object Stream
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Distribution]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Add msbuild to PATH
      uses: microsoft/setup-msbuild@v2
    - name: Configure CMake
      run: cmake -B ${{github.workspace}}/Build/VS2022_CL -G "Visual Studio 17 2022" -A x64 Build -DENABLE_OBJECT_STREAM=NO
    - name: Build
      run: msbuild Build\VS2022_CL\JoltPhysics.sln /property:Configuration=${{matrix.build_type}} -m
    - name: Test
      working-directory: ${{github.workspace}}/Build/VS2022_CL/${{matrix.build_type}}
      run: ./UnitTests.exe

  msvc_cl_dll:
    runs-on: windows-latest
    name: Visual Studio CL Shared Library
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Release, Distribution]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Add msbuild to PATH
      uses: microsoft/setup-msbuild@v2
    - name: Configure CMake
      run: cmake -B ${{github.workspace}}/Build/VS2022_CL -G "Visual Studio 17 2022" -A x64 Build -DBUILD_SHARED_LIBS=Yes
    - name: Build
      run: msbuild Build\VS2022_CL\JoltPhysics.sln /property:Configuration=${{matrix.build_type}} -m
    - name: Test
      working-directory: ${{github.workspace}}/Build/VS2022_CL/${{matrix.build_type}}
      run: ./UnitTests.exe

  msvc_cl_32_bit:
    runs-on: windows-latest
    name: Visual Studio CL 32-bit
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Release]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Add msbuild to PATH
      uses: microsoft/setup-msbuild@v2
    - name: Configure CMake
      run: cmake -B ${{github.workspace}}/Build/VS2022_CL_32_BIT -G "Visual Studio 17 2022" -A Win32 -DUSE_SSE4_1=OFF -DUSE_SSE4_2=OFF -DUSE_AVX=OFF -DUSE_AVX2=OFF -DUSE_AVX512=OFF -DUSE_LZCNT=OFF -DUSE_TZCNT=OFF -DUSE_F16C=OFF -DUSE_FMADD=OFF Build
    - name: Build
      run: msbuild Build\VS2022_CL_32_BIT\JoltPhysics.sln /property:Configuration=${{matrix.build_type}} -m
    - name: Test
      working-directory: ${{github.workspace}}/Build/VS2022_CL_32_BIT/${{matrix.build_type}}
      run: ./UnitTests.exe

  msvc_cl_arm:
    runs-on: windows-latest
    name: Visual Studio CL ARM
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Release]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Add msbuild to PATH
      uses: microsoft/setup-msbuild@v2
    - name: Configure CMake
      run: cmake -B ${{github.workspace}}/Build/VS2022_CL_ARM -G "Visual Studio 17 2022" -A ARM64 Build
    - name: Build
      run: msbuild Build\VS2022_CL_ARM\JoltPhysics.sln /property:Configuration=${{matrix.build_type}} -m

  msvc_cl_arm_32_bit:
    runs-on: windows-latest
    name: Visual Studio CL ARM 32-bit
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Release]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Add msbuild to PATH
      uses: microsoft/setup-msbuild@v2
    - name: Configure CMake
      # Windows 11 SDK 10.0.22621.0 is the last SDK to support 32-bit ARM, in the future if the github image no longer includes it, it can be installed with:
      # Start-Process -wait -FilePath "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe" -ArgumentList "modify", "--installPath", """C:\Program Files\Microsoft Visual Studio\2022\Enterprise""", "--quiet", "--norestart", "--nocache", "--add", "Microsoft.VisualStudio.Component.Windows11SDK.22621" -Verb RunAs
      run: cmake -B ${{github.workspace}}/Build/VS2022_CL_ARM_32_BIT -G "Visual Studio 17 2022" -A ARM -DCMAKE_SYSTEM_VERSION="10.0.22621.0" -DCMAKE_CXX_COMPILER_WORKS=1 Build 
    - name: Build
      run: msbuild Build\VS2022_CL_ARM_32_BIT\JoltPhysics.sln /property:Configuration=${{matrix.build_type}} -m

  msvc_clang:
    runs-on: windows-latest
    name: Visual Studio Clang
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Release, Distribution]
            double_precision: [No, Yes]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Add msbuild to PATH
      uses: microsoft/setup-msbuild@v2
    - name: Configure CMake
      run: cmake -B ${{github.workspace}}/Build/VS2022_Clang -G "Visual Studio 17 2022" -A x64 -T ClangCL Build -DDOUBLE_PRECISION=${{matrix.double_precision}}
    - name: Build
      run: msbuild Build\VS2022_Clang\JoltPhysics.sln /property:Configuration=${{matrix.build_type}} -m
    - name: Test
      working-directory: ${{github.workspace}}/Build/VS2022_Clang/${{matrix.build_type}}
      run: ./UnitTests.exe

  macos:
    runs-on: macos-latest
    name: macOS
    strategy:
        fail-fast: false
        matrix:
            build_type: [Debug, Release, Distribution]

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Configure CMake
      run: cmake -B ${{github.workspace}}/Build/MacOS_${{matrix.build_type}} -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DCMAKE_CXX_COMPILER=clang++ Build
    - name: Build
      run: cmake --build ${{github.workspace}}/Build/MacOS_${{matrix.build_type}} -j $(nproc)
    - name: Test
      working-directory: ${{github.workspace}}/Build/MacOS_${{matrix.build_type}}
      run: ctest --output-on-failure --verbose

  android:
    runs-on: ubuntu-latest
    name: Android
    strategy:
        fail-fast: false

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Setup Java
      uses: actions/setup-java@v4
      with:
        distribution: 'temurin'
        java-version: '17'
    - name: Gradle Build
      working-directory: ${{github.workspace}}/Build/Android
      run: ./gradlew build --no-daemon

  ios:
    runs-on: macos-latest
    name: iOS
    strategy:
        fail-fast: false

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Configure CMake
      run: cmake -B ${{github.workspace}}/Build/XCode_iOS -DTARGET_HELLO_WORLD=OFF -DTARGET_PERFORMANCE_TEST=OFF -DCMAKE_SYSTEM_NAME=iOS -GXcode Build
    - name: Build
      run: cmake --build ${{github.workspace}}/Build/XCode_iOS -- -sdk iphonesimulator -arch x86_64

  emscripten:
    runs-on: ubuntu-latest
    name: Emscripten

    steps:
    - name: Checkout Code
      uses: actions/checkout@v4
    - name: Setup emsdk
      uses: mymindstorm/setup-emsdk@v14
      with:
        version: ${{env.EMSCRIPTEN_VERSION}}
    - name: Verify emsdk
      run: emcc -v
    - name: Setup Node.js 18.x
      uses: actions/setup-node@v4
      with:
        node-version: 18.x
    - name: Configure CMake
      working-directory: ${{github.workspace}}/Build
      run: ./cmake_linux_emscripten.sh Distribution -DTARGET_HELLO_WORLD=OFF -DTARGET_PERFORMANCE_TEST=OFF
    - name: Build
      run: cmake --build ${{github.workspace}}/Build/WASM_Distribution -j $(nproc)      
    - name: Test
      working-directory: ${{github.workspace}}/Build/WASM_Distribution
      run: node UnitTests.js
