From e39f7359a4def87ebe77fd5bb5df97fca15b2d27 Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Tue, 3 Mar 2026 12:10:07 -0800 Subject: [PATCH 1/4] install.sh: Change default compiler to LLVM flang LLVM flang now officially supports PRIF, so that's most likely what an end user actually wants. Update the install script defaults to prefer flang, and prompt to brew install it when missing. Also: * Demote $CXX to be optional, because C++ is an optional dependency. * Add invocation of `brew update` may be required to see the latest llvm/flang * Fix many instances of `${VAR+x}` to `${VAR:+x}`, as the latter also correctly handles set to an empty string. * Remove the unnecessary brew tap of fortran-lang/hombrew-fortran, the fpm cask is now available in the default repository. --- install.sh | 124 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 39 deletions(-) diff --git a/install.sh b/install.sh index 317f6915..9febbe23 100755 --- a/install.sh +++ b/install.sh @@ -45,7 +45,6 @@ Report bugs to fortran@lbl.gov or at https://go.lbl.gov/caffeine EOF } -GCC_VERSION=${GCC_VERSION:=14} GASNET_VERSION="stable" VERBOSE="" GASNET_CONDUIT="${GASNET_CONDUIT:-smp}" @@ -58,7 +57,7 @@ Caffeine and this installer were developed with the following prerequisites. If any are missing and if permission is granted, the installer will install the latest versions using Homebrew: - GCC $GCC_VERSION + LLVM flang GASNet-EX $GASNET_VERSION fpm git (used by fpm to clone dependencies) @@ -115,23 +114,57 @@ while [ "$1" != "" ]; do shift done -set -u # error on use of undefined variable +# Early check for pre-installed Homebrew +BREW="${BREW:-brew}" +if command -v "$BREW" > /dev/null 2>&1; then + BREW_PREFIX=`$BREW --prefix || exit 0` + if [ -z ${BREW_PREFIX:+x} ] || [ ! -d "$BREW_PREFIX" ] ; then + echo Warning: Failed to detect Homebrew prefix + BREW_PREFIX= + fi +fi -if [ -z ${FC+x} ] || [ -z ${CC+x} ] || [ -z ${CXX+x} ]; then - if command -v gfortran-$GCC_VERSION > /dev/null 2>&1; then - FC=`which gfortran-$GCC_VERSION` +if [ -z ${FC:+x} ] || [ -z ${CC:+x} ]; then + if command -v flang > /dev/null 2>&1; then + FC=`which flang` echo "Setting FC=$FC" + if [ -n "$BREW_PREFIX" ] && [[ $FC =~ $BREW_PREFIX ]] ; then + # We are using Homebrew flang, so prefer Homebrew clang/clang++ + export PATH="$BREW_PREFIX/opt/llvm/bin:$PATH" + fi fi - if command -v gcc-$GCC_VERSION > /dev/null 2>&1; then - CC=`which gcc-$GCC_VERSION` + if command -v clang > /dev/null 2>&1; then + CC=`which clang` echo "Setting CC=$CC" fi - if command -v g++-$GCC_VERSION > /dev/null 2>&1; then - CXX=`which g++-$GCC_VERSION` +fi +if [ -n "$CC" ] && ! command -v "$CC" > /dev/null 2>&1; then + echo "CC=$CC not found. If you don't yet have a C compiler, please leave environment variable CC unset." + exit 1 +fi +if [ -n "$FC" ] && ! command -v "$FC" > /dev/null 2>&1; then + echo "FC=$FC not found. If you don't yet have a Fortran compiler, please leave environment variable FC unset." + exit 1 +fi +if [ -z ${CXX:+x} ] && [ -n "$CC" ] ; then + # C++ is an optional dependency + # try to auto-detect from CC + if [[ $(basename $CC) =~ clang ]] ; then + CXX_guess=clang++ + else + CXX_guess=g++ + fi + if [[ $CC =~ (-[0-9]+)$ ]] ; then + CXX_guess=${CXX_guess}${BASH_REMATCH[0]} + fi + if command -v $CXX_guess > /dev/null 2>&1; then + CXX=`which $CXX_guess` echo "Setting CXX=$CXX" fi fi +set -u # error on use of undefined variable + if command -v pkg-config > /dev/null 2>&1; then PKG_CONFIG=`which pkg-config` fi @@ -163,7 +196,7 @@ ask_permission_to_use_homebrew() { cat << EOF -Either one or more of the environment variables FC, CC, and CXX are unset or +Either one or more of the environment variables FC and CC are unset or one or more of the following packages are not in the PATH: pkg-config, realpath, make, fpm. If you grant permission to install prerequisites, you will be prompted before each installation. @@ -212,9 +245,9 @@ exit_if_user_declines() case ${1:-} in *GASNet*) echo "Please ensure the $pkg.pc file is in $PKG_CONFIG_PATH and then rerun './install.sh'." ;; - *GCC*) - echo "To use compilers other than Homebrew-installed gcc-$GCC_VERSION, g++-$GCC_VERSION, and gfortran-$GCC_VERSION," - echo "please set the FC, CC, and CXX environment variables and rerun './install.sh'." ;; + *FC*) + echo "To use compilers other than Homebrew-installed LLVM flang and clang," + echo "please set the FC and CC environment variables and rerun './install.sh'." ;; *) echo "Please ensure that $1 is installed and in your PATH and then rerun './install.sh'." ;; esac @@ -228,13 +261,11 @@ if [ ! -d $DEPENDENCIES_DIR ]; then mkdir -p $DEPENDENCIES_DIR fi -if [ -z ${FC+x} ] || [ -z ${CC+x} ] || [ -z ${CXX+x} ] || [ -z ${PKG_CONFIG+x} ] || [ -z ${REALPATH+x} ] || [ -z ${MAKE+x} ] || [ -z ${FPM+x} ] ; then +if [ -z ${FC:+x} ] || [ -z ${CC:+x} ] || [ -z ${PKG_CONFIG:+x} ] || [ -z ${REALPATH:+x} ] || [ -z ${MAKE:+x} ] || [ -z ${FPM:+x} ] ; then ask_permission_to_use_homebrew exit_if_user_declines "brew" - BREW="brew" - if ! command -v $BREW > /dev/null 2>&1; then ask_permission_to_install_homebrew @@ -264,39 +295,54 @@ EOF fi fi - if [ -z ${FC+x} ] || [ -z ${CC+x} ] || [ -z ${CXX+x} ]; then - ask_permission_to_install_homebrew_package "gfortran, gcc, and g++" "gcc@$GCC_VERSION" - exit_if_user_declines "GCC" - "$BREW" install gcc@$GCC_VERSION - if [ uname == "Linux" ]; then - brew link --force glibc - fi + BREW_PREFIX=`$BREW --prefix || exit 0` + if [ -z ${BREW_PREFIX:+x} ] || [ ! -d "$BREW_PREFIX" ] ; then + echo Failed to detect Homebrew prefix + echo 1 fi - CC=`which gcc-$GCC_VERSION` - CXX=`which g++-$GCC_VERSION` - FC=`which gfortran-$GCC_VERSION` - if [ -z ${REALPATH+x} ] || [ -z ${MAKE+x} ] ; then + # fetch the latest package definitions: + $BREW update + + if [ -z ${FC:+x} ] || [ -z ${CC:+x} ] ; then + ask_permission_to_install_homebrew_package "'llvm' and 'flang'" + exit_if_user_declines "FC" + $BREW install llvm flang + + # Homebrew does not inject clang/clang++ into PATH on macOS + export PATH="$BREW_PREFIX/opt/llvm/bin:$PATH" + CC=`which clang` + CXX=`which clang++` + FC=`which flang-new` + for tool in $CC $CXX $FC ; do + if ! command -v $tool > /dev/null 2>&1 ; then + echo Failed to detect Homebrew compiler install at $tool + exit 1 + fi + done + fi + + if [ -z ${REALPATH:+x} ] || [ -z ${MAKE:+x} ] ; then ask_permission_to_install_homebrew_package "'realpath' and 'make'" "coreutils" - exit_if_user_declines "realpath" - "$BREW" install coreutils + exit_if_user_declines "realpath and make" + $BREW install coreutils + REALPATH=`which realpath` + MAKE=`which make` fi - REALPATH=`which realpath` - if [ -z ${PKG_CONFIG+x} ]; then + if [ -z ${PKG_CONFIG:+x} ]; then ask_permission_to_install_homebrew_package "'pkg-config'" exit_if_user_declines "pkg-config" - "$BREW" install pkg-config + $BREW install pkg-config + PKG_CONFIG=`which pkg-config` fi - PKG_CONFIG=`which pkg-config` - if [ -z ${FPM+x} ] ; then + if [ -z ${FPM:+x} ] ; then ask_permission_to_install_homebrew_package "'fpm'" exit_if_user_declines "fpm" - "$BREW" tap fortran-lang/hombrew-fortran - "$BREW" install fpm + $BREW install fpm + FPM=`which fpm` fi - FPM=`which fpm` fi PREFIX=${PREFIX:-"${HOME}/.local"} @@ -304,7 +350,7 @@ mkdir -p "$PREFIX" PREFIX=`$REALPATH "$PREFIX"` echo "PREFIX=$PREFIX" -if [ -z ${PKG_CONFIG_PATH+x} ]; then +if [ -z ${PKG_CONFIG_PATH:+x} ]; then PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig" else PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH" From e01e5f0244991c0cc8229c6bb5b1f33f78cc3709 Mon Sep 17 00:00:00 2001 From: bonachea Date: Tue, 3 Mar 2026 15:05:01 -0800 Subject: [PATCH 2/4] Automate workaround for issue #228 that arises with brew-installed flang. --- install.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 9febbe23..0105639f 100755 --- a/install.sh +++ b/install.sh @@ -49,6 +49,7 @@ GASNET_VERSION="stable" VERBOSE="" GASNET_CONDUIT="${GASNET_CONDUIT:-smp}" YES=false +APPEND_CFLAGS="" list_prerequisites() { @@ -363,6 +364,13 @@ if [[ $FPM_FC == *flang* ]]; then fi FPM_CC="$($REALPATH $(command -v $CC))" +# workaround issue #228: clang cannot find Homebrew flang's C header +if [ "${BREW_PREFIX:-unset}" != unset ] ; then + if [[ $FPM_FC =~ flang ]] && [[ $FPM_FC =~ $BREW_PREFIX ]] ; then + APPEND_CFLAGS="-I$(dirname $(find "$BREW_PREFIX/Cellar/flang" -name ISO_Fortran_binding.h | head -1))" + fi +fi + ask_package_permission() { cat << EOF @@ -482,7 +490,7 @@ cat << EOF > $CAFFEINE_PC CAFFEINE_FPM_LDFLAGS=$GASNET_LDFLAGS $GASNET_LIB_LOCATIONS CAFFEINE_FPM_FC=$FPM_FC CAFFEINE_FPM_CC=$GASNET_CC -CAFFEINE_FPM_CFLAGS=$GASNET_CFLAGS $GASNET_CPPFLAGS +CAFFEINE_FPM_CFLAGS=$GASNET_CFLAGS $GASNET_CPPFLAGS $APPEND_CFLAGS Name: caffeine Description: Coarray Fortran parallel runtime library URL: https://gitlab.lbl.gov/berkeleylab/caffeine From c8edc4e0ee5063432dd95fa0e11d8d924856dabe Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Tue, 3 Mar 2026 11:47:04 -0800 Subject: [PATCH 3/4] CI: Add coverage for flang brew-installed by install.sh --- .github/workflows/build.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 49738a54..95fe715b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,23 +25,27 @@ jobs: version: 22 network: smp native_multi_image: 1 + brew_via_install: 1 FFLAGS: -fcoarray - os: macos-15 compiler: flang version: 22 network: smp + brew_via_install: 1 native_multi_image: 1 FFLAGS: -fcoarray - os: macos-15-intel compiler: flang version: 22 network: smp + brew_via_install: 1 native_multi_image: 1 FFLAGS: -fcoarray - os: macos-26 compiler: flang version: 22 network: smp + brew_via_install: 1 native_multi_image: 1 FFLAGS: -fcoarray @@ -177,7 +181,7 @@ jobs: echo "CXX=g++-${COMPILER_VERSION}" >> "$GITHUB_ENV" - name: Set flang variables - if: matrix.compiler == 'flang' + if: ${{ matrix.compiler == 'flang' && !matrix.brew_via_install }} run: | set -x echo "FC=flang-new" >> "$GITHUB_ENV" @@ -239,7 +243,7 @@ jobs: apt install -y build-essential pkg-config make git curl - name: Install macOS Dependencies - if: contains(matrix.os, 'macos') + if: ${{ contains(matrix.os, 'macos') && !matrix.brew_via_install }} run: | set -x brew update @@ -247,7 +251,7 @@ jobs: brew install gcc@12 - name: Install LLVM flang on macOS - if: contains(matrix.os, 'macos') && matrix.compiler == 'flang' + if: ${{ contains(matrix.os, 'macos') && matrix.compiler == 'flang' && !matrix.brew_via_install }} run: | set -x brew install llvm@${COMPILER_VERSION} flang @@ -258,6 +262,7 @@ jobs: echo "PATH=$(brew --prefix)/opt/llvm/bin:${PATH}" >> "$GITHUB_ENV" - name: Setup FPM + if: ${{ !matrix.brew_via_install }} uses: fortran-lang/setup-fpm@main with: github-token: ${{ secrets.GITHUB_TOKEN }} @@ -283,7 +288,9 @@ jobs: echo echo PATH="$PATH" for tool in ${FC} ${CC} ${CXX} fpm ; do - ( echo ; set -x ; w=$(which $tool) ; ls -al $w ; ls -alhL $w ; $tool --version ) + if command -v $tool > /dev/null 2>&1 ; then + ( echo ; set -x ; w=$(which $tool) ; ls -al $w ; ls -alhL $w ; $tool --version ) + fi done - name: Build Caffeine (install.sh) From eff5a1dc75d3ed31f4fd7a335e028052e10d85d1 Mon Sep 17 00:00:00 2001 From: bonachea Date: Tue, 3 Mar 2026 16:56:15 -0800 Subject: [PATCH 4/4] README updates --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6282361a..3101849e 100644 --- a/README.md +++ b/README.md @@ -50,9 +50,7 @@ Prerequisites & Dependencies ### Build prerequisites The `install.sh` script uses the following packages: * Fortran and C compilers - * We regularly test with: GNU Fortran versions 13, 14, 15 and LLVM Flang versions 19, 20, 21 - * On macOS the Homebrew-installed `llvm` and `flang` packages may require some - additional settings, see [issue #228](https://github.com/BerkeleyLab/caffeine/issues/228) for the latest information. + * We regularly test with: LLVM Flang versions 19:22 and GNU Fortran versions 13:15 * [Fortran package manager] `fpm` * [pkg-config] * [realpath] @@ -98,7 +96,10 @@ env FC= CC= CXX= ./install.sh