#!/usr/bin/env bash # scripts/quality/multi-compiler.sh # # Build and test the fast (non-CGAL) suite against multiple C++ # compilers in sequence. Catches compiler-specific issues: # * gcc-only extensions accidentally used # * clang's stricter template-error handling # * libstdc++ vs libc++ ABI assumptions # # Local-only. Each compiler gets its own build-multi-/ directory. # # Usage: # bash scripts/quality/multi-compiler.sh # auto-detect # bash scripts/quality/multi-compiler.sh g++ clang++ # specific list # # Exit codes: # 0 every detected/selected compiler builds + tests cleanly # 1 at least one compiler failed # 2 fewer than 2 compilers available set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" cd "$ROOT" # ── Pick compilers ────────────────────────────────────────────────────────── if [ $# -gt 0 ]; then COMPILERS=("$@") else COMPILERS=() for cand in g++ g++-13 g++-12 g++-11 clang++ clang++-17 clang++-16 clang++-15; do if command -v "$cand" >/dev/null 2>&1; then COMPILERS+=("$cand") fi done fi if [ "${#COMPILERS[@]}" -lt 1 ]; then echo "FAIL: no C++ compilers detected. Install gcc and/or clang." >&2 exit 2 fi echo "========================================" echo " Multi-compiler build matrix" echo " compilers: ${COMPILERS[*]}" echo "========================================" echo # De-duplicate by resolving each to its absolute path. declare -a UNIQ_BINS=() declare -a UNIQ_NAMES=() seen="" for cc in "${COMPILERS[@]}"; do if ! command -v "$cc" >/dev/null 2>&1; then echo " skip $cc (not in PATH)" continue fi full="$(command -v "$cc")" if echo "$seen" | grep -qx "$full"; then continue fi seen="$seen $full" UNIQ_BINS+=("$full") # Use a sanitised name for the build dir (replace + and / etc.). safe="$(echo "$cc" | sed 's|[/+]|_|g')" UNIQ_NAMES+=("$safe") done if [ "${#UNIQ_BINS[@]}" -lt 2 ]; then echo "WARNING: only ${#UNIQ_BINS[@]} unique compiler(s) — matrix is degenerate." echo " (continuing anyway; install a second toolchain for full coverage)" fi # ── Run each ──────────────────────────────────────────────────────────────── overall=0 i=0 for cc in "${UNIQ_BINS[@]}"; do name="${UNIQ_NAMES[$i]}" i=$((i + 1)) build="build-multi-$name" echo echo "── [$i/${#UNIQ_BINS[@]}] $name ─────────────────────" echo " bin: $cc" echo " build: $build" if ! cmake -S code -B "$build" \ -DCMAKE_CXX_COMPILER="$cc" \ -DCMAKE_BUILD_TYPE=Release \ -Wno-dev >/dev/null 2>&1; then echo " CONFIGURE FAILED" overall=1 continue fi if ! nice -n 19 cmake --build "$build" --target conformallab_tests \ -j"$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 2)" \ >"$build/build.log" 2>&1; then echo " BUILD FAILED — see $build/build.log" overall=1 continue fi if ! ( cd "$build" && ctest -E "^cgal\." --output-on-failure >"test.log" 2>&1 ); then echo " TESTS FAILED — see $build/test.log" overall=1 continue fi pass=$(grep -oE "tests passed.*out of [0-9]+" "$build/test.log" | head -1) echo " OK ($pass)" done echo if [ $overall -eq 0 ]; then echo "OK: every selected compiler built + passed the fast test suite." else echo "FAIL: at least one compiler did not produce a green test run." fi exit $overall