2121 strategy :
2222 fail-fast : false
2323 matrix :
24- os : [ubuntu-latest, macos-13 , windows-latest]
24+ os : [ubuntu-latest, macos-14 , windows-latest]
2525 toolchain :
2626 - {compiler: gcc, version: 10}
2727 - {compiler: gcc, version: 11}
3131 - {compiler: gcc, version: 15}
3232 - {compiler: intel, version: 2025.1}
3333 exclude :
34- - os : macos-13 # No Intel on MacOS anymore since 2024
34+ - os : macos-14 # No Intel on MacOS anymore since 2024
3535 toolchain : {compiler: intel, version: '2025.1'}
36+ - os : macos-14 # gcc@10 not available on macos-14 (ARM64)
37+ toolchain : {compiler: gcc, version: 10}
3638 - os : windows-latest # Doesn't pass build and tests yet
3739 toolchain : {compiler: intel, version: '2025.1'}
3840 - os : windows-latest # gcc 14 not available on Windows yet
@@ -45,14 +47,14 @@ jobs:
4547 - os : ubuntu-latest
4648 os-arch : linux-x86_64
4749 release-flags : --flag '--static -g -fbacktrace -O3'
48- - os : macos-13
50+ - os : macos-14
4951 os-arch : macos-x86_64
5052 release-flags : --flag '-g -fbacktrace -O3'
5153 - os : windows-latest
5254 os-arch : windows-x86_64
5355 release-flags : --flag '--static -g -fbacktrace -O3'
5456 exe : .exe
55- - os : macos-13
57+ - os : macos-14
5658 toolchain : {compiler: gcc, version: 15}
5759 release-flags : --flag '-g -fbacktrace -Og -fcheck=all,no-recursion -Wno-external-argument-mismatch'
5860
@@ -69,25 +71,89 @@ jobs:
6971
7072 # Phase 1: Bootstrap fpm with existing version
7173 - name : Install fpm
72- uses : fortran-lang/setup-fpm@v7
74+ uses : fortran-lang/setup-fpm@v8
7375 with :
74- fpm-version : ' v0.8 .0'
76+ fpm-version : ' v0.12 .0'
7577
76- # Backport gfortran shared libraries to version 10 folder. This is necessary because the macOS release of fpm
77- # 0.10.0 used for bootstrapping has these paths hardcoded in the executable.
78+ # Backport gfortran shared libraries to the paths expected by the bootstrap fpm binary.
79+ # The macOS x86_64 release used for bootstrapping has hardcoded library paths from the gcc version
80+ # it was built with. If the versions match, skip this step. Otherwise, create symlinks.
81+ # On ARM64 it runs under Rosetta 2 and needs /usr/local paths.
7882 - name : MacOS patch libgfortran
79- if : contains(matrix.os, 'macos') && !contains(matrix.toolchain.version, '10')
83+ if : contains(matrix.os, 'macos')
8084 run : |
8185 which gfortran-${{ matrix.toolchain.version }}
8286 which gfortran
83- mkdir /usr/local/opt/gcc@10
84- mkdir /usr/local/opt/gcc@10/lib
85- mkdir /usr/local/opt/gcc@10/lib/gcc
86- mkdir /usr/local/opt/gcc@10/lib/gcc/10
87- mkdir /usr/local/lib/gcc/10
88- ln -fs /usr/local/opt/gcc@${{ matrix.toolchain.version }}/lib/gcc/${{ matrix.toolchain.version }}/libquadmath.0.dylib /usr/local/opt/gcc@10/lib/gcc/10/libquadmath.0.dylib
89- ln -fs /usr/local/opt/gcc@${{ matrix.toolchain.version }}/lib/gcc/${{ matrix.toolchain.version }}/libgfortran.5.dylib /usr/local/opt/gcc@10/lib/gcc/10/libgfortran.5.dylib
90- ln -fs /usr/local/lib/gcc/${{ matrix.toolchain.version }}/libgcc_s.1.dylib /usr/local/lib/gcc/10/libgcc_s.1.dylib
87+ BREW_PREFIX=$(brew --prefix)
88+
89+ # Query the actual library paths that fpm expects
90+ echo "Checking library dependencies of fpm bootstrap binary..."
91+ otool -L $(which fpm)
92+
93+ # Extract the gcc version from the bootstrap binary's library paths
94+ BOOTSTRAP_GCC_VERSION=$(otool -L $(which fpm) | grep -o 'gcc@[0-9]\+' | head -n 1 | cut -d@ -f2)
95+ if [ -z "$BOOTSTRAP_GCC_VERSION" ]; then
96+ # Try alternative pattern: /lib/gcc/13/ -> extract 13
97+ BOOTSTRAP_GCC_VERSION=$(otool -L $(which fpm) | grep libgfortran | grep -o '/lib/gcc/[0-9]\+/' | grep -o '[0-9]\+' | head -n 1)
98+ fi
99+
100+ echo "Bootstrap fpm built with gcc@$BOOTSTRAP_GCC_VERSION"
101+ echo "Current toolchain: gcc@${{ matrix.toolchain.version }}"
102+
103+ if [ "$BOOTSTRAP_GCC_VERSION" == "${{ matrix.toolchain.version }}" ]; then
104+ echo "✓ Bootstrap gcc version matches current toolchain - no patching needed"
105+ exit 0
106+ fi
107+
108+ echo "⚠ Version mismatch detected - creating compatibility symlinks..."
109+
110+ # Find the actual Cellar path by following the symlink
111+ if [ -L "${BREW_PREFIX}/opt/gcc@${{ matrix.toolchain.version }}" ]; then
112+ GCC_CELLAR_PATH=$(cd -P "${BREW_PREFIX}/opt/gcc@${{ matrix.toolchain.version }}" && pwd)
113+ else
114+ GCC_CELLAR_PATH="${BREW_PREFIX}/Cellar/gcc@${{ matrix.toolchain.version }}"/*
115+ fi
116+ echo "GCC Cellar path: $GCC_CELLAR_PATH"
117+
118+ # Find the actual library files
119+ CURRENT_GFORTRAN=$(find "$GCC_CELLAR_PATH"/lib/gcc/${{ matrix.toolchain.version }} -name "libgfortran.*.dylib" 2>/dev/null | head -n 1)
120+ CURRENT_QUADMATH=$(find "$GCC_CELLAR_PATH"/lib/gcc/${{ matrix.toolchain.version }} -name "libquadmath.*.dylib" 2>/dev/null | head -n 1)
121+ CURRENT_GCC_S=$(find "$GCC_CELLAR_PATH"/lib/gcc/${{ matrix.toolchain.version }} -name "libgcc_s.*.dylib" 2>/dev/null | head -n 1)
122+
123+ echo "Current gcc@${{ matrix.toolchain.version }} libraries:"
124+ echo " libgfortran: $CURRENT_GFORTRAN"
125+ echo " libquadmath: $CURRENT_QUADMATH"
126+ echo " libgcc_s: $CURRENT_GCC_S"
127+
128+ # Extract the expected libgfortran path and create symlink
129+ LIBGFORTRAN_PATH=$(otool -L $(which fpm) | grep libgfortran | awk '{print $1}' | head -n 1)
130+ if [ -n "$LIBGFORTRAN_PATH" ] && [ -n "$CURRENT_GFORTRAN" ]; then
131+ TARGET_DIR=$(dirname "$LIBGFORTRAN_PATH")
132+ echo "Creating directory: $TARGET_DIR"
133+ sudo mkdir -p "$TARGET_DIR"
134+ echo "Linking $CURRENT_GFORTRAN to $LIBGFORTRAN_PATH"
135+ sudo ln -fs "$CURRENT_GFORTRAN" "$LIBGFORTRAN_PATH"
136+ fi
137+
138+ # Extract the expected libquadmath path and create symlink
139+ LIBQUADMATH_PATH=$(otool -L $(which fpm) | grep libquadmath | awk '{print $1}' | head -n 1)
140+ if [ -n "$LIBQUADMATH_PATH" ] && [ -n "$CURRENT_QUADMATH" ]; then
141+ TARGET_DIR=$(dirname "$LIBQUADMATH_PATH")
142+ echo "Creating directory: $TARGET_DIR"
143+ sudo mkdir -p "$TARGET_DIR"
144+ echo "Linking $CURRENT_QUADMATH to $LIBQUADMATH_PATH"
145+ sudo ln -fs "$CURRENT_QUADMATH" "$LIBQUADMATH_PATH"
146+ fi
147+
148+ # Extract the expected libgcc_s path and create symlink
149+ LIBGCC_PATH=$(otool -L $(which fpm) | grep libgcc_s | awk '{print $1}' | head -n 1)
150+ if [ -n "$LIBGCC_PATH" ] && [ -n "$CURRENT_GCC_S" ]; then
151+ TARGET_DIR=$(dirname "$LIBGCC_PATH")
152+ echo "Creating directory: $TARGET_DIR"
153+ sudo mkdir -p "$TARGET_DIR"
154+ echo "Linking $CURRENT_GCC_S to $LIBGCC_PATH"
155+ sudo ln -fs "$CURRENT_GCC_S" "$LIBGCC_PATH"
156+ fi
91157
92158 # gcc and g++ will point to clang/clang++: use versioned alias for fpm
93159 - name : MacOS patch C and C++ compilers
@@ -210,6 +276,7 @@ jobs:
210276 - uses : actions/checkout@v5
211277
212278 - name : Download Artifacts
279+ id : download_windows_artifacts
213280 uses : actions/download-artifact@v5
214281 with :
215282 path : ${{ github.workspace }}
@@ -243,7 +310,25 @@ jobs:
243310 - name : Fetch Windows executable
244311 shell : msys2 {0}
245312 run : |
246- cp fpm-*/fpm-*-windows-*-gcc-${{ matrix.gcc_v }}.exe ./ci/fpm.exe
313+ set -e
314+ download_path='${{ steps.download_windows_artifacts.outputs.download-path }}'
315+ download_path=$(printf '%s\n' "$download_path" | head -n1)
316+ if [ -z "$download_path" ]; then
317+ echo "download-artifact did not report a download path" >&2
318+ exit 1
319+ fi
320+ if command -v cygpath >/dev/null 2>&1; then
321+ posix_path=$(cygpath -u "$download_path")
322+ else
323+ posix_path="$download_path"
324+ fi
325+ exe_path=$(find "$posix_path" -maxdepth 2 -type f -name "fpm-*-windows-*-gcc-${{ matrix.gcc_v }}.exe" | head -n 1)
326+ if [ -z "$exe_path" ]; then
327+ echo "Windows executable not found under $posix_path" >&2
328+ ls -al "$posix_path" || true
329+ exit 1
330+ fi
331+ cp "$exe_path" ./ci/fpm.exe
247332
248333 - name : Fetch Git for Windows
249334 shell : msys2 {0}
0 commit comments