# Copyright (c) 2021-2024 Valve Corporation
# Copyright (c) 2021-2024 LunarG, Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author: Lenny Komow <lenny@lunarg.com>
# Author: Charles Giessen <charles@lunarg.com>

name: CI Build

# https://docs.github.com/en/actions/using-jobs/using-concurrency
concurrency:
  # github.head_ref is only defined on pull_request
  # Fallback to the run ID, which is guaranteed to be both unique and defined for the run.
  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id  }}
  cancel-in-progress: true

on:
  push:
  pull_request:
    branches:
    - main

permissions: read-all

jobs:
    linux:
        needs: codegen
        runs-on: ${{matrix.os}}
        strategy:
            matrix:
                compiler: [ {cc: gcc, cxx: g++}, {cc: clang, cxx: clang++} ]
                config: [ Debug, Release ]
                os: [ ubuntu-22.04, ubuntu-24.04 ]
        steps:
            - uses: actions/checkout@v4
            - uses: actions/setup-python@v5
              with:
                python-version: '3.11'
            - name: Test CMake min
              # NOTE: The main users who benefit from an older CMake version
              # are linux users stuck on older LTS releases. It's idiomatic best
              # practice to try and support them so they don't have to install
              # the CMake tarball. Ideally the minimum we use matches what the default
              # package provided by Ubuntu via APT.
              if: ${{ matrix.os == 'ubuntu-22.04' }}
              uses: lukka/get-cmake@latest
              with:
                cmakeVersion: 3.22.1
            - run: sudo apt update
            - run: sudo apt install --yes --no-install-recommends libwayland-dev libxrandr-dev
            - run: |
                cmake -S. -B build \
                -D CMAKE_BUILD_TYPE=${{ matrix.config }} \
                -D BUILD_TESTS=ON \
                -D UPDATE_DEPS=ON \
                -D LOADER_ENABLE_ADDRESS_SANITIZER=ON \
                -D BUILD_WERROR=ON \
                -D CMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} \
                -D CMAKE_C_COMPILER=${{ matrix.compiler.cc }}
            - run: cmake --build build
            - run: ctest --parallel --output-on-failure --test-dir build/
            - run: cmake --install build --prefix /tmp

    codegen:
      runs-on: ubuntu-latest
      steps:
        - uses: actions/checkout@v4
        - run: scripts/update_deps.py --dir ext --no-build
        - run: scripts/generate_source.py --verify ext/Vulkan-Headers/registry/

    linux-no-asm:
        needs: codegen
        runs-on: ubuntu-24.04
        steps:
            - uses: actions/checkout@v4
            - run: sudo apt update
            - run: sudo apt install --yes --no-install-recommends libwayland-dev libxrandr-dev
            - run: |
                cmake -S. -B build \
                -D CMAKE_BUILD_TYPE=Release \
                -D BUILD_TESTS=ON \
                -D UPDATE_DEPS=ON \
                -D BUILD_WERROR=ON \
                -D USE_GAS=OFF \
                -D CMAKE_C_COMPILER=clang \
                -D CMAKE_CXX_COMPILER=clang++
            - run: cmake --build build
            - run: cmake --install build --prefix /tmp
            - run: ctest --parallel --output-on-failure -E UnknownFunction --test-dir build/

    linux-32:
        needs: codegen
        runs-on: ubuntu-24.04
        strategy:
            matrix:
                config: [ Debug, Release ]
        steps:
            - uses: actions/checkout@v4
            - uses: actions/setup-python@v5
              with:
                python-version: '3.11'
            - uses: lukka/get-cmake@latest
              with:
                cmakeVersion: 3.22.1
            - name: Enable 32 bit
              run: sudo dpkg --add-architecture i386
            - run: sudo apt-get update
            - run: |
                sudo apt install --yes --no-install-recommends \
                gcc-multilib g++-multilib libc6:i386 libc6-dev-i386 libgcc-s1:i386 \
                libwayland-dev:i386 libxrandr-dev:i386
            - run: |
                cmake -S. -B build \
                -D CMAKE_BUILD_TYPE=${{matrix.config}} \
                -D BUILD_TESTS=ON \
                -D UPDATE_DEPS=ON \
                -D BUILD_WERROR=ON \
                -D SYSCONFDIR=/etc/not_vulkan \
                -D CMAKE_CXX_FLAGS=-m32 \
                -D CMAKE_C_FLAGS=-m32 \
                -G Ninja
              env:
                # https://gitlab.kitware.com/cmake/cmake/-/issues/25317
                PKG_CONFIG_PATH: /usr/lib/i386-linux-gnu/pkgconfig
            - run: cmake --build build
            - run: cmake --install build --prefix /tmp
            - run: ctest --parallel --output-on-failure --test-dir build/

    linux-32-no-asm:
        needs: codegen
        runs-on: ubuntu-24.04
        steps:
            - uses: actions/checkout@v4
            - uses: actions/setup-python@v5
              with:
                python-version: '3.11'
            - uses: lukka/get-cmake@latest
              with:
                cmakeVersion: 3.22.1
            - name: Enable 32 bit
              run: sudo dpkg --add-architecture i386
            - run: sudo apt-get update
            - run: |
                sudo apt install --yes --no-install-recommends \
                gcc-multilib g++-multilib libc6:i386 libc6-dev-i386 libgcc-s1:i386 \
                libwayland-dev:i386 libxrandr-dev:i386
            - run: |
                cmake -S. -B build \
                -D CMAKE_BUILD_TYPE=Release \
                -D BUILD_TESTS=ON \
                -D UPDATE_DEPS=ON \
                -D BUILD_WERROR=ON \
                -D USE_GAS=OFF \
                -D CMAKE_CXX_FLAGS=-m32 \
                -D CMAKE_C_FLAGS=-m32 \
                -G Ninja
              env:
                # https://gitlab.kitware.com/cmake/cmake/-/issues/25317
                PKG_CONFIG_PATH: /usr/lib/i386-linux-gnu/pkgconfig
            - run: cmake --build build
            - run: ctest --parallel --output-on-failure -E UnknownFunction --test-dir build/

    windows_vs:
        # windows is 2x expensive to run on GitHub machines, so only run if we know something else simple passed as well
        needs: linux-no-asm
        runs-on: windows-latest
        strategy:
            matrix:
                arch: [ Win32, x64 ]
                config: [ Debug, Release ]
        steps:
            - uses: actions/checkout@v4
            - run: |
                cmake -S. -B build `
                -D BUILD_TESTS=ON `
                -D UPDATE_DEPS=ON `
                -D CMAKE_BUILD_TYPE=${{matrix.config}} `
                -A ${{ matrix.arch }} `
                -D BUILD_WERROR=ON
            - run: cmake --build build/ --config ${{matrix.config}}
            - run: cmake --install build --prefix build/install --config ${{matrix.config}}
            - run: ctest --parallel --output-on-failure -C ${{matrix.config}} --test-dir build/

    windows_vs-no-asm:
        # windows is 2x expensive to run on GitHub machines, so only run if we know something else simple passed as well
        needs: linux-no-asm
        runs-on: windows-latest
        strategy:
            matrix:
                arch: [ Win32, x64 ]
        steps:
            - uses: actions/checkout@v4
            - run: |
                cmake -S. -B build `
                -D BUILD_TESTS=ON `
                -D UPDATE_DEPS=ON `
                -D USE_MASM=OFF `
                -D CMAKE_BUILD_TYPE=Release `
                -A ${{ matrix.arch }} `
                -D BUILD_WERROR=ON
            - run: cmake --build build/ --config Release
            - run: ctest --parallel --output-on-failure -C Release -E UnknownFunction --test-dir build/

    # Test both clang and clang-cl (Chromium project uses clang-cl)
    windows_clang:
      # windows is 2x expensive to run on GitHub machines, so only run if we know something else simple passed as well
      needs: linux-no-asm
      runs-on: windows-2022
      strategy:
        matrix:
            compiler: [ clang, clang-cl ]
            config: [ Debug, Release ]
      steps:
          - uses: actions/checkout@v4
          - uses: ilammy/msvc-dev-cmd@v1
          - run: |
              cmake -S. -B build `
              -D CMAKE_C_COMPILER=${{matrix.compiler}} `
              -D CMAKE_CXX_COMPILER=${{matrix.compiler}} `
              -D UPDATE_DEPS=ON `
              -D CMAKE_BUILD_TYPE=${{matrix.config}} `
              -D BUILD_WERROR=ON `
              -D BUILD_TESTS=ON `
              -G Ninja
          - run: cmake --build build/
          - run: ctest --parallel --output-on-failure --test-dir build/
          - run: cmake --install build --prefix build/install

    mac:
        # Mac is 10x expensive to run on GitHub machines, so only run if we know something else passed as well
        needs: windows_clang
        runs-on: macos-13
        strategy:
            matrix:
                config: [ Debug, Release ]
                static_build: [ APPLE_STATIC_LOADER=ON, APPLE_STATIC_LOADER=OFF ]
        steps:
            - uses: actions/checkout@v4
            - uses: actions/setup-python@v5
              with:
                python-version: '3.11'
            - run: |
                cmake -S. -B build \
                -D CMAKE_BUILD_TYPE=${{matrix.config}} \
                -D ${{matrix.static_build}} \
                -D BUILD_TESTS=ON \
                -D UPDATE_DEPS=ON \
                -D BUILD_WERROR=ON \
                -D LOADER_ENABLE_ADDRESS_SANITIZER=ON \
                -G Ninja
              env:
                # Prevents regression of KhronosGroup/Vulkan-Loader/issues/1332
                LDFLAGS: -Wl,-fatal_warnings
            - run: cmake --build build
            - run: cmake --install build --prefix /tmp
            - run: ctest --parallel --output-on-failure --test-dir build/

    apple-cross-compile:
      # Mac is 10x expensive to run on GitHub machines, so only run if we know something else passed as well
      needs: windows_clang
      name: ${{ matrix.CMAKE_SYSTEM_NAME }}
      runs-on: macos-13
      strategy:
          matrix:
            CMAKE_SYSTEM_NAME: [ iOS, tvOS ]
      steps:
          - uses: actions/checkout@v4
          - uses: actions/setup-python@v5
            with:
              python-version: '3.11'
          - run: |
              cmake -S . -B build \
              -D CMAKE_SYSTEM_NAME=${{ matrix.CMAKE_SYSTEM_NAME }} \
              "-D CMAKE_OSX_ARCHITECTURES=arm64;x86_64" \
              -D CMAKE_BUILD_TYPE=Debug \
              -D UPDATE_DEPS=ON \
              -D BUILD_WERROR=ON \
              -G Ninja
            env:
              LDFLAGS: -Wl,-fatal_warnings
          - run: cmake --build build
          - run: cmake --install build --prefix /tmp
          - name: Verify Universal Binary
            run: |
              vtool -show-build /tmp/lib/libvulkan.dylib | grep 'architecture x86_64'
              vtool -show-build /tmp/lib/libvulkan.dylib | grep 'architecture arm64'

    # Building a universal binary disables assembly automatically
    # Furthermore the Vulkan SDK ships universal binaries
    mac-univeral:
        # Mac is 10x expensive to run on GitHub machines, so only run if we know something else passed as well
        needs: windows_clang
        name: "Universal Binary Testing (STATIC ${{ matrix.static }}) w/ ${{ matrix.generator }}"
        runs-on: macos-latest
        strategy:
            matrix:
                static: [ 'ON', 'OFF' ]
                generator: [ Ninja, Xcode ]
        steps:
            - uses: actions/checkout@v4
            - uses: actions/setup-python@v5
              with:
                python-version: '3.11'
            - run: |
                cmake -S. -B build \
                -D CMAKE_BUILD_TYPE=Release \
                -D APPLE_STATIC_LOADER=${{matrix.static}} \
                "-D CMAKE_OSX_ARCHITECTURES=arm64;x86_64" \
                -D BUILD_TESTS=ON \
                -D UPDATE_DEPS=ON \
                -D BUILD_WERROR=ON \
                -G ${{ matrix.generator }}
              env:
                LDFLAGS: -Wl,-fatal_warnings
            - run: cmake --build build --config Release
            - run: ctest --parallel --output-on-failure --build-config Release -E UnknownFunction --test-dir build/
            - run: cmake --install build --config Release --prefix /tmp
            - name: Verify Universal Binary
              if: ${{ matrix.static == 'OFF' }}
              run: |
                vtool -show-build /tmp/lib/libvulkan.dylib | grep 'architecture x86_64'
                vtool -show-build /tmp/lib/libvulkan.dylib | grep 'architecture arm64'

    chromium:
      needs: codegen
      runs-on: ubuntu-latest
      steps:
        - uses: actions/checkout@v4
        - run: scripts/gn/gn.py

    mingw:
      # windows is 2x expensive to run on GitHub machines, so only run if we know something else simple passed as well
      if: false # Disabled due to issues with msys2 making CMake unable to find a working compiler
      needs: linux-no-asm
      runs-on: windows-2022
      defaults:
        run:
          shell: bash
      steps:
        - uses: actions/checkout@v4
        - uses: actions/setup-python@v5
          with:
            python-version: '3.11'
        - name: Setup uasm
          run: |
            C:/msys64/usr/bin/pacman -Sy --noconfirm --needed mingw-w64-x86_64-uasm
            printf '%s\n' 'C:/msys64/mingw64/bin' >> $GITHUB_PATH
        - name: UASM Check
          run: uasm -?
        - run: |
            cmake -S. -B build \
            -D UPDATE_DEPS=ON \
            -D CMAKE_BUILD_TYPE=Release \
            -D BUILD_WERROR=ON \
            -G Ninja
        - run: cmake --build build
        - run: cmake --install build --prefix /tmp

    mingw-use-gas:
      # windows is 2x expensive to run on GitHub machines, so only run if we know something else simple passed as well
      needs: linux-no-asm
      runs-on: windows-2022
      defaults:
        run:
          shell: bash
      steps:
        - uses: actions/checkout@v4
        - uses: actions/setup-python@v5
          with:
            python-version: '3.11'
        - run: |
            cmake -S. -B build \
            -D UPDATE_DEPS=ON \
            -D CMAKE_BUILD_TYPE=Release \
            -D BUILD_WERROR=ON \
            -D USE_GAS=ON \
            -G Ninja
        - run: cmake --build build
        - run: cmake --install build --prefix /tmp

    mingw-no-asm:
      # windows is 2x expensive to run on GitHub machines, so only run if we know something else simple passed as well
      needs: linux-no-asm
      runs-on: windows-2022
      defaults:
        run:
          shell: bash
      steps:
        - uses: actions/checkout@v4
        - uses: actions/setup-python@v5
          with:
            python-version: '3.11'
        # Make sure this doesn't fail even without explicitly setting '-D USE_MASM=OFF' and without uasm
        - run: |
            cmake -S. -B build \
            -D UPDATE_DEPS=ON \
            -D CMAKE_BUILD_TYPE=Release \
            -D BUILD_WERROR=ON \
            -G Ninja
        - run: cmake --build build
        - run: cmake --install build --prefix /tmp

    mingw-no-asm-explicit:
      # windows is 2x expensive to run on GitHub machines, so only run if we know something else simple passed as well
      needs: linux-no-asm
      runs-on: windows-2022
      defaults:
        run:
          shell: bash
      steps:
        - uses: actions/checkout@v4
        - run: |
            cmake -S. -B build \
            -D UPDATE_DEPS=ON \
            -D CMAKE_BUILD_TYPE=Release \
            -D BUILD_WERROR=ON \
            -D USE_MASM=OFF \
            -G Ninja
        - run: cmake --build build
        - run: cmake --install build --prefix /tmp
