Skip to content

Test LLVM Patches

Test LLVM Patches #178

name: Test LLVM Patches
# Manual-only: this workflow rebuilds four LLVM toolchains on the meatloaf
# runner (hours on 8 cores, starving the main x86 CI queue) and two more on
# pastrami, whose disk cannot hold its build trees alongside the installed
# toolchains. Run it deliberately via workflow_dispatch after touching
# llvm-patches/, rather than on every push of a PR that does.
on:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true
jobs:
step1-configure-all:
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
name: 'Step 1: Configure all LLVM versions and verify patches'
runs-on:
- self-hosted
- Linux
- X64
strategy:
matrix:
include:
- llvm-version: 21
build-id: "21"
install-suffix: ""
variant-flag: ""
- llvm-version: 22
build-id: "22-translator"
install-suffix: "-translator"
variant-flag: "--variant translator"
- llvm-version: 22
build-id: "22-native"
install-suffix: "-native"
variant-flag: "--variant native"
# LLVM 23 needs only one build: chipStar patches in llvm#213052, so the
# SPIRV-target build also serves the translator and the producer is
# chosen per compilation by -f[no-]integrated-objemitter.
- llvm-version: 23
build-id: "23"
install-suffix: ""
variant-flag: "--variant native"
fail-fast: true
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 0
submodules: 'recursive'
- name: Configure LLVM ${{ matrix.build-id }}
run: |
rm -rf $HOME/llvm-builds/${{ matrix.build-id }}
mkdir -p $HOME/llvm-builds/${{ matrix.build-id }}
cd $HOME/llvm-builds/${{ matrix.build-id }}
rm -rf scripts llvm-patches
cp -r ${{ github.workspace }}/scripts .
cp -r ${{ github.workspace }}/llvm-patches .
chmod +x scripts/configure_llvm.sh
./scripts/configure_llvm.sh --version ${{ matrix.llvm-version }} \
--install-dir $HOME/install/llvm/${{ matrix.llvm-version }}.0${{ matrix.install-suffix }} \
${{ matrix.variant-flag }} --configure-only
step2-build-test:
needs: step1-configure-all
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
name: Build LLVM ${{ matrix.build-id }} and test chipStar
runs-on:
- self-hosted
- Linux
- X64
env:
IGC_EnableDPEmulation: 1
OverrideDefaultFP64Settings: 1
CHIP_LOGLEVEL: err
CHIP_MODULE_CACHE_DIR: ""
POCL_KERNEL_CACHE: 0
CHIP_L0_EVENT_TIMEOUT: 1790
strategy:
matrix:
include:
- llvm-version: 21
build-id: "21"
install-suffix: ""
- llvm-version: 22
build-id: "22-translator"
install-suffix: "-translator"
- llvm-version: 22
build-id: "22-native"
install-suffix: "-native"
- llvm-version: 23
build-id: "23"
install-suffix: ""
fail-fast: false
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 0
submodules: 'recursive'
- name: Build LLVM ${{ matrix.build-id }}
id: build_llvm
continue-on-error: true
run: |
BUILD_DIR="$HOME/llvm-builds/${{ matrix.build-id }}/llvm-project/llvm/build_${{ matrix.llvm-version }}"
if [ ! -d "$BUILD_DIR" ]; then
echo "Error: Build directory $BUILD_DIR does not exist. Step 1 may have failed."
exit 1
fi
cd "$BUILD_DIR"
make -j$(nproc)
timeout-minutes: 300
- name: Stage install for later
if: steps.build_llvm.outcome == 'success'
run: |
rm -rf $HOME/llvm-stage/${{ matrix.build-id }}
DESTDIR=$HOME/llvm-stage/${{ matrix.build-id }} cmake --install $HOME/llvm-builds/${{ matrix.build-id }}/llvm-project/llvm/build_${{ matrix.llvm-version }}
- name: Build chipStar with LLVM ${{ matrix.build-id }}
id: build_chipstar
if: steps.build_llvm.outcome == 'success'
run: |
# Source modules for device drivers
if [ -f "$HOME/.local/init/bash" ]; then
export MODULESHOME=$HOME/.local
source "$MODULESHOME/init/bash"
elif [ -f /etc/profile.d/lmod.sh ]; then
source /etc/profile.d/lmod.sh &> /dev/null
else
source /etc/profile.d/modules.sh &> /dev/null
fi
module use ~/modulefiles
module load oneapi/2025.0.4 opencl/dgpu
# Build/test against the INSTALLED LLVM toolchain (staged above), not
# the build tree. The build tree's clang resource dir lacks
# install-only runtime headers such as omp.h, which made
# TestHipccFopenmp fail with "'omp.h' file not found".
LLVM_PREFIX="$HOME/install/llvm/${{ matrix.llvm-version }}.0${{ matrix.install-suffix }}"
LLVM_STAGE="$HOME/llvm-stage/${{ matrix.build-id }}${LLVM_PREFIX}"
LLVM_BIN="${LLVM_STAGE}/bin"
test -f "${LLVM_BIN}/clang" || exit 1
# The staged binaries are thin drivers; all the driver logic lives in
# libclang-cpp.so / libLLVM.so. Their RUNPATH points at the *final*
# install prefix ($HOME/install/llvm/<ver>), not at the stage, so by
# default the staged clang loads the previously installed libraries
# and silently runs old code. That makes this lane test the installed
# toolchain rather than the one just built from llvm-patches/, which
# is precisely what this workflow exists to validate. Pin the loader
# to the stage, and persist it to the test steps via GITHUB_ENV since
# chipStar invokes clang again at test time.
export LD_LIBRARY_PATH="${LLVM_STAGE}/lib:${LLVM_STAGE}/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> "$GITHUB_ENV"
# Fail loudly if the pin did not take effect, rather than silently
# validating the wrong toolchain again.
RESOLVED=$(ldd "${LLVM_BIN}/clang" 2>/dev/null | awk '/libclang-cpp/{print $3}')
case "$RESOLVED" in
"${LLVM_STAGE}"/*) echo "OK: clang resolves libclang-cpp from the stage" ;;
"") echo "NOTE: clang does not link libclang-cpp dynamically; nothing to pin" ;;
*) echo "ERROR: clang resolves libclang-cpp from '$RESOLVED', not the stage"; exit 1 ;;
esac
test -f "${LLVM_BIN}/../lib/clang/${{ matrix.llvm-version }}/include/omp.h" \
|| { echo "ERROR: omp.h missing from LLVM install toolchain at ${LLVM_BIN}"; exit 1; }
cd ${{ github.workspace }}
rm -rf build-llvm${{ matrix.build-id }}
mkdir -p build-llvm${{ matrix.build-id }}
cd build-llvm${{ matrix.build-id }}
cmake .. -DLLVM_CONFIG_BIN=${LLVM_BIN}/llvm-config -GNinja \
-DCMAKE_BUILD_TYPE=Debug \
-DCHIP_BUILD_SAMPLES=ON -DCHIP_BUILD_TESTS=ON
ninja all install -j$(nproc)
ninja build_tests install -j$(nproc)
timeout-minutes: 60
- name: Test chipStar with LLVM ${{ matrix.build-id }} (iGPU OpenCL)
if: always() && steps.build_chipstar.outcome == 'success'
continue-on-error: true
run: |
if [ -f "$HOME/.local/init/bash" ]; then
export MODULESHOME=$HOME/.local; source "$MODULESHOME/init/bash"
elif [ -f /etc/profile.d/lmod.sh ]; then source /etc/profile.d/lmod.sh &> /dev/null
else source /etc/profile.d/modules.sh &> /dev/null; fi
module use ~/modulefiles
# IGC 2.36.3/2.38.2 miscompile chipStar kernels under their
# optimizer (TestSnakeMiscompileO2); this build carries the fix.
module load igc/all-fixes-2026.07.30
module load opencl/igpu
cd ${{ github.workspace }}/build-llvm${{ matrix.build-id }}
../scripts/check.py ./ igpu opencl
timeout-minutes: 60
- name: Test chipStar with LLVM ${{ matrix.build-id }} (iGPU Level0)
if: always() && steps.build_chipstar.outcome == 'success'
continue-on-error: true
run: |
if [ -f "$HOME/.local/init/bash" ]; then
export MODULESHOME=$HOME/.local; source "$MODULESHOME/init/bash"
elif [ -f /etc/profile.d/lmod.sh ]; then source /etc/profile.d/lmod.sh &> /dev/null
else source /etc/profile.d/modules.sh &> /dev/null; fi
module use ~/modulefiles
# IGC 2.36.3/2.38.2 miscompile chipStar kernels under their
# optimizer (TestSnakeMiscompileO2); this build carries the fix.
module load igc/all-fixes-2026.07.30
module load level-zero/igpu
cd ${{ github.workspace }}/build-llvm${{ matrix.build-id }}
../scripts/check.py ./ igpu level0
timeout-minutes: 60
- name: Test chipStar with LLVM ${{ matrix.build-id }} (dGPU Level0)
if: always() && steps.build_chipstar.outcome == 'success'
run: |
if [ -f "$HOME/.local/init/bash" ]; then
export MODULESHOME=$HOME/.local; source "$MODULESHOME/init/bash"
elif [ -f /etc/profile.d/lmod.sh ]; then source /etc/profile.d/lmod.sh &> /dev/null
else source /etc/profile.d/modules.sh &> /dev/null; fi
module use ~/modulefiles
# IGC 2.36.3/2.38.2 miscompile chipStar kernels under their
# optimizer (TestSnakeMiscompileO2); this build carries the fix.
module load igc/all-fixes-2026.07.30
module load level-zero/dgpu
cd ${{ github.workspace }}/build-llvm${{ matrix.build-id }}
../scripts/check.py ./ dgpu level0
timeout-minutes: 60
- name: Test chipStar with LLVM ${{ matrix.build-id }} (dGPU OpenCL)
if: always() && steps.build_chipstar.outcome == 'success'
run: |
if [ -f "$HOME/.local/init/bash" ]; then
export MODULESHOME=$HOME/.local; source "$MODULESHOME/init/bash"
elif [ -f /etc/profile.d/lmod.sh ]; then source /etc/profile.d/lmod.sh &> /dev/null
else source /etc/profile.d/modules.sh &> /dev/null; fi
module use ~/modulefiles
# IGC 2.36.3/2.38.2 miscompile chipStar kernels under their
# optimizer (TestSnakeMiscompileO2); this build carries the fix.
module load igc/all-fixes-2026.07.30
module load opencl/dgpu
cd ${{ github.workspace }}/build-llvm${{ matrix.build-id }}
../scripts/check.py ./ dgpu opencl
timeout-minutes: 60
- name: Test chipStar with LLVM ${{ matrix.build-id }} (CPU OpenCL)
if: always() && steps.build_chipstar.outcome == 'success'
run: |
if [ -f "$HOME/.local/init/bash" ]; then
export MODULESHOME=$HOME/.local; source "$MODULESHOME/init/bash"
elif [ -f /etc/profile.d/lmod.sh ]; then source /etc/profile.d/lmod.sh &> /dev/null
else source /etc/profile.d/modules.sh &> /dev/null; fi
module use ~/modulefiles
# IGC 2.36.3/2.38.2 miscompile chipStar kernels under their
# optimizer (TestSnakeMiscompileO2); this build carries the fix.
module load igc/all-fixes-2026.07.30
module load opencl/cpu
cd ${{ github.workspace }}/build-llvm${{ matrix.build-id }}
../scripts/check.py ./ cpu opencl --num-tries=3
timeout-minutes: 60
- uses: actions/upload-artifact@v4
if: failure()
with:
name: test-logs-llvm${{ matrix.build-id }}
path: |
${{ github.workspace }}/build-llvm${{ matrix.build-id }}/checkpy_*.txt
${{ github.workspace }}/build-llvm${{ matrix.build-id }}/Testing/Temporary/LastTest.log
install-llvm-on-main:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
name: Install LLVM ${{ matrix.build-id }} on main branch
runs-on:
- self-hosted
- Linux
- X64
strategy:
matrix:
include:
- llvm-version: 21
build-id: "21"
install-suffix: ""
module-name: "21.0"
- llvm-version: 22
build-id: "22-translator"
install-suffix: "-translator"
module-name: "22.0-translator"
- llvm-version: 22
build-id: "22-native"
install-suffix: "-native"
module-name: "22.0-native"
- llvm-version: 23
build-id: "23"
install-suffix: ""
module-name: "23.0"
fail-fast: false
steps:
- name: Install LLVM ${{ matrix.build-id }}
id: install_llvm
run: |
set -euo pipefail
STAGED="$HOME/llvm-stage/${{ matrix.build-id }}"
INSTALL_DIR="$HOME/install/llvm/${{ matrix.llvm-version }}.0${{ matrix.install-suffix }}"
# This job runs on every push to main, but the stage is produced by a
# *prior* pull_request run of this workflow. If that build failed, was
# skipped, or the stage was already consumed, there is nothing to
# install. Bail out before touching the live toolchain: destroying it
# takes CI down for every PR and can only be undone by a full rebuild.
if [ ! -d "${STAGED}${INSTALL_DIR}" ]; then
echo "No staged build at ${STAGED}${INSTALL_DIR}; leaving $INSTALL_DIR untouched."
echo "installed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# Keep the previous toolchain until the new one is in place, so a
# failure here is recoverable.
BACKUP="${INSTALL_DIR}.prev"
rm -rf "$BACKUP"
if [ -d "$INSTALL_DIR" ]; then
mv "$INSTALL_DIR" "$BACKUP"
fi
if ! mv "${STAGED}${INSTALL_DIR}" "$INSTALL_DIR"; then
echo "Install failed; restoring previous toolchain."
rm -rf "$INSTALL_DIR"
[ -d "$BACKUP" ] && mv "$BACKUP" "$INSTALL_DIR"
exit 1
fi
echo "installed=true" >> "$GITHUB_OUTPUT"
timeout-minutes: 5
- name: Verify LLVM ${{ matrix.build-id }} installation
if: steps.install_llvm.outputs.installed == 'true'
run: |
set -euo pipefail
INSTALL_DIR="$HOME/install/llvm/${{ matrix.llvm-version }}.0${{ matrix.install-suffix }}"
BACKUP="${INSTALL_DIR}.prev"
if [ ! -x "$INSTALL_DIR/bin/clang" ]; then
echo "Installed toolchain has no usable clang; restoring previous."
rm -rf "$INSTALL_DIR"
[ -d "$BACKUP" ] && mv "$BACKUP" "$INSTALL_DIR"
exit 1
fi
"$INSTALL_DIR/bin/clang" --version
- name: Generate modulefile for LLVM ${{ matrix.build-id }}
if: steps.install_llvm.outputs.installed == 'true'
run: |
MODULE_DIR="$HOME/modulefiles/llvm"
INSTALL_DIR="$HOME/install/llvm/${{ matrix.llvm-version }}.0${{ matrix.install-suffix }}"
mkdir -p "$MODULE_DIR"
{
echo '#%Module'
echo ''
echo "set install_dir $INSTALL_DIR"
echo 'pushenv llvm_PATH $install_dir'
echo 'pushenv llvm_ROOT $install_dir'
echo 'pushenv llvm_DIR $install_dir'
echo 'pushenv LLVM_PATH $install_dir'
echo 'pushenv LLVM_ROOT $install_dir'
echo 'pushenv LLVM_DIR $install_dir'
echo ''
echo 'prepend-path PATH $install_dir/bin'
echo 'prepend-path LD_LIBRARY_PATH $install_dir/lib'
echo 'prepend-path LD_LIBRARY_PATH $install_dir/lib64'
echo 'prepend-path LIBRARY_PATH $install_dir/lib'
echo 'prepend-path LIBRARY_PATH $install_dir/lib64'
echo 'prepend-path CPATH $install_dir/include'
echo 'prepend-path PKG_CONFIG_PATH $install_dir/lib/pkgconfig'
echo 'prepend-path CMAKE_PREFIX_PATH $install_dir/lib/cmake'
} > "$MODULE_DIR/${{ matrix.module-name }}"
echo "Created modulefile: $MODULE_DIR/${{ matrix.module-name }}"
# Only reap on success. Reaping unconditionally used to discard the stage
# even when the install had failed, so the next attempt had nothing to
# install from.
- name: Cleanup staged install and backup
if: success() && steps.install_llvm.outputs.installed == 'true'
run: |
rm -rf "$HOME/llvm-stage/${{ matrix.build-id }}"
rm -rf "$HOME/install/llvm/${{ matrix.llvm-version }}.0${{ matrix.install-suffix }}.prev"
step1-configure-all-macos:
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
name: 'Step 1: Configure LLVM 22 (macOS)'
runs-on: [self-hosted, ARM64, MacOS]
strategy:
matrix:
variant: [translator, native]
fail-fast: true
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 0
submodules: 'recursive'
- name: Configure LLVM 22 (${{ matrix.variant }})
shell: /bin/bash {0}
run: |
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"
BUILD_DIR="$HOME/llvm-builds/22-${{ matrix.variant }}"
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
rm -rf scripts llvm-patches
cp -r ${{ github.workspace }}/scripts .
cp -r ${{ github.workspace }}/llvm-patches .
chmod +x scripts/configure_llvm.sh
./scripts/configure_llvm.sh --version 22 \
--install-dir $HOME/install/llvm/22.0-${{ matrix.variant }} \
--variant ${{ matrix.variant }} --configure-only
step2-build-test-macos:
needs: step1-configure-all-macos
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
name: Build LLVM 22 (${{ matrix.variant }}) (macOS) and test chipStar
runs-on: [self-hosted, ARM64, MacOS]
env:
CHIP_DEVICE_TYPE: pocl
CHIP_MODULE_CACHE_DIR: ""
strategy:
matrix:
variant: [translator, native]
fail-fast: false
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 0
submodules: 'recursive'
- name: Build LLVM 22 (${{ matrix.variant }})
id: build_llvm
shell: /bin/bash {0}
continue-on-error: true
run: |
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"
BUILD_DIR="$HOME/llvm-builds/22-${{ matrix.variant }}/llvm-project/llvm/build_22"
if [ ! -d "$BUILD_DIR" ]; then
echo "Error: Build directory $BUILD_DIR does not exist. Step 1 may have failed."
exit 1
fi
cd "$BUILD_DIR"
cmake --build . -j$(sysctl -n hw.ncpu)
timeout-minutes: 300
- name: Stage install for later
if: steps.build_llvm.outcome == 'success'
shell: /bin/bash {0}
run: |
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"
rm -rf $HOME/llvm-stage/22-${{ matrix.variant }}
DESTDIR=$HOME/llvm-stage/22-${{ matrix.variant }} cmake --install $HOME/llvm-builds/22-${{ matrix.variant }}/llvm-project/llvm/build_22
- name: Test chipStar with LLVM 22 (${{ matrix.variant }}) (PoCL OpenCL)
if: steps.build_llvm.outcome == 'success'
shell: /bin/bash {0}
run: |
source /opt/homebrew/Cellar/modules/5.6.0/init/bash
export MODULEPATH="/Users/paulius/modulefiles:$MODULEPATH"
module load pocl
# Build/test against the INSTALLED LLVM toolchain (staged above), not
# the build tree, which lacks install-only runtime headers such as
# omp.h (breaks TestHipccFopenmp with "'omp.h' file not found").
LLVM_PREFIX="$HOME/install/llvm/22.0-${{ matrix.variant }}"
LLVM_STAGE="$HOME/llvm-stage/22-${{ matrix.variant }}${LLVM_PREFIX}"
LLVM_BIN="${LLVM_STAGE}/bin"
test -f "${LLVM_BIN}/clang" || exit 1
test -f "${LLVM_BIN}/../lib/clang/22/include/omp.h" \
|| { echo "ERROR: omp.h missing from LLVM install toolchain at ${LLVM_BIN}"; exit 1; }
# configure_llvm.sh builds with LLVM_LINK_LLVM_DYLIB=ON and
# CMAKE_INSTALL_RPATH pinned to the final install prefix, so a staged
# (DESTDIR) clang resolves libclang-cpp/libLLVM from the previously
# installed toolchain and runs old driver code. Pin the loader to the
# stage so this lane tests what it just built. DYLD_LIBRARY_PATH (not
# DYLD_FALLBACK_LIBRARY_PATH) is required: fallback is consulted only
# after @rpath resolution fails, and here it succeeds with the wrong
# library. Diagnostic only, not fatal, since the macOS linkage layout
# is not verified here the way the Linux one is.
export DYLD_LIBRARY_PATH="${LLVM_STAGE}/lib${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}}"
echo "clang links against:"
otool -L "${LLVM_BIN}/clang" 2>/dev/null | grep -iE "clang-cpp|libLLVM" || true
export PATH="/Users/paulius/.pyenv/shims:/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"
export CHIP_DEVICE_TYPE=pocl
export OCL_ICD_VENDORS=/Users/paulius/install/pocl/etc/OpenCL/vendors/
export SPIRV_TOOLS_PREFIX=$(brew --prefix spirv-tools)
export CMAKE_PREFIX_PATH="${SPIRV_TOOLS_PREFIX}:${CMAKE_PREFIX_PATH}"
cd ${{ github.workspace }}
rm -rf build-22-${{ matrix.variant }}
mkdir -p build-22-${{ matrix.variant }}
cd build-22-${{ matrix.variant }}
/opt/homebrew/bin/cmake .. \
-DLLVM_CONFIG_BIN=${LLVM_BIN}/llvm-config \
-DOpenCL_LIBRARY=/Users/paulius/install/pocl/lib/libpocl.dylib \
-GNinja -DCMAKE_BUILD_TYPE=Debug
ninja CHIP
ninja build_tests
ninja
../scripts/check.py ./ pocl opencl
timeout-minutes: 60
- uses: actions/upload-artifact@v4
if: failure()
with:
name: test-logs-macos-llvm22-${{ matrix.variant }}
path: |
build-22-${{ matrix.variant }}/checkpy_*.txt
build-22-${{ matrix.variant }}/Testing/Temporary/LastTest.log
install-llvm-on-main-macos:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
name: Install LLVM 22 (${{ matrix.variant }}) on main branch (macOS)
runs-on: [self-hosted, ARM64, MacOS]
strategy:
matrix:
variant: [translator, native]
fail-fast: false
steps:
- name: Install LLVM 22 (${{ matrix.variant }})
id: install_llvm_macos
run: |
set -euo pipefail
STAGED="$HOME/llvm-stage/22-${{ matrix.variant }}"
INSTALL_DIR="$HOME/install/llvm/22.0-${{ matrix.variant }}"
# See the Linux job: the stage comes from a prior pull_request run, so
# it may not exist. Never delete the live toolchain before we know we
# have a replacement for it.
if [ ! -d "${STAGED}${INSTALL_DIR}" ]; then
echo "No staged build at ${STAGED}${INSTALL_DIR}; leaving $INSTALL_DIR untouched."
echo "installed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
BACKUP="${INSTALL_DIR}.prev"
rm -rf "$BACKUP"
if [ -d "$INSTALL_DIR" ]; then
mv "$INSTALL_DIR" "$BACKUP"
fi
if ! mv "${STAGED}${INSTALL_DIR}" "$INSTALL_DIR"; then
echo "Install failed; restoring previous toolchain."
rm -rf "$INSTALL_DIR"
[ -d "$BACKUP" ] && mv "$BACKUP" "$INSTALL_DIR"
exit 1
fi
echo "installed=true" >> "$GITHUB_OUTPUT"
timeout-minutes: 5
- name: Verify LLVM 22 (${{ matrix.variant }}) installation
if: steps.install_llvm_macos.outputs.installed == 'true'
run: |
set -euo pipefail
INSTALL_DIR="$HOME/install/llvm/22.0-${{ matrix.variant }}"
BACKUP="${INSTALL_DIR}.prev"
if [ ! -x "$INSTALL_DIR/bin/clang" ]; then
echo "Installed toolchain has no usable clang; restoring previous."
rm -rf "$INSTALL_DIR"
[ -d "$BACKUP" ] && mv "$BACKUP" "$INSTALL_DIR"
exit 1
fi
"$INSTALL_DIR/bin/clang" --version
- name: Generate modulefile for LLVM 22 (${{ matrix.variant }})
if: steps.install_llvm_macos.outputs.installed == 'true'
shell: /bin/bash {0}
run: |
MODULE_DIR="$HOME/modulefiles/llvm"
INSTALL_DIR="$HOME/install/llvm/22.0-${{ matrix.variant }}"
mkdir -p "$MODULE_DIR"
{
echo '#%Module'
echo ''
echo "set install_dir $INSTALL_DIR"
echo 'pushenv llvm_PATH $install_dir'
echo 'pushenv llvm_ROOT $install_dir'
echo 'pushenv llvm_DIR $install_dir'
echo 'pushenv LLVM_PATH $install_dir'
echo 'pushenv LLVM_ROOT $install_dir'
echo 'pushenv LLVM_DIR $install_dir'
echo ''
echo 'prepend-path PATH $install_dir/bin'
echo '# Use DYLD_FALLBACK_LIBRARY_PATH instead of DYLD_LIBRARY_PATH'
echo '# This allows other libraries (like PoCL) to use their @rpath first,'
echo '# while still providing LLVM libs as a fallback for tools that need them.'
echo 'prepend-path DYLD_FALLBACK_LIBRARY_PATH $install_dir/lib'
echo 'prepend-path DYLD_FALLBACK_LIBRARY_PATH $install_dir/lib64'
echo 'prepend-path LIBRARY_PATH $install_dir/lib'
echo 'prepend-path LIBRARY_PATH $install_dir/lib64'
echo 'prepend-path CPATH $install_dir/include'
echo 'prepend-path PKG_CONFIG_PATH $install_dir/lib/pkgconfig'
echo 'prepend-path CMAKE_PREFIX_PATH $install_dir/lib/cmake'
} > "$MODULE_DIR/22.0-${{ matrix.variant }}"
echo "Created modulefile: $MODULE_DIR/22.0-${{ matrix.variant }}"
# Only reap on success; see the Linux job.
- name: Cleanup staged install and backup
if: success() && steps.install_llvm_macos.outputs.installed == 'true'
run: |
rm -rf "$HOME/llvm-stage/22-${{ matrix.variant }}"
rm -rf "$HOME/install/llvm/22.0-${{ matrix.variant }}.prev"