# Copyright 2022-2026 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause

name: Reusable LLVM rebuild

permissions: read-all

on:
  workflow_call:
    inputs:
      version:
        description: Version to build in major.minor format For example '18.1'.
        required: true
        type: string
      full_version:
        description: Version to build in major.minor.patch format. For example '18.1.8'.
        required: true
        type: string
      lto:
        description: Build LTO-enabled LLVM toolchain ('ON' or 'OFF').
        required: false # Not required since there is a default value
        type: string
        default: 'OFF'
      asserts:
        description: Build LLVM with assertions ('ON' or 'OFF').
        required: false # Not required since there is a default value
        type: string
        default: 'ON'
      # arch inputs is used only for linux-build jobs, macos and win just ignore it and skip aarch64 builds
      arch:
        description: Target architecture ('x86' or 'aarch64').
        required: false # Not required since there is a default value
        type: string
        default: 'x86'
      ubuntu:
        description: Version of Ubuntu Dockerfile to use. For example '22.04'.
        required: true
        type: string
      win_sdk:
        description: Win SDK version string. For example, '10.0.18362.0'.
        required: true
        type: string
      vs_version:
        description: Visual Studio version ('vs2019' or 'vs2022').
        required: false
        type: string
        default: 'vs2022'
  workflow_dispatch:
    inputs:
      version:
        description: Version to build in major.minor format For example '18.1'.
        required: true
        type: string
        default: '18.1'
      full_version:
        description: Version to build in major.minor.patch format. For example '18.1.8'.
        required: true
        type: string
        default: '18.1.8'
      lto:
        description: Build LTO-enabled LLVM toolchain.
        required: true
        type: string
        default: 'OFF'
      asserts:
        description: Build LLVM with assertions.
        required: true
        type: string
        default: 'ON'
      arch:
        description: Target architecture.
        required: true
        type: string
        default: 'x86'
      ubuntu:
        description: Version of Ubuntu Dockerfile to use. For example '22.04'.
        required: true
        type: string
        default: '22.04'
      win_sdk:
        description: Win SDK version string. For example, '10.0.18362.0'.
        required: true
        type: string
        default: '10.0.18362.0'
      vs_version:
        description: Visual Studio version ('vs2019' or 'vs2022').
        required: false
        type: string
        default: 'vs2019'

jobs:
  linux-build:
    runs-on: ${{ inputs.arch == 'aarch64' && 'ubuntu-22.04-arm' || 'ubuntu-latest' }}
    env:
      TAR_NAME: llvm-${{ inputs.full_version }}-ubuntu${{ inputs.ubuntu }}${{ inputs.arch == 'aarch64' && 'aarch64' || '' }}-Release${{ inputs.asserts == 'ON' && '+Asserts' || '' }}${{ inputs.lto == 'ON' && '-lto' || '' }}-x86.arm.wasm.tar.xz
      DOCKER_DIR: docker/ubuntu/${{ inputs.ubuntu }}/cpu_ispc_build
      ARTIFACT_NAME: llvm${{ inputs.asserts == 'OFF' && 'rel' || '' }}_linux_${{ inputs.arch }}_lto_${{ inputs.lto }}

    steps:
    - name: Free disk space
      uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1
      with:
        tool-cache: false
        android: true
        dotnet: true
        haskell: true
        large-packages: true
        docker-images: true
        swap-storage: true

    - name: Print inputs and environment
      run: |
        echo "version: $INPUTS_VERSION"
        echo "full_version: $INPUTS_FULL_VERSION"
        echo "lto: $INPUTS_LTO"
        echo "asserts: $INPUTS_ASSERTS"
        echo "arch: $INPUTS_ARCH"
        echo "ubuntu: $INPUTS_UBUNTU"
        echo "TAR_NAME: $TAR_NAME"
        echo "DOCKER_DIR: $DOCKER_DIR"
        echo "ARTIFACT_NAME: $ARTIFACT_NAME"
      env:
        INPUTS_VERSION: ${{ inputs.version }}
        INPUTS_FULL_VERSION: ${{ inputs.full_version }}
        INPUTS_LTO: ${{ inputs.lto }}
        INPUTS_ASSERTS: ${{ inputs.asserts }}
        INPUTS_ARCH: ${{ inputs.arch }}
        INPUTS_UBUNTU: ${{ inputs.ubuntu }}

    - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
      with:
        submodules: true

    - name: Check environment
      run: |
        cat /proc/cpuinfo

    - name: Build LLVM
      run: |
        cd $DOCKER_DIR
        docker buildx create --use
        docker buildx build \
          --tag ispc/ubuntu${INPUTS_UBUNTU} \
          --target=llvm_build \
          --build-arg REPO="${GITHUB_REPOSITORY}" \
          --build-arg SHA="${GITHUB_SHA}" \
          --build-arg LTO="${INPUTS_LTO}" \
          --build-arg LLVM_VERSION="${INPUTS_VERSION}" \
          --build-arg LLVM_DISABLE_ASSERTIONS=${{ inputs.asserts == 'ON' && 'OFF' || 'ON' }} \
          --output=type=tar,dest=result.tar .
      env:
        INPUTS_UBUNTU: ${{ inputs.ubuntu }}
        INPUTS_LTO: ${{ inputs.lto }}
        INPUTS_VERSION: ${{ inputs.version }}

    - name: Pack LLVM
      run: |
        cd $DOCKER_DIR
        rm -rf cache.local
        tar xvf result.tar usr/local/src/llvm
        mv usr/local/src/llvm/bin-$INPUTS_VERSION .
        export XZ_DEFAULTS="-T0" # run zx in all threads
        tar cJvf $TAR_NAME bin-$INPUTS_VERSION
      env:
        INPUTS_VERSION: ${{ inputs.version }}

    - name: Upload package
      uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
      with:
        name: ${{ env.ARTIFACT_NAME }}
        path: ${{ env.DOCKER_DIR }}/${{ env.TAR_NAME }}

  win-build:
    runs-on: windows-2022
    if: inputs.arch != 'aarch64'
    env:
      TAR_BASE_NAME: llvm-${{ inputs.full_version }}-win.${{ inputs.vs_version }}-Release${{ inputs.asserts == 'ON' && '+Asserts' || '' }}${{ inputs.lto == 'ON' && '-lto' || '' }}-x86.arm.wasm
      ARTIFACT_NAME: llvm${{ inputs.asserts == 'OFF' && 'rel' || '' }}_win_x86_lto_${{ inputs.lto }}

    steps:
    - name: Print inputs and environment
      run: |
        echo "version: $env:INPUTS_VERSION"
        echo "full_version: $env:INPUTS_FULL_VERSION"
        echo "lto: $env:INPUTS_LTO"
        echo "asserts: $env:INPUTS_ASSERTS"
        echo "arch: $env:INPUTS_ARCH"
        echo "win_sdk: $env:INPUTS_WIN_SDK"
        echo "vs_version: $env:INPUTS_VS_VERSION"
        echo "TAR_BASE_NAME: $env:TAR_BASE_NAME"
        echo "DOCKER_DIR: $env:DOCKER_DIR"
        echo "ARTIFACT_NAME: $env:ARTIFACT_NAME"
      env:
        INPUTS_VERSION: ${{ inputs.version }}
        INPUTS_FULL_VERSION: ${{ inputs.full_version }}
        INPUTS_LTO: ${{ inputs.lto }}
        INPUTS_ASSERTS: ${{ inputs.asserts }}
        INPUTS_ARCH: ${{ inputs.arch }}
        INPUTS_WIN_SDK: ${{ inputs.win_sdk }}
        INPUTS_VS_VERSION: ${{ inputs.vs_version }}

    - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
      with:
        submodules: true

    - name: Check environment
      shell: cmd
      run: |
        cmake --version
        wmic cpu get caption, deviceid, name, numberofcores, maxclockspeed, status

    - name: Install dependencies
      shell: cmd
      run: |
        mkdir llvm
        echo LLVM_HOME=%GITHUB_WORKSPACE%\llvm>> %GITHUB_ENV%
        echo ISPC_HOME=%GITHUB_WORKSPACE%>> %GITHUB_ENV%

    - name: Build LLVM
      shell: cmd
      run: |
        if "%INPUTS_VS_VERSION%" == "vs2019" (
          set VSVARS="C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
        ) else if "%INPUTS_VS_VERSION%" == "vs2022" (
          set VSVARS="C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
        ) else (
          echo "Unknown VS version"
          exit /b 1
        )
        call %VSVARS%
        cmake %ISPC_HOME%\superbuild ^
          -B build-%INPUTS_VERSION% ^
          --preset os ^
          -DLTO="%INPUTS_LTO%" ^
          -DLLVM_VERSION="%INPUTS_VERSION%" ^
          -DCMAKE_SYSTEM_VERSION="%INPUTS_WIN_SDK%" ^
          -DCMAKE_INSTALL_PREFIX=%LLVM_HOME%\bin-%INPUTS_VERSION% ^
          -DBUILD_STAGE2_TOOLCHAIN_ONLY=ON ^
          -DXE_DEPS=OFF ^
          -DLLVM_DISABLE_ASSERTIONS=${{ inputs.asserts == 'ON' && 'OFF' || 'ON' }}
        cmake --build build-%INPUTS_VERSION%
        rmdir /s /q build-%INPUTS_VERSION%
      env:
        INPUTS_VS_VERSION: ${{ inputs.vs_version }}
        INPUTS_VERSION: ${{ inputs.version }}
        INPUTS_LTO: ${{ inputs.lto }}
        INPUTS_WIN_SDK: ${{ inputs.win_sdk }}

    - name: Pack LLVM
      shell: cmd
      run: |
        cd llvm
        7z.exe a -ttar -snl %TAR_BASE_NAME%.tar bin-%INPUTS_VERSION%
        7z.exe a -t7z %TAR_BASE_NAME%.tar.7z %TAR_BASE_NAME%.tar
      env:
        INPUTS_VERSION: ${{ inputs.version }}

    - name: Upload package
      uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
      with:
        name: ${{ env.ARTIFACT_NAME }}
        path: llvm/${{ env.TAR_BASE_NAME }}.tar.7z

  mac-build:
    # This job is not capable to build on a shared runner with LTO=on, so need to use self-hosted macOS runner.
    runs-on: ${{ inputs.lto == 'ON' && 'macOS' || 'macos-14' }}
    timeout-minutes: 7200
    if: inputs.arch != 'aarch64'

    env:
      TAR_NAME: llvm-${{ inputs.full_version }}-macos-Release${{ inputs.asserts == 'ON' && '+Asserts' || '' }}${{ inputs.lto == 'ON' && '-lto' || '' }}-universal-x86.arm.wasm.tar.xz
      ARTIFACT_NAME: llvm${{ inputs.asserts == 'OFF' && 'rel' || '' }}_macos_universal_lto_${{ inputs.lto }}

    steps:
    - name: Print inputs and environment
      run: |
        echo "version: $INPUTS_VERSION"
        echo "full_version: $INPUTS_FULL_VERSION"
        echo "lto: $INPUTS_LTO"
        echo "asserts: $INPUTS_ASSERTS"
        echo "arch: $INPUTS_ARCH"
        echo "TAR_NAME: $TAR_NAME"
        echo "DOCKER_DIR: $DOCKER_DIR"
        echo "ARTIFACT_NAME: $ARTIFACT_NAME"
      env:
        INPUTS_VERSION: ${{ inputs.version }}
        INPUTS_FULL_VERSION: ${{ inputs.full_version }}
        INPUTS_LTO: ${{ inputs.lto }}
        INPUTS_ASSERTS: ${{ inputs.asserts }}
        INPUTS_ARCH: ${{ inputs.arch }}

    - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
      with:
        submodules: true

    - name: Install dependencies
      run: |
        ${{ inputs.lto == 'ON' && '.github/workflows/scripts/install-llvm-deps-mac-hosted.sh' || '.github/workflows/scripts/install-llvm-deps-mac.sh' }}

    - name: Check environment
      run: |
        which -a clang
        sysctl -n machdep.cpu.brand_string
        sysctl -n hw.ncpu

    - name: Build LLVM
      run: |
        cmake "$ISPC_HOME/superbuild" \
          -B "build-${INPUTS_VERSION}" \
          --preset os \
          -DLTO="${INPUTS_LTO}" \
          -DLLVM_VERSION="${INPUTS_VERSION}" \
          -DCMAKE_INSTALL_PREFIX="$LLVM_HOME/bin-${INPUTS_VERSION}" \
          -DBUILD_STAGE2_TOOLCHAIN_ONLY=ON \
          -DXE_DEPS=OFF \
          -DMACOS_UNIVERSAL_BIN=ON \
          -DLLVM_DISABLE_ASSERTIONS=${{ inputs.asserts == 'ON' && 'OFF' || 'ON' }} \
          -DISPC_ANDROID_NDK_PATH="/Users/Shared/android-ndk-r20b"
        cmake --build "build-${INPUTS_VERSION}"
        rm -rf "build-${INPUTS_VERSION}"
      env:
        INPUTS_VERSION: ${{ inputs.version }}
        INPUTS_LTO: ${{ inputs.lto }}

    - name: Pack LLVM
      run: |
        cd llvm
        tar cJvf $TAR_NAME bin-$INPUTS_VERSION
      env:
        INPUTS_VERSION: ${{ inputs.version }}

    - name: Upload package
      uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
      with:
        name: ${{ env.ARTIFACT_NAME }}
        path: llvm/${{ env.TAR_NAME }}
