# This workflow is for pre-commit testing of the LLVM-libc project.
name: LLVM-libc Pre-commit Fullbuild Tests
permissions:
  contents: read
on:
  pull_request:
    branches: [ "main" ]
    paths:
      - 'libc/**'
      - '.github/workflows/libc-fullbuild-tests.yml'

jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        # Build basic linux configuration with Debug/Release/MinSizeRel and all
        # other configurations in Debug only.
        include:
          - os: ubuntu-24.04
            build_type: Debug
            c_compiler: clang-22
            cpp_compiler: clang++-22
            target: x86_64-unknown-linux-llvm
            include_scudo: ON
          - os: ubuntu-24.04
            build_type: Release
            c_compiler: clang-22
            cpp_compiler: clang++-22
            target: x86_64-unknown-linux-llvm
            include_scudo: ON
          - os: ubuntu-24.04
            build_type: MinSizeRel
            c_compiler: clang-22
            cpp_compiler: clang++-22
            target: x86_64-unknown-linux-llvm
            include_scudo: ON
          - os: ubuntu-24.04-arm
            build_type: Debug
            c_compiler: clang-22
            cpp_compiler: clang++-22
            target: aarch64-unknown-linux-llvm
            include_scudo: ON
          - os: ubuntu-24.04
            build_type: Debug
            c_compiler: clang-22
            cpp_compiler: clang++-22
            target: x86_64-unknown-uefi-llvm
            include_scudo: OFF
          - os: ubuntu-24.04
            build_type: MinSizeRel
            c_compiler: clang-22
            cpp_compiler: clang++-22
            target: armv6m-none-eabi
            include_scudo: OFF
          - os: ubuntu-24.04
            build_type: MinSizeRel
            c_compiler: clang-22
            cpp_compiler: clang++-22
            target: armv7m-none-eabi
            include_scudo: OFF
          - os: ubuntu-24.04
            build_type: MinSizeRel
            c_compiler: clang-22
            cpp_compiler: clang++-22
            target: armv7em-none-eabi
            include_scudo: OFF
          - os: ubuntu-24.04
            build_type: MinSizeRel
            c_compiler: clang-22
            cpp_compiler: clang++-22
            target: armv8m.main-none-eabi
            include_scudo: OFF
          - os: ubuntu-24.04
            build_type: MinSizeRel
            c_compiler: clang-22
            cpp_compiler: clang++-22
            target: armv8.1m.main-none-eabi
            include_scudo: OFF
          - os: ubuntu-24.04
            build_type: MinSizeRel
            c_compiler: clang-22
            cpp_compiler: clang++-22
            target: riscv32-unknown-elf
            include_scudo: OFF
          # TODO: add back gcc build when it is fixed
          # - c_compiler: gcc
          #   cpp_compiler: g++
    steps:
    - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
    
    # Libc's build is relatively small comparing with other components of LLVM.
    # A fresh fullbuild takes about 190MiB of uncompressed disk space, which can
    # be compressed into ~40MiB. Limiting the cache size to 1G should be enough.
    # Prefer sccache as it is more modern.
    # Do not use direct GHAC access even though it is supported by sccache. GHAC rejects
    # frequent small object writes.
    - name: Setup ccache
      uses: hendrikmuhs/ccache-action@bfa03e1de4d7f7c3e80ad9109feedd05c4f5a716 # v1.2.19
      with:
        max-size: 1G
        key: libc_fullbuild_${{ matrix.c_compiler }}
        variant: sccache
    
    # Notice:
    # - MPFR is required by some of the mathlib tests.
    # - Debian has a multilib setup, so we need to symlink the asm directory.
    #   For more information, see https://wiki.debian.org/Multiarch/LibraryPathOverview
    - name: Prepare dependencies (Ubuntu)
      run: |
        wget https://apt.llvm.org/llvm.sh
        chmod +x llvm.sh
        sudo ./llvm.sh 22
        sudo apt-get update
        sudo apt-get install -y libmpfr-dev libgmp-dev libmpc-dev ninja-build linux-libc-dev
        sudo ln -sf /usr/include/$(uname -p)-linux-gnu/asm /usr/include/asm

    - name: Set reusable strings
      id: strings
      shell: bash
      run: |
        echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT"
        echo "build-install-dir=${{ github.workspace }}/install" >> "$GITHUB_OUTPUT"
    
    # Configure libc fullbuild with scudo.
    # Use MinSizeRel to reduce the size of the build.
    - name: Configure CMake
      run: |
        export RUNTIMES="libc"

        export CMAKE_FLAGS="
          -G Ninja
          -S ${{ github.workspace }}/runtimes
          -B ${{ steps.strings.outputs.build-output-dir }}
          -DCMAKE_ASM_COMPILER=${{ matrix.c_compiler }}
          -DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
          -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
          -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
          -DCMAKE_C_COMPILER_LAUNCHER=sccache
          -DCMAKE_CXX_COMPILER_LAUNCHER=sccache
          -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.build-install-dir }}"

        if [[ ${{ matrix.include_scudo}} == "ON" ]]; then
          export RUNTIMES="$RUNTIMES;compiler-rt"
          export CMAKE_FLAGS="$CMAKE_FLAGS
            -DLLVM_LIBC_INCLUDE_SCUDO=ON
            -DCOMPILER_RT_BUILD_SCUDO_STANDALONE_WITH_LLVM_LIBC=ON
            -DCOMPILER_RT_BUILD_GWP_ASAN=OFF
            -DCOMPILER_RT_SCUDO_STANDALONE_BUILD_SHARED=OFF"
        fi

        case "${{ matrix.target }}" in
          *-none-eabi|riscv32-unknown-elf)
            cmake $CMAKE_FLAGS \
              -C ${{ github.workspace }}/libc/cmake/caches/${{ matrix.target }}.cmake
            ;;
          *)
            cmake -DLLVM_RUNTIME_TARGETS=${{ matrix.target }} \
              -DLLVM_ENABLE_RUNTIMES="$RUNTIMES" \
              -DLLVM_LIBC_FULL_BUILD=ON \
              $CMAKE_FLAGS
            ;;
        esac

    - name: Build
      run: >
        cmake 
        --build ${{ steps.strings.outputs.build-output-dir }} 
        --parallel
        --target install

    - name: Test
      # Skip UEFI and baremetal tests until we have testing set up.
      if: ${{
          !endsWith(matrix.target, '-uefi-llvm') &&
          !endsWith(matrix.target, '-none-eabi') &&
          matrix.target != 'riscv32-unknown-elf'
        }}
      run: >
        cmake 
        --build ${{ steps.strings.outputs.build-output-dir }} 
        --parallel
        --target check-libc