Skip to content

Bump fortran-lang/setup-fpm from 7 to 8 #2800

Bump fortran-lang/setup-fpm from 7 to 8

Bump fortran-lang/setup-fpm from 7 to 8 #2800

Workflow file for this run

name: CI
on:
push:
pull_request:
release:
types: [published]
env:
CI: "ON" # We can detect this in the build system and other vendors implement it
HOMEBREW_NO_ANALYTICS: "ON" # Make Homebrew installation a little quicker
HOMEBREW_NO_AUTO_UPDATE: "ON"
HOMEBREW_NO_BOTTLE_SOURCE_FALLBACK: "ON"
HOMEBREW_NO_GITHUB_API: "ON"
HOMEBREW_NO_INSTALL_CLEANUP: "ON"
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-14, windows-latest]
toolchain:
- {compiler: gcc, version: 10}
- {compiler: gcc, version: 11}
- {compiler: gcc, version: 12}
- {compiler: gcc, version: 13}
- {compiler: gcc, version: 14}
- {compiler: gcc, version: 15}
- {compiler: intel, version: 2025.2}
exclude:
- os: macos-14 # No Intel on MacOS anymore since 2024
toolchain: {compiler: intel, version: '2025.1'}
- os: macos-14 # Intel compiler does not support ARM (macos-14)
toolchain: {compiler: intel, version: '2025.2'}
- os: macos-14 # gcc@10 not available on macos-14 (ARM64)
toolchain: {compiler: gcc, version: 10}
- os: windows-latest # Doesn't pass build and tests yet
toolchain: {compiler: intel, version: '2025.2'}
- os: windows-latest # gcc 14 not available on Windows yet
toolchain: {compiler: gcc, version: 14}
- os: windows-latest # gcc 15 not available on Windows yet
toolchain: {compiler: gcc, version: 15}
- os: ubuntu-latest # gcc 15 not available on Ubuntu via setup-fortran yet
toolchain: {compiler: gcc, version: 15}
include:
- os: ubuntu-latest
os-arch: linux-x86_64
release-flags: --flag '--static -g -fbacktrace -O3'
- os: macos-14
os-arch: macos-x86_64
release-flags: --flag '-g -fbacktrace -O3'
- os: windows-latest
os-arch: windows-x86_64
release-flags: --flag '--static -g -fbacktrace -O3'
exe: .exe
- os: macos-14
toolchain: {compiler: gcc, version: 15}
release-flags: --flag '-g -fbacktrace -Og -fcheck=all,no-recursion -Wno-external-argument-mismatch'
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Setup Fortran compiler
uses: fortran-lang/[email protected]
id: setup-fortran
with:
compiler: ${{ matrix.toolchain.compiler }}
version: ${{ matrix.toolchain.version }}
# Phase 1: Bootstrap fpm with existing version
- name: Install fpm
uses: fortran-lang/setup-fpm@v8
with:
fpm-version: 'v0.12.0'
# Backport gfortran shared libraries to the paths expected by the bootstrap fpm binary.
# The macOS x86_64 release used for bootstrapping has hardcoded library paths from the gcc version
# it was built with. If the versions match, skip this step. Otherwise, create symlinks.
# On ARM64 it runs under Rosetta 2 and needs /usr/local paths.
- name: MacOS patch libgfortran
if: contains(matrix.os, 'macos')
run: |
which gfortran-${{ matrix.toolchain.version }}
which gfortran
BREW_PREFIX=$(brew --prefix)
# Query the actual library paths that fpm expects
echo "Checking library dependencies of fpm bootstrap binary..."
otool -L $(which fpm)
# Extract the gcc version from the bootstrap binary's library paths
BOOTSTRAP_GCC_VERSION=$(otool -L $(which fpm) | grep -o 'gcc@[0-9]\+' | head -n 1 | cut -d@ -f2)
if [ -z "$BOOTSTRAP_GCC_VERSION" ]; then
# Try alternative pattern: /lib/gcc/13/ -> extract 13
BOOTSTRAP_GCC_VERSION=$(otool -L $(which fpm) | grep libgfortran | grep -o '/lib/gcc/[0-9]\+/' | grep -o '[0-9]\+' | head -n 1)
fi
echo "Bootstrap fpm built with gcc@$BOOTSTRAP_GCC_VERSION"
echo "Current toolchain: gcc@${{ matrix.toolchain.version }}"
if [ "$BOOTSTRAP_GCC_VERSION" == "${{ matrix.toolchain.version }}" ]; then
echo "✓ Bootstrap gcc version matches current toolchain - no patching needed"
exit 0
fi
echo "⚠ Version mismatch detected - creating compatibility symlinks..."
# Find the actual Cellar path by following the symlink
if [ -L "${BREW_PREFIX}/opt/gcc@${{ matrix.toolchain.version }}" ]; then
GCC_CELLAR_PATH=$(cd -P "${BREW_PREFIX}/opt/gcc@${{ matrix.toolchain.version }}" && pwd)
else
GCC_CELLAR_PATH="${BREW_PREFIX}/Cellar/gcc@${{ matrix.toolchain.version }}"/*
fi
echo "GCC Cellar path: $GCC_CELLAR_PATH"
# Find the actual library files
CURRENT_GFORTRAN=$(find "$GCC_CELLAR_PATH"/lib/gcc/${{ matrix.toolchain.version }} -name "libgfortran.*.dylib" 2>/dev/null | head -n 1)
CURRENT_QUADMATH=$(find "$GCC_CELLAR_PATH"/lib/gcc/${{ matrix.toolchain.version }} -name "libquadmath.*.dylib" 2>/dev/null | head -n 1)
CURRENT_GCC_S=$(find "$GCC_CELLAR_PATH"/lib/gcc/${{ matrix.toolchain.version }} -name "libgcc_s.*.dylib" 2>/dev/null | head -n 1)
echo "Current gcc@${{ matrix.toolchain.version }} libraries:"
echo " libgfortran: $CURRENT_GFORTRAN"
echo " libquadmath: $CURRENT_QUADMATH"
echo " libgcc_s: $CURRENT_GCC_S"
# Extract the expected libgfortran path and create symlink
LIBGFORTRAN_PATH=$(otool -L $(which fpm) | grep libgfortran | awk '{print $1}' | head -n 1)
if [ -n "$LIBGFORTRAN_PATH" ] && [ -n "$CURRENT_GFORTRAN" ]; then
TARGET_DIR=$(dirname "$LIBGFORTRAN_PATH")
echo "Creating directory: $TARGET_DIR"
sudo mkdir -p "$TARGET_DIR"
echo "Linking $CURRENT_GFORTRAN to $LIBGFORTRAN_PATH"
sudo ln -fs "$CURRENT_GFORTRAN" "$LIBGFORTRAN_PATH"
fi
# Extract the expected libquadmath path and create symlink
LIBQUADMATH_PATH=$(otool -L $(which fpm) | grep libquadmath | awk '{print $1}' | head -n 1)
if [ -n "$LIBQUADMATH_PATH" ] && [ -n "$CURRENT_QUADMATH" ]; then
TARGET_DIR=$(dirname "$LIBQUADMATH_PATH")
echo "Creating directory: $TARGET_DIR"
sudo mkdir -p "$TARGET_DIR"
echo "Linking $CURRENT_QUADMATH to $LIBQUADMATH_PATH"
sudo ln -fs "$CURRENT_QUADMATH" "$LIBQUADMATH_PATH"
fi
# Extract the expected libgcc_s path and create symlink
LIBGCC_PATH=$(otool -L $(which fpm) | grep libgcc_s | awk '{print $1}' | head -n 1)
if [ -n "$LIBGCC_PATH" ] && [ -n "$CURRENT_GCC_S" ]; then
TARGET_DIR=$(dirname "$LIBGCC_PATH")
echo "Creating directory: $TARGET_DIR"
sudo mkdir -p "$TARGET_DIR"
echo "Linking $CURRENT_GCC_S to $LIBGCC_PATH"
sudo ln -fs "$CURRENT_GCC_S" "$LIBGCC_PATH"
fi
# gcc and g++ will point to clang/clang++: use versioned alias for fpm
- name: MacOS patch C and C++ compilers
if: contains(matrix.os, 'macos')
run: |
echo "CC=gcc-${{ matrix.toolchain.version }}" >> $GITHUB_ENV
echo "FPM_CC=gcc-${{ matrix.toolchain.version }}" >> $GITHUB_ENV
echo "CXX=g++-${{ matrix.toolchain.version }}" >> $GITHUB_ENV
echo "FPM_CXX=g++-${{ matrix.toolchain.version }}" >> $GITHUB_ENV
echo "FPM_LDFLAGS=-lstdc++" >> $GITHUB_ENV
- name: Remove fpm from path
shell: bash
run: |
mv $(which fpm) fpm-bootstrap${{ matrix.exe }}
echo "BOOTSTRAP=$PWD/fpm-bootstrap" >> $GITHUB_ENV
- name: Build Fortran fpm (bootstrap)
shell: bash
run: |
${{ env.BOOTSTRAP }} build
- name: Run Fortran fpm (bootstrap)
shell: bash
run: |
${{ env.BOOTSTRAP }} run
${{ env.BOOTSTRAP }} run -- --version
${{ env.BOOTSTRAP }} run -- --help
- name: Test Fortran fpm (bootstrap)
shell: bash
run: |
${{ env.BOOTSTRAP }} test --flag " -Wno-external-argument-mismatch"
- name: Install Fortran fpm (bootstrap)
shell: bash
run: |
${{ env.BOOTSTRAP }} install
# Phase 2: Bootstrap fpm with itself
- name: Replace bootstrapping version
shell: bash
run: |
${{ env.BOOTSTRAP }} run --runner cp -- fpm-debug${{ matrix.exe }}
rm -v ${{ env.BOOTSTRAP }}
echo "FPM=$PWD/fpm-debug" >> $GITHUB_ENV
- name: Get version (normal)
if: github.event_name != 'release'
shell: bash
run: |
VERSION=$(git rev-parse --short HEAD)
echo "VERSION=$VERSION" >> $GITHUB_ENV
- name: Get version (release)
if: github.event_name == 'release'
shell: bash
run: |
VERSION=$(echo ${{ github.ref }} | cut -dv -f2)
echo "VERSION=$VERSION" >> $GITHUB_ENV
FPM_VERSION=$(${{ env.FPM }} --version | grep -o '${{ env.REGEX }}')
[ "$VERSION" = "$FPM_VERSION" ]
env:
REGEX: '[0-9]\{1,4\}\.[0-9]\{1,4\}\.[0-9]\{1,4\}'
- name: Build Fortran fpm
shell: bash
run: |
${{ env.FPM }} build ${{ matrix.release-flags }}
- name: Run Fortran fpm
shell: bash
run: |
${{ env.FPM }} run ${{ matrix.release-flags }}
${{ env.FPM }} run ${{ matrix.release-flags }} -- --version
${{ env.FPM }} run ${{ matrix.release-flags }} -- --help
- name: Test Fortran fpm
shell: bash
run: |
${{ env.FPM }} test ${{ matrix.release-flags }}
- name: Install Fortran fpm
shell: bash
run: |
${{ env.FPM }} install ${{ matrix.release-flags }}
- name: Package release version
shell: bash
run: |
${{ env.FPM }} run ${{ matrix.release-flags }} --runner cp -- ${{ env.EXE }}
rm -v ${{ env.FPM }}
echo "FPM_RELEASE=${{ env.EXE }}" >> $GITHUB_ENV
env:
EXE: fpm-${{ env.VERSION }}-${{ matrix.os-arch }}-gcc-${{ matrix.toolchain.version }}${{ matrix.exe }}
- name: Run release version
shell: bash
run: |
ci/run_tests.sh "$PWD/${{ env.FPM_RELEASE }}"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.FPM_RELEASE }}
path: ${{ env.FPM_RELEASE }}
make-installer:
if: ${{ github.event_name == 'release' && contains(github.ref, 'v') || github.event_name == 'push' }}
runs-on: windows-latest
needs:
- build
strategy:
fail-fast: false
matrix:
gcc_v: [11,12,13]
steps:
- uses: actions/checkout@v5
- name: Download Artifacts
id: download_windows_artifacts
uses: actions/download-artifact@v5
with:
path: ${{ github.workspace }}
pattern: fpm-*-windows-*-gcc-${{ matrix.gcc_v }}.exe
- name: Get version (normal)
if: github.event_name != 'release'
shell: bash
run: |
VERSION=$(git rev-parse --short HEAD)
echo "VERSION=$VERSION" >> $GITHUB_ENV
- name: Get version (release)
if: github.event_name == 'release'
shell: bash
run: |
VERSION=$(echo ${{ github.ref }} | cut -dv -f2)
echo "VERSION=$VERSION" >> $GITHUB_ENV
env:
REGEX: '[0-9]\{1,4\}\.[0-9]\{1,4\}\.[0-9]\{1,4\}'
- name: Setup MinGW (MSYS2)
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: false
install: >-
wget
unzip
- name: Fetch Windows executable
shell: msys2 {0}
run: |
set -e
download_path='${{ steps.download_windows_artifacts.outputs.download-path }}'
download_path=$(printf '%s\n' "$download_path" | head -n1)
if [ -z "$download_path" ]; then
echo "download-artifact did not report a download path" >&2
exit 1
fi
if command -v cygpath >/dev/null 2>&1; then
posix_path=$(cygpath -u "$download_path")
else
posix_path="$download_path"
fi
exe_path=$(find "$posix_path" -maxdepth 2 -type f -name "fpm-*-windows-*-gcc-${{ matrix.gcc_v }}.exe" | head -n 1)
if [ -z "$exe_path" ]; then
echo "Windows executable not found under $posix_path" >&2
ls -al "$posix_path" || true
exit 1
fi
cp "$exe_path" ./ci/fpm.exe
- name: Fetch Git for Windows
shell: msys2 {0}
run: |
cd ./ci
wget ${{ env.git_download }} -O MinGit.zip
unzip MinGit.zip -d MinGit
env:
git_download: "https://github.com/git-for-windows/git/releases/download/v2.33.1.windows.1/MinGit-2.33.1-64-bit.zip"
- name: Fetch EnVar Plugin for NSIS
shell: msys2 {0}
run: |
cd ./ci
wget ${{ env.envar_download }} -O EnVar-Plugin.zip
mkdir EnVar_plugin
unzip EnVar-Plugin.zip -d EnVar_plugin
env:
envar_download: "https://github.com/GsNSIS/EnVar/releases/download/v0.3.1/EnVar-Plugin.zip"
- name: Install NSIS
run: choco install nsis -y
shell: pwsh
- name: Add NSIS to PATH
shell: pwsh
run: |
$dirs = @(
"${env:ProgramFiles(x86)}\NSIS",
"${env:ProgramFiles}\NSIS"
) | Where-Object { $_ -and (Test-Path $_) }
if (-not $dirs) { throw "NSIS not found under Program Files." }
$dirs | ForEach-Object { $_ | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append }
- name: Generate installer
run: |
cd ./ci
makensis fpm-installer.nsi
move fpm-installer.exe fpm-installer-${{ env.VERSION }}-gcc-${{ matrix.gcc_v }}.exe
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: fpm-installer-gcc-${{ matrix.gcc_v }}
path: ci/fpm-installer-${{ env.VERSION }}-gcc-${{ matrix.gcc_v }}.exe
upload-artifacts:
if: ${{ github.event_name == 'release' && contains(github.ref, 'v') || github.event_name == 'push' }}
runs-on: ubuntu-latest
needs:
- build
- make-installer
steps:
- id: deploy-on-push
if: ${{ github.event_name == 'push' }}
run:
echo "::set-output name=result::${{ env.DEPLOY_BRANCH }}"
env:
DEPLOY_BRANCH: ${{ secrets.DEPLOY_BRANCH && contains(github.ref, secrets.DEPLOY_BRANCH) && 1 || 0 }}
- uses: actions/checkout@v5
if: ${{ github.event_name == 'push' }}
- name: Download Artifacts
uses: actions/download-artifact@v5
with:
path: fpm-cd-artifacts
pattern: 'fpm-*-gcc-12*'
merge-multiple: true
- name: Normalize file names for continuous delivery
if: ${{ github.event_name == 'push' }}
run: |
cd fpm-cd-artifacts
for output in fpm-*; do
mv -v $(basename $output) $(basename $output | sed -E '${{ env.replace }}')
done
env:
replace: 's/-([0-9]+\.[0-9]+\.[0-9]+-[0-9]+-g)?[0-9a-f]+//'
- name: Create SHA256 checksums
run: |
cd fpm-cd-artifacts
for output in fpm-*; do
sha256sum $(basename "$output") | tee $(basename "$output").sha256
done
- name: Move/Create continuous tag
if: ${{ github.event_name == 'push' && steps.deploy-on-push.outputs.result != 0 }}
run: |
git tag --force 'current' ${{ github.sha }}
git push --tags --force
- name: Upload assets
uses: svenstaro/upload-release-action@v2
if: ${{ github.event_name == 'release' || steps.deploy-on-push.outputs.result != 0 }}
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: fpm-cd-artifacts/*
file_glob: true
tag: ${{ github.event_name == 'release' && github.ref || 'current'}}
overwrite: true