name: Shared build workflow

on:
  workflow_call:
    inputs:
      environment:
        required: true
        type: string

env:
  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
  BUILD_TYPE: RelWithDebInfo
  RELEASE_STAGE: ${{ vars.RELEASE_STAGE || 'unstable' }}

jobs:
  ##########################
  #
  # Linux
  # Ubuntu 22.04
  #
  # Using this version instead of 24.04 to use a lower GLIBC version (2.34)
  ##########################
  build-platform-linux:
    strategy:
      matrix:
        architecture: [
          {name: 'amd64',    triple: 'x86_64-linux-gnu'},
          {name: 'i686',     triple: 'i686-linux-gnu'},
          {name: 'arm64',    triple: 'aarch64-linux-gnu'},
          {name: 'armhf',    triple: 'arm-linux-gnueabihf'},
          {name: 'powerpc',  triple: 'powerpc-linux-gnu'},
          {name: 'ppc64',    triple: 'powerpc64-linux-gnu'},
          {name: 'ppc64el',  triple: 'powerpc64le-linux-gnu'}
        ]

    name: "Building for platform linux-${{matrix.architecture.name}}"
    runs-on: "ubuntu-22.04"
    environment: ${{ inputs.environment }}

    steps:
    ###
    # Packages
    ###

    - uses: awalsh128/cache-apt-pkgs-action@latest
      name: Install required packages
      with:
        packages: flex bison ninja-build cmake clang libpulse-dev portaudio19-dev libasound2-dev libjack-dev libpipewire-0.3-dev qtbase5-dev libdbus-1-dev
        version: "0.1"

    - uses: awalsh128/cache-apt-pkgs-action@latest
      name: Install required cross-platform packages (${{ matrix.architecture.triple }})
      if: matrix.architecture.name != 'amd64'
      with:
        packages: gcc-12-${{ matrix.architecture.triple }} g++-12-${{ matrix.architecture.triple }}
        version: "0.1"

    - name: Settings
      working-directory: ${{github.workspace}}
      run: |
        echo "CMAKE_GENERATOR=Ninja Multi-Config" >> $GITHUB_ENV
        echo "CC=clang" >> $GITHUB_ENV
        echo "CXX=clang++" >> $GITHUB_ENV
        echo "CFLAGS='--target=${{ matrix.architecture.triple }}'" >> $GITHUB_ENV
        echo "CXXFLAGS='--target=${{ matrix.architecture.triple }}'" >> $GITHUB_ENV

    ###
    # SDL
    ###

    # Setup SDL
    - name: Set up SDL
      id: sdl
      uses: libsdl-org/setup-sdl@main
      with:
        version: 2-latest
        build-type: Release
        # Workaround for when changing the runner OS version
        cmake-arguments: "-DCACHE_OS_VERSION=Ubuntu_22.04"

    ###
    # OpenAL
    ###

    # soft-oal setup
    - name: Checkout soft-oal
      uses: actions/checkout@v4
      with:
        repository: 'kcat/openal-soft'
        path: 'thirdparties/soft-oal'
        ref: '1.24.1'

    - name: Configure and install soft-oal
      working-directory: ${{github.workspace}}/thirdparties/soft-oal
      run: |
        cmake -B ./build \
        -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/soft-oal/install'
        cmake --build ./build --config Release --parallel
        cmake --install ./build --config Release

    ###
    # Project
    ###

    - uses: actions/checkout@v4
      with:
        path: 'source'

    - name: CMake Settings
      run: |
        echo "CMAKE_PARAM=--log-level=VERBOSE \
        -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' \
        -DOPENAL_LIBRARY='${{github.workspace}}/thirdparties/soft-oal' \
        -DOPENAL_INCLUDE_DIR='${{github.workspace}}/thirdparties/soft-oal/include' \
        -DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }} \
        -DPRODUCT_VERSION_STAGE='${{ env.RELEASE_STAGE }}'" >> $GITHUB_ENV

    - name: Configure CMake
      working-directory: ${{github.workspace}}
      run: |
        cmake -B ./build ${{ env.CMAKE_PARAM }} ./source

    - name: Build
      working-directory: ${{github.workspace}}
      run: |
        cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel

    - name: Test
      working-directory: ${{github.workspace}}
      # Execute tests defined by the CMake configuration.
      # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
      run: |
        cd "${{github.workspace}}/build"
        ctest -C ${{env.BUILD_TYPE}}

    - name: Install
      working-directory: ${{github.workspace}}
      # Install to the directory defined in CMAKE_INSTALL_PREFIX
      run: |
        cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
        # Copy libraries
        mkdir ${{github.workspace}}/package
        cp -l ${{steps.sdl.outputs.prefix}}/lib/libSDL2-2.0.so.0 '${{github.workspace}}/package/'
        cp -l ${{github.workspace}}/thirdparties/soft-oal/install/lib/libopenal.so.1 '${{github.workspace}}/package/'
        if [ -d ${{github.workspace}}/install/bin ]; then cp -r ${{github.workspace}}/install/bin/openmohaa/. '${{github.workspace}}/package'; fi
        if [ -d ${{github.workspace}}/install/lib ]; then cp -r ${{github.workspace}}/install/lib/openmohaa/. '${{github.workspace}}/package'; fi

    ###
    # Artifacts
    ###

    - uses: actions/upload-artifact@v4
      with:
        name: out-linux-${{matrix.architecture.name}}
        if-no-files-found: error
        path:
          ${{github.workspace}}/package

  ##########################
  #
  # Microsoft Windows
  # Windows Server 2022
  #
  ##########################
  build-platform-windows:
    strategy:
      matrix:
        architecture: [
          {name: 'x64',   config: 'x64',    toolset: 'x64' },
          {name: 'x86',   config: 'Win32',  toolset: 'x64_x86' },
          {name: 'arm64', config: 'ARM64',  toolset: 'x64_arm64' }
        ]

    name: "Building for platform windows-${{matrix.architecture.name}}"
    runs-on: "windows-2022"
    environment: ${{ inputs.environment }}

    steps:
    ###
    # Packages
    ###

    #
    # Commented out for now, chocolatey servers started complaining about too many requests
    #
    #- name: Install required packages
    #  run: |
    #    choco install -y ninja

    - name: Install required packages
      run: |
        $DownloadPath="$($env:USERPROFILE)\Downloads"
        Invoke-WebRequest "https://github.com/ninja-build/ninja/releases/download/v1.12.1/ninja-win.zip" -OutFile "$DownloadPath\ninja-win.zip"
        Expand-Archive -Path "$DownloadPath\ninja-win.zip" -DestinationPath "$($env:PROGRAMFILES)\ninja"
        echo "$($env:PROGRAMFILES)\ninja" >> $GITHUB_PATH

    - name: Install Flex/Bison
      working-directory: ${{github.workspace}}
      run: |
        mkdir thirdparties && cd thirdparties
        git clone --depth 1 --single-branch --branch v2.5.25 https://github.com/lexxmark/winflexbison.git
        cmake -B winflexbison-build -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/winflexbison-install' ./winflexbison
        cmake --build winflexbison-build --config Release --parallel
        cmake --install winflexbison-build --config Release

    - name: Settings
      working-directory: ${{github.workspace}}
      run: |
        echo "CMAKE_GENERATOR=Ninja Multi-Config" >> $env:GITHUB_ENV
        echo "CC=cl.exe" >> $env:GITHUB_ENV
        echo "CXX=cl.exe" >> $env:GITHUB_ENV
        pushd "$($env:PROGRAMFILES)\Microsoft Visual Studio\*\*\VC\Auxiliary\Build"
        cmd /c "vcvarsall.bat ${{ matrix.architecture.toolset }} & set" | ForEach-Object {
          if ($_ -match "=") {
            # Split into key=value
            $var = $_.split("=", 2);
            echo "$($var[0])=$($var[1])" >> $env:GITHUB_ENV
          }
        }
        popd

    ###
    # SDL
    ###

    # Setup SDL
    - name: Set up SDL
      id: sdl
      uses: libsdl-org/setup-sdl@main
      with:
        version: 2-latest
        build-type: Release
        cmake-arguments: ""

    ###
    # OpenAL
    ###

    # soft-oal setup
    - name: Checkout soft-oal
      uses: actions/checkout@v4
      with:
        repository: 'kcat/openal-soft'
        path: 'thirdparties/soft-oal'
        ref: '1.24.1'

    # soft-oal build
    # Statically link the CRT runtime into OAL as a workaround to prevent crashes
    - name: Configure and install soft-oal
      working-directory: ${{github.workspace}}/thirdparties/soft-oal
      run: |
        cmake -B ./build `
        -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/soft-oal/install' `
        -DALSOFT_BUILD_ROUTER=OFF `
        -DALSOFT_REQUIRE_WINMM=ON `
        -DALSOFT_REQUIRE_DSOUND=ON `
        -DALSOFT_REQUIRE_WASAPI=ON `
        -DCMAKE_C_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" `
        -DCMAKE_CXX_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" `
        -DCMAKE_C_FLAGS_MINSIZEREL="/MT /O2 /Ob2 /DNDEBUG" `
        -DCMAKE_CXX_FLAGS_MINSIZEREL="/MT /O1 /Ob1 /DNDEBUG" `
        -DCMAKE_C_FLAGS_RELWITHDEBINFO="/MT /Zi /O2 /Ob1 /DNDEBUG" `
        -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="/MT /Zi /O2 /Ob1 /DNDEBUG"
        cmake --build ./build --config Release --parallel
        cmake --install ./build --config Release
        # Unfortunately soft-oal produces a binary called OpenAL32 even in 64-bit
        if (("x64", "ARM64") -icontains "${{ matrix.architecture.config }}") { Rename-Item -Path '.\install\bin\OpenAL32.dll' -NewName 'OpenAL64.dll' }

    ###
    # Project
    ###

    - uses: actions/checkout@v4
      with:
        path: 'source'

    - name: CMake Settings
      run: |
        echo "CMAKE_PARAM= `
        --log-level=VERBOSE `
        -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' `
        -DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }} `
        -DBISON_EXECUTABLE='${{github.workspace}}/thirdparties/winflexbison-install/win_bison.exe' `
        -DOPENAL_LIBRARY='${{github.workspace}}/thirdparties/soft-oal' `
        -DOPENAL_INCLUDE_DIR='${{github.workspace}}/thirdparties/soft-oal/include' `
        -DFLEX_EXECUTABLE='${{github.workspace}}/thirdparties/winflexbison-install/win_flex.exe' `
        -DPRODUCT_VERSION_STAGE='${{ env.RELEASE_STAGE }}'".Replace("`r", "").Replace("`n", "") >> $env:GITHUB_ENV

    - name: Configure CMake
      working-directory: ${{github.workspace}}
      run: |
        cmake -B ./build ${{ env.CMAKE_PARAM }} ./source

    - name: Build
      working-directory: ${{github.workspace}}
      run: |
        cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel

    - name: Test
      working-directory: ${{github.workspace}}
      # Execute tests defined by the CMake configuration.
      # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
      run: |
        cd "${{github.workspace}}/build"
        ctest -C ${{env.BUILD_TYPE}}

    - name: Install
      working-directory: ${{github.workspace}}
      # Install to the directory defined in CMAKE_INSTALL_PREFIX
      run: |
        cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
        New-Item -ItemType Directory '${{github.workspace}}/package'
        Copy-Item '${{steps.sdl.outputs.prefix}}/bin/*.dll' -Destination '${{github.workspace}}/package'
        Copy-Item '${{github.workspace}}/thirdparties/soft-oal/install/bin/*.dll' -Destination '${{github.workspace}}/package'
        if (Test-Path ${{github.workspace}}/install/bin) { Copy-Item '${{github.workspace}}/install/bin/*' -Include '*.dll','*.exe','*.pdb' -Destination '${{github.workspace}}/package' }
        if (Test-Path ${{github.workspace}}/install/lib) { Copy-Item '${{github.workspace}}/install/lib/*' -Include '*.dll','*.exe','*.pdb' -Destination '${{github.workspace}}/package' }

    ###
    # Artifact
    ###

    - uses: actions/upload-artifact@v4
      with:
        name: out-windows-${{matrix.architecture.name}}
        if-no-files-found: error
        path: |
          ${{github.workspace}}/package
          !${{github.workspace}}/package/**/*.pdb

    - uses: actions/upload-artifact@v4
      with:
        name: out-windows-${{matrix.architecture.name}}-pdb
        if-no-files-found: error
        path: |
          ${{github.workspace}}/package

  ##########################
  #
  # Apple macOS
  # macOS 14
  #
  # This version is used as the OS, as older versions are slower.
  ##########################
  build-platform-macos:
    strategy:
      matrix:
        architecture: [
          #{name: 'x86_64',   triple: 'x86_64-apple-macos10.8'},
          #{name: 'arm64',    triple: 'arm64-apple-macos11'}
          #{name: 'x86_64',    build_name: 'x86_64'},
          #{name: 'arm64',     build_name: 'arm64'},
          # Compile into an universal binary
          {name: 'multiarch(arm64-x86_64)', build_name: 'arm64;x86_64' }
        ]

    name: "Building for platform macos-${{matrix.architecture.name}}"
    runs-on: "macos-15"
    environment: ${{inputs.environment}}

    steps:
    ###
    # Packages
    ###

    # Install required packages
    # Paths on x86_64 and ARM64 are different for homebrew
    - name: Install required packages
      run: |
        brew update && brew install git flex bison ninja cmake llvm ninja

    - name: Settings
      working-directory: ${{github.workspace}}
      run: |
        echo "CMAKE_GENERATOR=Ninja Multi-Config" >> $GITHUB_ENV
        echo "CC=clang" >> $GITHUB_ENV
        echo "CXX=clang++" >> $GITHUB_ENV
        echo "MACOSX_DEPLOYMENT_TARGET=10.15" >> $GITHUB_ENV

    ###
    # SDL
    ###

    # Setup SDL
    - name: Set up SDL
      id: sdl
      uses: libsdl-org/setup-sdl@main
      with:
        version: 2-latest
        build-type: Release
        cmake-arguments: "-DCMAKE_OSX_ARCHITECTURES='${{ matrix.architecture.build_name }}'
          -DCMAKE_VERBOSE_MAKEFILE=on"
    ###
    # OpenAL
    ###

    # soft-oal setup
    # Use GCC instead of Clang because of missing SSE intrinsics
    # It also doesn't enable altivec support on PowerPC by default
    - name: Checkout soft-oal
      uses: actions/checkout@v4
      with:
        repository: 'kcat/openal-soft'
        path: 'thirdparties/soft-oal'
        ref: '1.24.1'

    - name: Configure and install soft-oal
      working-directory: ${{github.workspace}}/thirdparties/soft-oal
      run: |
        cmake -B ./build \
        -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/soft-oal/install' \
        -DCMAKE_OSX_ARCHITECTURES='${{ matrix.architecture.build_name }}' \
        -DCMAKE_VERBOSE_MAKEFILE=on
        cmake --build ./build --config Release --parallel
        cmake --install ./build --config Release

    ###
    # Project
    ###

    - uses: actions/checkout@v4
      with:
        path: 'source'

    - name: CMake Settings
      run: |
        echo "CMAKE_PARAM=--log-level=VERBOSE \
        -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' \
        -DCMAKE_VERBOSE_MAKEFILE=on \
        -DCMAKE_OSX_ARCHITECTURES='${{ matrix.architecture.build_name }}' \
        -DOPENAL_LIBRARY='${{github.workspace}}/thirdparties/soft-oal/install' \
        -DOPENAL_INCLUDE_DIR='${{github.workspace}}/thirdparties/soft-oal/install/include/AL' \
        -DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }} \
        -DPRODUCT_VERSION_STAGE='${{ env.RELEASE_STAGE }}'" >> $GITHUB_ENV

    - name: Configure CMake
      working-directory: ${{github.workspace}}
      run: |
        cmake -B ./build ${{ env.CMAKE_PARAM }} ./source

    - name: Build
      working-directory: ${{github.workspace}}
      run: |
        cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel

    - name: Test
      working-directory: ${{github.workspace}}
      # Execute tests defined by the CMake configuration.
      # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
      run: |
        cd "${{github.workspace}}/build"
        ctest -C ${{env.BUILD_TYPE}}

    - name: Install
      working-directory: ${{github.workspace}}
      # Install to the directory defined in CMAKE_INSTALL_PREFIX
      run: |
        cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
        # Create hard-link and copy symbolic links
        mkdir ${{github.workspace}}/package
        cp -l ${{steps.sdl.outputs.prefix}}/lib/libSDL2-2.0.0.dylib '${{github.workspace}}/package/'
        cp -l ${{github.workspace}}/thirdparties/soft-oal/install/lib/libopenal.1.dylib '${{github.workspace}}/package/'
        if [ -d ${{github.workspace}}/install/bin ]; then cp -r ${{github.workspace}}/install/bin/openmohaa/. '${{github.workspace}}/package'; fi
        if [ -d ${{github.workspace}}/install/lib ]; then cp -r ${{github.workspace}}/install/lib/openmohaa/. '${{github.workspace}}/package'; fi

    ###
    # Artifacts
    ###

    - uses: actions/upload-artifact@v4
      with:
        name: out-macos-${{matrix.architecture.name}}
        if-no-files-found: error
        path:
          ${{github.workspace}}/package
