From 427370184e36798bdffa7439957d965917f44bf6 Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Thu, 15 Oct 2026 14:47:33 +0530 Subject: [PATCH 1/4] Fix Windows and macOS GitHub CI after runner image updates Git for Windows 2.56 moved /mingw64 to /ucrt64, so curl and other tools were not found in the PATH passed to packcheck. The macOS image ships Command Line Tools 27.0 with default Xcode 26.6; linking against the CLT SDK fails with a tapi "unknown architecture arm64e.x1-macos" error. Select the default Xcode so that the compiler, linker and SDK come from the same toolchain. GHC records the SDK library path when it is installed, so a GHC restored from the cache can still pass the CLT SDK path to the linker. Add the Xcode version and build to the macOS GHC and dependency cache keys, so that a runner image with a different Xcode installs GHC afresh. --- .github/workflows/packcheck.yml | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/.github/workflows/packcheck.yml b/.github/workflows/packcheck.yml index e36933e1..eb7148ec 100644 --- a/.github/workflows/packcheck.yml +++ b/.github/workflows/packcheck.yml @@ -272,6 +272,26 @@ jobs: - uses: actions/checkout@v4 + # The macOS image may ship Command Line Tools newer than the default + # Xcode (e.g. CLT 27.0 with Xcode 26.6). Linking against the CLT SDK then + # fails with "tapi error: malformed file ... unknown architecture + # arm64e.x1-macos". Select the default Xcode so that the compiler, linker + # and SDK come from the same toolchain. packcheck clears the environment, + # so SDKROOT or DEVELOPER_DIR cannot be used instead. + # + # GHC records the SDK library path when it is installed, so the GHC and + # dependency cache keys include the Xcode version and build. A runner + # image with a different Xcode then installs GHC afresh. + - name: Select default Xcode (macOS) + id: xcode + if: runner.os == 'macOS' + run: | + sudo xcode-select -s /Applications/Xcode.app/Contents/Developer + xcode-select -p + xcrun --show-sdk-path + ver=$(xcodebuild -version | awk 'NR==1{v=$2} /Build version/{b=$3} END{print v "-" b}') + echo "toolchain=-xcode-$ver" >> "$GITHUB_OUTPUT" + # This should happen before cache restore. - name: Remove ~/.ghcup symlink (non-Windows) if: runner.os != 'Windows' @@ -299,7 +319,7 @@ jobs: with: path: | ~/.ghcup - key: ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }} + key: ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}${{ steps.xcode.outputs.toolchain }} # GHC is not test/options specific #- name: Restore ghcup and ghc (Windows) @@ -330,7 +350,7 @@ jobs: ~/.local/bin ~/.local/state/cabal ~/.stack - key: ${{ matrix.command }}-deps-ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}-${{ matrix.name }} + key: ${{ matrix.command }}-deps-ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}-${{ matrix.name }}${{ steps.xcode.outputs.toolchain }} # Deps are test/options specific - name: Restore build dependencies, hackage index, local/bin (Windows) @@ -401,7 +421,8 @@ jobs: ARGS="$ARGS CABAL_BUILDDIR=\"/c/b\" WINVER=$WINVER" ARGS="$ARGS NUMBER_OF_PROCESSORS=$NUMBER_OF_PROCESSORS" ARGS="$ARGS PROCESSOR_IDENTIFIER=\"$PROCESSOR_IDENTIFIER\"" - PATH_VAR="$PATH_VAR:/c/ghcup:/c/Program Files/7-Zip:/mingw64/bin" + # Git for Windows 2.56 moved /mingw64 to /ucrt64 + PATH_VAR="$PATH_VAR:/c/ghcup:/c/Program Files/7-Zip:/ucrt64/bin:/mingw64/bin" ;; esac ARGS="$ARGS PATH=\"$PATH_VAR\"" @@ -436,7 +457,7 @@ jobs: if: always() && steps.deps-only.outcome == 'success' && runner.os != 'Windows' && steps.restore-ghcup.outputs.cache-hit != 'true' with: path: ~/.ghcup - key: ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }} + key: ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}${{ steps.xcode.outputs.toolchain }} # On Windows, ghc restore step takes 2-3 minutes whereas installing # GHC takes less than 2 minutes. On top of this saving the ghc cache @@ -458,7 +479,7 @@ jobs: ~/.local/bin ~/.local/state/cabal ~/.stack - key: ${{ matrix.command }}-deps-ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}-${{ matrix.name }} + key: ${{ matrix.command }}-deps-ghc-${{ matrix.ghc_version }}-v${{ matrix.ghc_salt }}-${{ matrix.runner }}-${{ matrix.name }}${{ steps.xcode.outputs.toolchain }} # hackage package index is part of C:/cabal # Deps are test/options specific, hence, matrix.name in the key From 334ee81b888a1196b9bd9a0ef22f3e61e549bf79 Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Thu, 15 Oct 2026 14:47:33 +0530 Subject: [PATCH 2/4] Fix the cache paths and remove the dead mirror in the CircleCI config cabal 3.10 and later keep the package store in ~/.local/state/cabal, so cache ~/.local instead of ~/.local/bin. Fall back to the master branch's cache, then to any branch's cache, when the branch has none. hackage.fpcomplete.com no longer resolves, so remove it as the hackage mirror. --- .circleci/config.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ce911d90..a1822ebb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,7 +45,6 @@ env: &env # cabal options # ------------------------------------------------------------------------ CABAL_CHECK_RELAX: "y" - CABAL_HACKAGE_MIRROR: "hackage.haskell.org:http://hackage.fpcomplete.com" CABAL_PROJECT: "cabal.project" # ------------------------------------------------------------------------ @@ -134,13 +133,19 @@ preinstall: &preinstall restore: &restore # Needs to happen after installing ca-certificates restore_cache: - key: v1-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }} + keys: + - v1-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }} + # Fallback to master branch's cache. + - v1-{{ .Environment.CIRCLE_JOB }}-master + # Fallback to any branch's cache. + - v1-{{ .Environment.CIRCLE_JOB }}- save: &save save_cache: key: v1-{{ .Environment.CIRCLE_JOB }}-{{ .Branch }} paths: - - ~/.local/bin + # cabal 3.10 and later use ~/.local/bin and ~/.local/state/cabal + - ~/.local - ~/.cabal - ~/.stack - ~/.ghcup From 20514de6ae27035b0406b4ed46d628c806e40b49 Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Thu, 15 Oct 2026 15:39:51 +0530 Subject: [PATCH 3/4] Download the native stack binary on arm64 fetch_stack always downloaded the x86_64 stack binary. On arm64 macOS it runs under Rosetta and installs an x86_64 GHC, whose link fails with the Command Line Tools SDK on the current GitHub macOS images. Pick the osx or linux binary for the machine architecture, x86_64 or aarch64. --- packcheck.sh | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packcheck.sh b/packcheck.sh index a46d0c61..c6336b2f 100755 --- a/packcheck.sh +++ b/packcheck.sh @@ -801,13 +801,17 @@ EOF # fi #} +# $1: directory to place stack executable in +# $2: architecture, x86_64 or aarch64 fetch_stack_osx() { - curl --fail -sSkL https://www.stackage.org/stack/osx-x86_64 \ + curl --fail -sSkL https://www.stackage.org/stack/osx-$2 \ | tar xz --strip-components=1 -C $1 --include '*/stack' } +# $1: directory to place stack executable in +# $2: architecture, x86_64 or aarch64 fetch_stack_linux() { - curl --fail -sSkL https://www.stackage.org/stack/linux-x86_64 \ + curl --fail -sSkL https://www.stackage.org/stack/linux-$2 \ | tar xz --strip-components=1 -C $1 --wildcards '*/stack' } @@ -820,9 +824,17 @@ fetch_stack_windows() { fetch_stack() { mkdir -p $1 local os=$(uname) + # Use the native binary, an x86_64 stack on arm64 macOS runs under + # Rosetta and installs an x86_64 GHC. + local arch=$(uname -m) + case "$arch" in + x86_64|amd64) arch=x86_64 ;; + arm64|aarch64) arch=aarch64 ;; + *) die "Unknown architecture [$arch]" ;; + esac case "$os" in - Darwin) retry_cmd fetch_stack_osx $1 ;; - Linux) retry_cmd fetch_stack_linux $1 ;; + Darwin) retry_cmd fetch_stack_osx $1 $arch ;; + Linux) retry_cmd fetch_stack_linux $1 $arch ;; CYGWIN*|MINGW*|MSYS*) retry_cmd fetch_stack_windows $1 ;; *) die "Unknown OS [$os]" ;; esac From b96dc870fb4a562bf8a26e1b32b78ee94e9a7715 Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Thu, 15 Oct 2026 14:47:34 +0530 Subject: [PATCH 4/4] Bump the packcheck commit in the CI config templates --- .circleci/config.yml | 2 +- .cirrus.yml | 2 +- .github/workflows/packcheck.yml | 2 +- appveyor.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a1822ebb..f8153deb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -64,7 +64,7 @@ env: &env # If you have not committed packcheck.sh in your repo at PACKCHECK # then it is automatically pulled from this URL. PACKCHECK_GITHUB_URL: "https://raw.githubusercontent.com/composewell/packcheck" - PACKCHECK_GITHUB_COMMIT: "dd6862df527f317fd4987afa523fba3f4fde7e19" + PACKCHECK_GITHUB_COMMIT: "20514de6ae27035b0406b4ed46d628c806e40b49" # ubuntu seems to have better support than debian on CI systems docker: diff --git a/.cirrus.yml b/.cirrus.yml index 7d54b964..eeea227e 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -56,7 +56,7 @@ task: # If you have not committed packcheck.sh in your repo at PACKCHECK # then it is automatically pulled from this URL. PACKCHECK_GITHUB_URL: "https://raw.githubusercontent.com/composewell/packcheck" - PACKCHECK_GITHUB_COMMIT: "4efa717bc63b4bbd0501a07df5c610849e5d6281" + PACKCHECK_GITHUB_COMMIT: "20514de6ae27035b0406b4ed46d628c806e40b49" cabal_cache: folder: ~/.cabal diff --git a/.github/workflows/packcheck.yml b/.github/workflows/packcheck.yml index eb7148ec..427f9ab6 100644 --- a/.github/workflows/packcheck.yml +++ b/.github/workflows/packcheck.yml @@ -109,7 +109,7 @@ jobs: # If you have not committed packcheck.sh in your repo at PACKCHECK # then it is automatically pulled from this URL. PACKCHECK_GITHUB_URL: "https://raw.githubusercontent.com/composewell/packcheck" - PACKCHECK_GITHUB_COMMIT: "b91dd7daf50d91047ca8c1cce47e8634e34dfcbc" + PACKCHECK_GITHUB_COMMIT: "20514de6ae27035b0406b4ed46d628c806e40b49" # ubuntu seems to have better support than debian on CI systems runs-on: ${{ matrix.runner }} diff --git a/appveyor.yml b/appveyor.yml index f245b5cf..ec87b5a9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -58,7 +58,7 @@ environment: # If you have not committed packcheck.sh in your repo at PACKCHECK_LOCAL_PATH # then it is automatically pulled from this URL. PACKCHECK_GITHUB_URL: "https://raw.githubusercontent.com/composewell/packcheck" - PACKCHECK_GITHUB_COMMIT: "4efa717bc63b4bbd0501a07df5c610849e5d6281" + PACKCHECK_GITHUB_COMMIT: "20514de6ae27035b0406b4ed46d628c806e40b49" # Override the temp directory to avoid sed escaping issues # See https://github.com/haskell/cabal/issues/5386