From f913a5c106e61169402208676793c188d3db5e68 Mon Sep 17 00:00:00 2001 From: Izaak Beekman Date: Tue, 5 May 2026 13:14:27 -0400 Subject: [PATCH 1/3] build: bump LLVM to 21 Update Dockerfile ARG LLVM_VER (both stages) and CI.yml env from 20 to 21 so the LLVM build pulls release/21.x. Existing >= 20 conditionals already cover the projects/runtimes split and the flang-new -> flang rename, which became hard requirements in LLVM 21. --- .github/workflows/CI.yml | 2 +- Dockerfile | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c78640e..fe8065a 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -7,7 +7,7 @@ permissions: env: DOCKER_BUILDKIT: 1 - LLVM_VER: "20" + LLVM_VER: "21" # Uncomment to cap ninja parallelism (reduces peak memory for cold LLVM builds) # NINJA_MAX_JOBS: "2" diff --git a/Dockerfile b/Dockerfile index 64358c5..31c8ff3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,7 @@ set -euo pipefail EOC ARG PHASED_BUILD=true -ARG LLVM_VER=20 +ARG LLVM_VER=21 # Clone LLVM repo. A shallow clone is faster, but pulling a cached repository is faster yet # cd inside heredoc script; WORKDIR can't replace it # RUN --mount=type=cache,target=/git <= 20: flang binary is versioned (flang-20) with a 'flang' symlink; + # LLVM >= 20: flang binary is versioned (flang-${LLVM_VER}) with a 'flang' symlink; # use -L to follow symlinks so find matches both the real file and the symlink FLANG="$(find -L /tmp/llvm -name flang -type f)" if [ -z "$FLANG" ]; then @@ -301,7 +301,7 @@ ENV OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 # http://tau.uoregon.edu/tau.tgz # http://fs.paratools.com/tau-mirror/tau.tgz # http://fs.paratools.com/tau-nightly.tgz -ARG LLVM_VER=20 +ARG LLVM_VER=21 # hadolint ignore=DL3003 RUN --mount=type=cache,id=ccache-tau,target=/home/salt/ccache < Date: Tue, 5 May 2026 21:14:08 -0400 Subject: [PATCH 2/3] =?UTF-8?q?fix(llvm-21):=20rename=20FortranCommon?= =?UTF-8?q?=E2=86=92FortranSupport,=20move=20runtime=20to=20flang-rt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LLVM 21 reorganized Flang: - flang/lib/Common → flang/lib/Support (lib FortranCommon → FortranSupport) - flang/runtime → flang-rt subproject (built via LLVM_ENABLE_RUNTIMES) Add LLVM_VER >= 21 branch to LLVM_RUNTIMES (adds flang-rt) and to FLANG_TARGETS (uses install-FortranSupport, drops install-FortranRuntime since install-runtimes aggregate now handles flang-rt). Backwards compatible: LLVM 20 path unchanged. Verified all 27 explicit ninja targets resolve in LLVM 21 via configure-only probe build (cmake -GNinja, then ninja -t query for each target). --- Dockerfile | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 31c8ff3..fae1d4a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -108,7 +108,11 @@ set -euo pipefail # Configure the build # LLVM >= 20: openmp moved from PROJECTS to RUNTIMES (hard error in LLVM 21) - if [ "${LLVM_VER}" -ge 20 ]; then + # LLVM >= 21: flang/runtime split into flang-rt subproject; build via RUNTIMES + if [ "${LLVM_VER}" -ge 21 ]; then + LLVM_PROJECTS="flang;clang;clang-tools-extra;mlir" + LLVM_RUNTIMES="compiler-rt;openmp;flang-rt" + elif [ "${LLVM_VER}" -ge 20 ]; then LLVM_PROJECTS="flang;clang;clang-tools-extra;mlir" LLVM_RUNTIMES="compiler-rt;openmp" else @@ -147,9 +151,16 @@ set -euo pipefail tools/flang/install install-flang-libraries install-flang-headers "$FLANG_BIN_TARGET" install-flang-cmake-exports install-flangFrontend install-flangFrontendTool - install-FortranCommon install-FortranDecimal install-FortranEvaluate install-FortranLower - install-FortranParser install-FortranRuntime install-FortranSemantics + install-FortranDecimal install-FortranEvaluate install-FortranLower + install-FortranParser install-FortranSemantics ) + # LLVM >= 21 renamed FortranCommon -> FortranSupport, and FortranRuntime moved + # to the flang-rt subproject (built via install-runtimes). + if [ "${LLVM_VER}" -ge 21 ]; then + FLANG_TARGETS+=(install-FortranSupport) + else + FLANG_TARGETS+=(install-FortranCommon install-FortranRuntime) + fi # Use install-runtimes (aggregate target) because individual runtime install # targets (e.g. install-omp) aren't forwarded from the ExternalProject sub-build. From 3153f193fd8b1f320bb5acad6a6442989187432b Mon Sep 17 00:00:00 2001 From: Izaak Beekman Date: Tue, 5 May 2026 21:48:44 -0400 Subject: [PATCH 3/3] fix(hooks): migrate PostToolUse hooks from CLAUDE_FILE_PATH env to stdin JSON Claude Code no longer exports CLAUDE_FILE_PATH; PostToolUse hooks now receive input as JSON on stdin. All 7 hooks were silently no-op'ing (or erroring on 'unbound variable' under set -u) until tool-input was extracted via jq. - Read file_path from .tool_input.file_path on stdin - Add 'set -euo pipefail' to two hooks that lacked it - Fix latent regex in check-workflow-expressions.sh to accept YAML list dash prefix ('- run: |'), which had been masked by the no-op behavior Tested each hook against pass/fail fixtures in .tmp/hook-test/ and confirmed correct exit codes plus violation output. Edge cases (no path, empty JSON) exit 0 cleanly. Ref: https://code.claude.com/docs/en/hooks.md --- .claude/hooks/check-dockerfile-heredoc-strict.sh | 1 + .claude/hooks/check-lint-registration.sh | 1 + .claude/hooks/check-shell-strict-mode.sh | 2 ++ .claude/hooks/check-trailing-whitespace.sh | 1 + .claude/hooks/check-unicode-lookalikes.sh | 1 + .claude/hooks/check-workflow-expressions.sh | 6 ++++-- .claude/hooks/lint-changed-file.sh | 1 + 7 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.claude/hooks/check-dockerfile-heredoc-strict.sh b/.claude/hooks/check-dockerfile-heredoc-strict.sh index 6057bc8..729aecd 100755 --- a/.claude/hooks/check-dockerfile-heredoc-strict.sh +++ b/.claude/hooks/check-dockerfile-heredoc-strict.sh @@ -3,6 +3,7 @@ # Source: CLAUDE.md - "Dockerfile RUN heredocs use set -euo pipefail" set -euo pipefail +CLAUDE_FILE_PATH=$(jq -r '.tool_input.file_path // empty') [[ -z "$CLAUDE_FILE_PATH" ]] && exit 0 case "$(basename "$CLAUDE_FILE_PATH")" in diff --git a/.claude/hooks/check-lint-registration.sh b/.claude/hooks/check-lint-registration.sh index 752a1fc..9e7184c 100755 --- a/.claude/hooks/check-lint-registration.sh +++ b/.claude/hooks/check-lint-registration.sh @@ -3,6 +3,7 @@ # Also flags stale entries (files listed in lint.sh that no longer exist). set -euo pipefail +CLAUDE_FILE_PATH=$(jq -r '.tool_input.file_path // empty') [[ -z "$CLAUDE_FILE_PATH" ]] && exit 0 cd "$(git rev-parse --show-toplevel)" || exit 1 diff --git a/.claude/hooks/check-shell-strict-mode.sh b/.claude/hooks/check-shell-strict-mode.sh index 269ce4d..75a9ace 100755 --- a/.claude/hooks/check-shell-strict-mode.sh +++ b/.claude/hooks/check-shell-strict-mode.sh @@ -1,7 +1,9 @@ #!/bin/bash # PostToolUse hook: Ensure shell scripts contain 'set -euo pipefail'. # Exception: lint.sh uses 'set -uo pipefail' (omits -e for non-fail-fast design). +set -euo pipefail +CLAUDE_FILE_PATH=$(jq -r '.tool_input.file_path // empty') [[ -z "$CLAUDE_FILE_PATH" ]] && exit 0 case "$(basename "$CLAUDE_FILE_PATH")" in diff --git a/.claude/hooks/check-trailing-whitespace.sh b/.claude/hooks/check-trailing-whitespace.sh index b10c4eb..777a0f2 100755 --- a/.claude/hooks/check-trailing-whitespace.sh +++ b/.claude/hooks/check-trailing-whitespace.sh @@ -3,6 +3,7 @@ # Markdown exception: trailing two spaces after text (line break) is allowed. set -euo pipefail +CLAUDE_FILE_PATH=$(jq -r '.tool_input.file_path // empty') [[ -z "$CLAUDE_FILE_PATH" ]] && exit 0 # Skip binary files diff --git a/.claude/hooks/check-unicode-lookalikes.sh b/.claude/hooks/check-unicode-lookalikes.sh index f87f3a5..d34d3a9 100755 --- a/.claude/hooks/check-unicode-lookalikes.sh +++ b/.claude/hooks/check-unicode-lookalikes.sh @@ -4,6 +4,7 @@ # Intentional Unicode (e.g., box-drawing chars in terminal output) is NOT matched. set -euo pipefail +CLAUDE_FILE_PATH=$(jq -r '.tool_input.file_path // empty') [[ -z "$CLAUDE_FILE_PATH" ]] && exit 0 case "$(basename "$CLAUDE_FILE_PATH")" in diff --git a/.claude/hooks/check-workflow-expressions.sh b/.claude/hooks/check-workflow-expressions.sh index 96b3b49..d229d37 100755 --- a/.claude/hooks/check-workflow-expressions.sh +++ b/.claude/hooks/check-workflow-expressions.sh @@ -4,7 +4,9 @@ # # Checks for ${{ github.* }} on lines inside run: blocks. These should be # replaced with shell env vars (e.g., $GITHUB_REF) set via the step's env: key. +set -euo pipefail +CLAUDE_FILE_PATH=$(jq -r '.tool_input.file_path // empty') [[ -z "$CLAUDE_FILE_PATH" ]] && exit 0 case "$(basename "$CLAUDE_FILE_PATH")" in @@ -15,13 +17,13 @@ esac # Use awk to find ${{ github.* }} only inside run: blocks. # Track indentation to detect when a run: block ends. violations=$(awk ' - /^[[:space:]]+run:[[:space:]]*[|>]/ { + /^[[:space:]]+(-[[:space:]]+)?run:[[:space:]]*[|>]/ { in_run = 1 match($0, /^[[:space:]]*/) run_indent = RLENGTH next } - /^[[:space:]]+run:[[:space:]]*[^|>]/ { + /^[[:space:]]+(-[[:space:]]+)?run:[[:space:]]*[^|>]/ { # Single-line run: value if ($0 ~ /\$\{\{[[:space:]]*github\./) print NR": "$0 next diff --git a/.claude/hooks/lint-changed-file.sh b/.claude/hooks/lint-changed-file.sh index 475ea12..3c0152b 100755 --- a/.claude/hooks/lint-changed-file.sh +++ b/.claude/hooks/lint-changed-file.sh @@ -3,6 +3,7 @@ # Delegates to lint.sh --file for consistent linter args. set -euo pipefail +CLAUDE_FILE_PATH=$(jq -r '.tool_input.file_path // empty') [[ -z "$CLAUDE_FILE_PATH" ]] && exit 0 cd "$(git rev-parse --show-toplevel)" || exit 1