From 2494f5f75ce3c88b22e60f3eb171cfaccf03ab6e Mon Sep 17 00:00:00 2001 From: bonachea Date: Fri, 4 Sep 2026 09:51:31 -0700 Subject: [PATCH 01/24] co_broadcast: Remove an incorrect/misleading comment c_sizeof only allows interoperable types --- src/caffeine/co_broadcast_s.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/caffeine/co_broadcast_s.F90 b/src/caffeine/co_broadcast_s.F90 index c9838274f..0bd52f9d9 100644 --- a/src/caffeine/co_broadcast_s.F90 +++ b/src/caffeine/co_broadcast_s.F90 @@ -25,8 +25,6 @@ subroutine contiguous_co_broadcast(a, source_image, stat, errmsg, errmsg_alloc) if (present(stat)) stat=0 call caf_co_broadcast(a, source_image, product(shape(a)), current_team%info%gex_team) - ! With a compliant Fortran 2018 compiler, pass in c_sizeof(a) as the `Nelem` argument - ! and eliminate the calculation of num_elements*sizeof(a) in caffeine.c. end subroutine module procedure prif_co_broadcast_cptr From 8b61ac2c10cc51b9ad0455dd4b0ebf48cf8cb87d Mon Sep 17 00:00:00 2001 From: bonachea Date: Tue, 1 Sep 2026 17:34:41 -0700 Subject: [PATCH 02/24] run-fpm.sh info: Fix CFLAGS output Due to copy-pasta we were printing the wrong value for CFLAGS --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 8fb08e6ca..51ffcc11a 100755 --- a/install.sh +++ b/install.sh @@ -639,7 +639,7 @@ elif echo "info" | grep -w -q -e "\$fpm_sub_cmd" ; then echo FC=\$FC echo CC=\$CC echo FFLAGS=\$FFLAGS - echo CFLAGS=\$FFLAGS + echo CFLAGS=\$CFLAGS echo LDFLAGS=\$LDFLAGS grep -e link \$SRCDIR/fpm.toml echo GASNET=\$GASNETDIR From 39a50c0916506383208dee7ac31355bdfda8b875 Mon Sep 17 00:00:00 2001 From: bonachea Date: Tue, 25 Aug 2026 13:10:04 -0400 Subject: [PATCH 03/24] install: Update --prereqs output Add a new section for library dependencies, and add the version and source --- install.sh | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/install.sh b/install.sh index 51ffcc11a..1850d5c2a 100755 --- a/install.sh +++ b/install.sh @@ -12,6 +12,7 @@ USAGE: --help Display this help text --prefix=PREFIX Install library into 'PREFIX' directory + Default prefix='\$HOME/.local/bin' --network= Build Caffeine to target given GASNet network conduit. should be one of: smp: single-node shared-memory conduit (default) @@ -20,7 +21,6 @@ USAGE: ofi: OpenFabrics Interfaces ucx: Unified Communication X --prereqs Display a list of prerequisite software. - Default prefix='\$HOME/.local/bin' --verbose Show verbose build commands --yes Assume (yes) to all prompts for non-interactive build --enable-threads Build a thread-safe Caffeine library and link to @@ -33,7 +33,6 @@ Some influential environment variables: FFLAGS Fortran compiler flags CC C compiler command CFLAGS C compiler flags - CPP C preprocessor CPPFLAGS C preprocessor flags, e.g. -I if you have headers in a nonstandard directory LDFLAGS linker flags, e.g. -L if you have libraries in a @@ -48,6 +47,11 @@ EOF } GASNET_VERSION="stable" +GASNET_SOURCE_URL="https://github.com/BerkeleyLab/gasnet/releases/download/gex-$GASNET_VERSION/GASNet-$GASNET_VERSION.tar.gz" +ASSERT_GIT=$(awk -F'"' '/^assert =/ {print $2}' manifest/fpm.toml.template) +ASSERT_VERSION=$(awk -F'"' '/^assert =/ {print $4}' manifest/fpm.toml.template) +JULIENNE_GIT=$(awk -F'"' '/^julienne =/ {print $2}' manifest/fpm.toml.template) +JULIENNE_VERSION=$(awk -F'"' '/^julienne =/ {print $4}' manifest/fpm.toml.template) VERBOSE="" GASNET_CONDUIT="${GASNET_CONDUIT:-smp}" GASNET_THREADMODE="${GASNET_THREADMODE:-seq}" @@ -58,19 +62,28 @@ APPEND_LDFLAGS="" list_prerequisites() { cat << EOF -Caffeine and this installer were developed with the following prerequisites. +Caffeine's build system has the following system software prerequisites. If any are missing and if permission is granted, the installer will install the latest versions using Homebrew: - LLVM flang - GASNet-EX $GASNET_VERSION + LLVM flang (or another supported Fortran compiler) fpm - git (used by fpm to clone dependencies) + git (used to clone dependencies) curl pkg-config realpath (Homebrew coreutils) GNU Make (Homebrew coreutils) +The installer will also download and build the following library dependencies, +which are installed along with the Caffeine library to the install prefix: + + GASNet-EX $GASNET_VERSION + - $GASNET_SOURCE_URL + Assert $ASSERT_VERSION + - $ASSERT_GIT + Julienne $JULIENNE_VERSION (optional, only used for unit tests) + - $JULIENNE_GIT + EOF } @@ -404,7 +417,6 @@ if ! $PKG_CONFIG $pkg ; then exit_if_user_declines "GASNet-EX" GASNET_TAR_FILE="$DEPENDENCIES_DIR/GASNet-$GASNET_VERSION.tar.gz" - GASNET_SOURCE_URL="https://github.com/BerkeleyLab/gasnet/releases/download/gex-$GASNET_VERSION/GASNet-$GASNET_VERSION.tar.gz" if [ ! -d $DEPENDENCIES_DIR ]; then mkdir -pv $DEPENDENCIES_DIR fi From d7c67a7851f3827d8d3152d2cf3ad0a2a4f78fab Mon Sep 17 00:00:00 2001 From: bonachea Date: Tue, 1 Sep 2026 15:11:28 -0400 Subject: [PATCH 04/24] CI: Add test coverage for install.sh help outputs --- .github/workflows/build.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0e86cb1f4..f6e9fec63 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -498,6 +498,13 @@ jobs: find $RDIR $BDIR /usr/lib/ -name '*flang_rt*' -exec ls -al {} \; | sort | uniq fi + - name: Test install.sh outputs + run: | + ./install.sh --help 2>&1 | tee output + test ${PIPESTATUS[0]} = 0 && grep -q "fortran@lbl.gov" output + ./install.sh --prereqs 2>&1 | tee output + test ${PIPESTATUS[0]} = 0 && grep -q "GASNet-EX" output + - name: Build Caffeine (install.sh) run: | for var in FC CC CXX FFLAGS CPPFLAGS CFLAGS CXXFLAGS LDFLAGS LIBS GASNET_CONFIGURE_ARGS ; do From a3e1fd07d47e42910f5afce51cea7e7808dac892 Mon Sep 17 00:00:00 2001 From: bonachea Date: Tue, 1 Sep 2026 15:35:31 -0400 Subject: [PATCH 05/24] install.sh: Excise realpath dependency Realpath is not available by default on macOS, but perl is and we already require perl (through GASNet) so use perl instead. This usually eliminates the need for Homebrew coreutils package, because suitable GNU Make is also available by default. run-fpm.sh was already relying on bash-isms, so be explicit that it requires bash. --- install.sh | 49 +++++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/install.sh b/install.sh index 1850d5c2a..d89ba84a0 100755 --- a/install.sh +++ b/install.sh @@ -71,8 +71,7 @@ the latest versions using Homebrew: git (used to clone dependencies) curl pkg-config - realpath (Homebrew coreutils) - GNU Make (Homebrew coreutils) + GNU Make The installer will also download and build the following library dependencies, which are installed along with the Caffeine library to the install prefix: @@ -87,6 +86,25 @@ which are installed along with the Caffeine library to the install prefix: EOF } +realpath() { + set +x + if [ -z "$1" ]; then + echo "ERROR: expected a non-empty pathname" >&2 + return 1 + fi + + perl -e ' + use Cwd "abs_path"; + my $abs = abs_path($ARGV[0]); + if (defined $abs) { + print "$abs\n"; + } else { + print "ERROR: $ARGV[0] does not exist"; + exit 1; + } + ' "$1" +} + # GASNET_CONFIGURE_ARGS is deliberately inherited from the caller environment GASNET_CONFIGURE_ARGS=${GASNET_CONFIGURE_ARGS:=} @@ -190,10 +208,6 @@ if command -v pkg-config > /dev/null 2>&1; then PKG_CONFIG=`which pkg-config` fi -if command -v realpath > /dev/null 2>&1; then - REALPATH=`which realpath` -fi - if command -v make > /dev/null 2>&1; then MAKE=`which make` fi @@ -218,7 +232,7 @@ ask_permission_to_use_homebrew() cat << EOF 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. +one or more of the following packages are not in the PATH: pkg-config, make, fpm. If you grant permission to install prerequisites, you will be prompted before each installation. Press 'Enter' to choose the square-bracketed default answer: @@ -282,7 +296,7 @@ if [ ! -d $DEPENDENCIES_DIR ]; then mkdir -p $DEPENDENCIES_DIR fi -if [ -z ${FC:+x} ] || [ -z ${CC:+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 ${MAKE:+x} ] || [ -z ${FPM:+x} ] ; then ask_permission_to_use_homebrew exit_if_user_declines "brew" @@ -343,11 +357,10 @@ EOF 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 and make" + if [ -z ${MAKE:+x} ] ; then + ask_permission_to_install_homebrew_package "'make'" "coreutils" + exit_if_user_declines "make" $BREW install coreutils - REALPATH=`which realpath` MAKE=`which make` fi @@ -368,7 +381,7 @@ fi PREFIX=${PREFIX:-"${HOME}/.local"} mkdir -p "$PREFIX" -PREFIX=`$REALPATH "$PREFIX"` +PREFIX=$(realpath "$PREFIX") echo "PREFIX=$PREFIX" if [ -z ${PKG_CONFIG_PATH:+x} ]; then @@ -378,12 +391,12 @@ else fi echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH" -FPM_FC="$($REALPATH $(command -v $FC))" +FPM_FC="$(realpath $(command -v $FC))" if [[ $FPM_FC == *flang* ]]; then # issue #358: pattern must only match the end, to avoid false positives on directory components FPM_FC=${FPM_FC/%flang-[1-9][0-9]/flang-new} fi -FPM_CC="$($REALPATH $(command -v $CC))" +FPM_CC="$(realpath $(command -v $CC))" if [ "${BREW_PREFIX:-unset}" != unset ] ; then # fixups necessitated by using Brew flang: @@ -493,7 +506,7 @@ esac # Strip compiler flags # Warning: This assumes the full path doesn't contain any spaces! GASNET_CC_STRIPPED="$(echo $GASNET_CC | awk '{print $1};')" -GASNET_CC_REAL="$($REALPATH $GASNET_CC_STRIPPED)" +GASNET_CC_REAL="$(realpath $GASNET_CC_STRIPPED)" if [ "$GASNET_CC_REAL" != "$FPM_CC" ]; then echo "GASNET_CC=$GASNET_CC_REAL" and "FPM_CC=$FPM_CC don't match" @@ -579,7 +592,7 @@ esac RUN_FPM_SH="run-fpm.sh" cat << EOF > $RUN_FPM_SH -#!/bin/sh +#!/bin/bash #-- DO NOT EDIT -- created by caffeine/install.sh FPM="${FPM}" FC="`$PKG_CONFIG caffeine --variable=CAFFEINE_FPM_FC`" @@ -589,7 +602,7 @@ RAWFLAGS="$compiler_flag" FFLAGS="\$NATIVEFLAGS \$RAWFLAGS" CFLAGS="`$PKG_CONFIG caffeine --variable=CAFFEINE_FPM_CFLAGS`" LDFLAGS="`$PKG_CONFIG caffeine --variable=CAFFEINE_FPM_LDFLAGS`" -FPM_DRIVER=\${FPM_DRIVER:-\`realpath \$0\`} +FPM_DRIVER=\${FPM_DRIVER:-\$([[ "\$0" == /* ]] && echo "\$0" || echo "\$PWD/\$0")} export FPM_DRIVER fpm_sub_cmd=\$1; shift if echo "--help -help --version -version --list -list new update list clean publish" | grep -w -q -e "\$fpm_sub_cmd" ; then From 729a93b02328f9f5fbbbaf31ac7d7c6d33f540bb Mon Sep 17 00:00:00 2001 From: bonachea Date: Thu, 3 Sep 2026 15:41:46 -0700 Subject: [PATCH 06/24] install.sh: Fix detection/installation of GNU Make Homebrew provides GNU Make in the `make` package (not `coreutils`, as previously claimed), and the provided binary is called `gmake`, not `make`. This has probably never been encountered because modern distros of both Linux and macOS already include a `/usr/bin/make` by default. However when probing for make, check for `gmake` first, because it's more likely to give us a newer version when available on macOS. --- install.sh | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/install.sh b/install.sh index d89ba84a0..0f1080aa1 100755 --- a/install.sh +++ b/install.sh @@ -208,7 +208,9 @@ if command -v pkg-config > /dev/null 2>&1; then PKG_CONFIG=`which pkg-config` fi -if command -v make > /dev/null 2>&1; then +if command -v gmake > /dev/null 2>&1; then + MAKE=`which gmake` +elif command -v make > /dev/null 2>&1; then MAKE=`which make` fi @@ -255,10 +257,6 @@ EOF ask_permission_to_install_homebrew_package() { echo "" - if [ ! -z ${2+x} ]; then - echo "Homebrew installs $1 collectively in one package named '$2'." - echo "" - fi printf "Is it ok to use Homebrew to install $1? [yes] " } @@ -358,10 +356,10 @@ EOF fi if [ -z ${MAKE:+x} ] ; then - ask_permission_to_install_homebrew_package "'make'" "coreutils" + ask_permission_to_install_homebrew_package "'make'" exit_if_user_declines "make" - $BREW install coreutils - MAKE=`which make` + $BREW install make + MAKE=`which gmake` fi if [ -z ${PKG_CONFIG:+x} ]; then From aaccf90e53f5cc060a81fa8a81621075299ae045 Mon Sep 17 00:00:00 2001 From: bonachea Date: Tue, 1 Sep 2026 12:45:33 -0700 Subject: [PATCH 07/24] install.sh: Stop asking permission to install GASNet GASNet is a required dependency, and we prefer the install script to install its own copy (or re-use one in the prefix); asking just encourages users to try and manually install GASNet themselves, which basically saves nothing and they are likely to get it wrong. fpm doesn't ask permission to download required dependencies (e.g. Assert), so stop asking permission to download GASNet. --- install.sh | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/install.sh b/install.sh index 0f1080aa1..1671f69d7 100755 --- a/install.sh +++ b/install.sh @@ -276,8 +276,6 @@ exit_if_user_declines() if [ -n "$answer" -a "$answer" != "y" -a "$answer" != "Y" -a "$answer" != "Yes" -a "$answer" != "YES" -a "$answer" != "yes" ]; then echo "Installation declined." case ${1:-} in - *GASNet*) - echo "Please ensure the $pkg.pc file is in $PKG_CONFIG_PATH and then 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'." ;; @@ -409,24 +407,10 @@ if [ "${BREW_PREFIX:-unset}" != unset ] ; then fi fi -ask_package_permission() -{ - cat << EOF - -$1 not found in $2 - -Press 'Enter' for the square-bracketed default answer: -EOF - printf "Is it ok to download and install $1? [yes] " -} - pkg="gasnet-$GASNET_CONDUIT-$GASNET_THREADMODE" export PKG_CONFIG_PATH if ! $PKG_CONFIG $pkg ; then - ask_package_permission "GASNet-EX" "PKG_CONFIG_PATH" - exit_if_user_declines "GASNet-EX" - GASNET_TAR_FILE="$DEPENDENCIES_DIR/GASNet-$GASNET_VERSION.tar.gz" if [ ! -d $DEPENDENCIES_DIR ]; then mkdir -pv $DEPENDENCIES_DIR From 593eb320be2c93a8360d37f735ef6ccc54453740 Mon Sep 17 00:00:00 2001 From: bonachea Date: Tue, 1 Sep 2026 15:56:35 -0700 Subject: [PATCH 08/24] install: Add --{enable,disable}-debug This GASNet configure option is now also recognized by Caffeine install with the following behaviors: * Defaults to --disable-debug (i.e. optimized mode) * Controls the default setting for ASSERTIONS, unless explicitly overridden in CPPFLAGS/FFLAGS. As a result, **Caffeine ASSERTIONS now default to disabled**, which is a change in behavior. * Default Fortran optimization to -O0 in debug mode, otherwise -O3 as before. --- install.sh | 67 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 14 deletions(-) diff --git a/install.sh b/install.sh index 1671f69d7..3af4dadc4 100755 --- a/install.sh +++ b/install.sh @@ -23,6 +23,8 @@ USAGE: --prereqs Display a list of prerequisite software. --verbose Show verbose build commands --yes Assume (yes) to all prompts for non-interactive build + --enable-debug Build Caffeine and GASNet in LOW-PERFORMANCE debug mode, + disabling optimization and enabling assertions to help find defects. --enable-threads Build a thread-safe Caffeine library and link to thread-safe GASNet, for use in threaded do-concurrent. @@ -53,11 +55,15 @@ ASSERT_VERSION=$(awk -F'"' '/^assert =/ {print $4}' manifest/fpm.toml.template) JULIENNE_GIT=$(awk -F'"' '/^julienne =/ {print $2}' manifest/fpm.toml.template) JULIENNE_VERSION=$(awk -F'"' '/^julienne =/ {print $4}' manifest/fpm.toml.template) VERBOSE="" -GASNET_CONDUIT="${GASNET_CONDUIT:-smp}" -GASNET_THREADMODE="${GASNET_THREADMODE:-seq}" YES=false APPEND_CFLAGS="" APPEND_LDFLAGS="" +# these variables deliberately inherited from the caller environment +GASNET_CONDUIT="${GASNET_CONDUIT:-smp}" +GASNET_THREADMODE="${GASNET_THREADMODE:-seq}" +GASNET_CODEMODE="${GASNET_CODEMODE:-opt}" +GASNET_CONFIGURE_ARGS=${GASNET_CONFIGURE_ARGS:-} + list_prerequisites() { @@ -105,8 +111,14 @@ realpath() { ' "$1" } -# GASNET_CONFIGURE_ARGS is deliberately inherited from the caller environment -GASNET_CONFIGURE_ARGS=${GASNET_CONFIGURE_ARGS:=} +append_gasnet_configure_arg() { + if [[ -z "$GASNET_CONFIGURE_ARGS" ]] ; then + GASNET_CONFIGURE_ARGS="\"$1\"" + else + # Quoting is believed sufficient for embedded whitespace but not quotes + GASNET_CONFIGURE_ARGS+=" \"${1//\"/\\\"}\"" + fi +} while [ "$1" != "" ]; do orig_arg="$1" @@ -144,15 +156,27 @@ while [ "$1" != "" ]; do --enable-threads) GASNET_THREADMODE=par ;; --disable-threads) GASNET_THREADMODE=seq ;; - *) - # We pass the unmodified argument to GASNet configure - # Quoting is believed sufficient for embedded whitespace but not quotes - GASNET_CONFIGURE_ARGS+="${GASNET_CONFIGURE_ARGS+ }\"${orig_arg//\"/\\\"}\"" + --enable-debug) GASNET_CODEMODE=debug ; append_gasnet_configure_arg "$orig_arg" ;; + --disable-debug) GASNET_CODEMODE=opt ; append_gasnet_configure_arg "$orig_arg" ;; + + *) # Pass unrecognized args unmodified to GASNet configure + append_gasnet_configure_arg "$orig_arg" ;; esac shift done +if [[ -n "$VERBOSE" ]] ; then +( set +x + echo Command-line arguments: + echo PREFIX=$PREFIX + echo GASNET_CONDUIT=$GASNET_CONDUIT + echo GASNET_CONFIGURE_ARGS=$GASNET_CONFIGURE_ARGS + echo GASNET_THREADMODE=$GASNET_THREADMODE + echo GASNET_CODEMODE=$GASNET_CODEMODE +) +fi + # Early check for pre-installed Homebrew BREW="${BREW:-brew}" if command -v "$BREW" > /dev/null 2>&1; then @@ -523,25 +547,39 @@ exit_if_pkg_config_pc_file_missing "caffeine" user_compiler_flags="${CPPFLAGS:-} ${FFLAGS:-}" +# compiler-specific flag defaults +compiler_flag="-g" +compiler_flag_debug="-O0" +compiler_flag_opt="-O3" compiler_version=$($FPM_FC --version) if [[ $compiler_version =~ 'flang' ]]; then - compiler_flag="-g -O3" + : # use defaults elif [[ $compiler_version =~ 'GNU Fortran' ]]; then - compiler_flag="-g -O3 -ffree-line-length-0 -Wno-unused-dummy-argument" + compiler_flag="-g -ffree-line-length-0 -Wno-unused-dummy-argument" elif [[ $compiler_version =~ 'LFortran' ]]; then - compiler_flag="-O3 --cpp --realloc-lhs-arrays --separate-compilation --no-style-suggestions --implicit-argument-casting" + compiler_flag="--cpp --realloc-lhs-arrays --separate-compilation --no-style-suggestions --implicit-argument-casting" + compiler_flag_debug="" # LFortran -g not always available and leads to bizarre errors when it's not else # unknown compiler - compiler_flag="-g -O2" + compiler_flag_opt=-O2 echo "WARNING: Failed to detect a recognized Fortran compiler" fi +if [[ "$GASNET_CODEMODE" == "debug" ]] ; then + compiler_flag="$compiler_flag_debug $compiler_flag" +else + compiler_flag="$compiler_flag_opt $compiler_flag" +fi + # enable Assert's multi-image support with PRIF callbacks provided by libcaffeine compiler_flag+=" -DASSERT_MULTI_IMAGE -DASSERT_PARALLEL_CALLBACKS" # enable Julienne's multi-image support with PRIF callbacks provided by julienne-driver compiler_flag+=" -DHAVE_MULTI_IMAGE_SUPPORT -DJULIENNE_PARALLEL_CALLBACKS" if ! [[ "$user_compiler_flags " =~ -[DU]ASSERTIONS[=\ ] ]] ; then - # default to enabling assertions, unless the command line sets a relevant flag - compiler_flag+=" -DASSERTIONS" + # assertions not explicitly enabled or disabled on the command-line + # default assertions based on codemode (--enable-debug) + if [[ "$GASNET_CODEMODE" == "debug" ]] ; then + compiler_flag+=" -DASSERTIONS" + fi fi if [[ $GASNET_THREADMODE == "par" ]] ; then @@ -651,6 +689,7 @@ elif echo "info" | grep -w -q -e "\$fpm_sub_cmd" ; then grep -e link \$SRCDIR/fpm.toml echo GASNET=\$GASNETDIR echo GASNET_CONDUIT=$GASNET_CONDUIT + echo GASNET_CODEMODE=$GASNET_CODEMODE echo GASNET_THREADMODE=$GASNET_THREADMODE if test -r "\$GASNETCONFIG"; then grep -e GASNETI_BUILD_ID -e GASNETI_CONFIGURE_ARGS \$GASNETCONFIG | cut -d' ' -f2- From 52c8f275eacf2432df06d001480b6d98479c1ea1 Mon Sep 17 00:00:00 2001 From: bonachea Date: Tue, 1 Sep 2026 19:09:10 -0700 Subject: [PATCH 09/24] issue 241: Ensure that CFLAGS always tracks the ASSERTIONS setting in FFLAGS --- install.sh | 12 +++++++++++- src/caffeine/caffeine.c | 15 ++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/install.sh b/install.sh index 3af4dadc4..1629d30cb 100755 --- a/install.sh +++ b/install.sh @@ -592,6 +592,16 @@ compiler_flag+=" -DCAF_NETWORK_$GASNET_CONDUIT_UPPER" # Should come last to allow command-line overrides compiler_flag+=" $user_compiler_flags" +# Ensure that certain preprocessor settings in FFLAGS are always appended to CFLAGS +APPEND_CFLAGS="" +for opt in $compiler_flag; do + case "$opt" in + -DASSERTIONS* | -UASSERTIONS* | -DFORCE_PRIF_* | -UFORCE_PRIF_*) + APPEND_CFLAGS+=" $opt" + ;; + esac +done + case $GASNET_CONDUIT in ibv|ofi|ucx) GASNET_RUNNER_ARG="${GASNET_RUNNER_ARG:-$GASNET_PREFIX/bin/gasnetrun_$GASNET_CONDUIT -n \${CAF_IMAGES:-2}}" @@ -620,7 +630,7 @@ CC="`$PKG_CONFIG caffeine --variable=CAFFEINE_FPM_CC`" NATIVEFLAGS="" RAWFLAGS="$compiler_flag" FFLAGS="\$NATIVEFLAGS \$RAWFLAGS" -CFLAGS="`$PKG_CONFIG caffeine --variable=CAFFEINE_FPM_CFLAGS`" +CFLAGS="`$PKG_CONFIG caffeine --variable=CAFFEINE_FPM_CFLAGS` $APPEND_CFLAGS" LDFLAGS="`$PKG_CONFIG caffeine --variable=CAFFEINE_FPM_LDFLAGS`" FPM_DRIVER=\${FPM_DRIVER:-\$([[ "\$0" == /* ]] && echo "\$0" || echo "\$PWD/\$0")} export FPM_DRIVER diff --git a/src/caffeine/caffeine.c b/src/caffeine/caffeine.c index 0b4e23fc3..5af811681 100644 --- a/src/caffeine/caffeine.c +++ b/src/caffeine/caffeine.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -20,6 +19,13 @@ #include "caffeine-internal.h" #include "version.h" +// Ensure assertion enforcement in this file tracks the Caffeine ASSERTIONS setting +#undef NDEBUG +#if !ASSERTIONS +#define NDEBUG 1 +#endif +#include + enum { UNRECOGNIZED_TYPE, ERRMSG_TOO_SHORT @@ -51,18 +57,13 @@ CAF_IDENT(Network, CAF_STRINGIFY(GASNET_CONDUIT_NAME)); CAF_IDENT(LibraryVersion, CAF_STRINGIFY(CAF_RELEASE_VERSION_MAJOR) "." CAF_STRINGIFY(CAF_RELEASE_VERSION_MINOR) "." CAF_STRINGIFY(CAF_RELEASE_VERSION_PATCH)); -#if 0 -// TODO: PRIFVersion does not correctly respect FORCE_PRIF_X flags unless they are also passed in CFLAGS CAF_IDENT(PRIFVersion, CAF_STRINGIFY(CAF_PRIF_VERSION_MAJOR) "." CAF_STRINGIFY(CAF_PRIF_VERSION_MINOR)); -#endif -#if 0 -#if ASSERTIONS // TODO: This doesn't yet work, until we fix issue #241 +#if ASSERTIONS CAF_IDENT(Assertions, "1"); #else CAF_IDENT(Assertions, "0"); #endif -#endif CAF_IDENT(BuildTime, __DATE__ " " __TIME__ ); CAF_IDENT(CompilerID, PLATFORM_COMPILER_IDSTR); CAF_IDENT(GASNetConfig, GASNET_CONFIG_STRING); From 23cda26854a84d543a3646f955e1c516d5f04212 Mon Sep 17 00:00:00 2001 From: bonachea Date: Tue, 1 Sep 2026 16:25:47 -0700 Subject: [PATCH 10/24] CI: Update install.sh argument construction Add jobs to cover --disable-debug builds Add command to check ident strings --- .github/workflows/build.yml | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f6e9fec63..0a2eae943 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -181,6 +181,20 @@ jobs: version: 0.63 container: phhargrove/lfortran:0.63.0-1 + # --- OPT coverage --- + - os: ubuntu-24.04 + compiler: flang + version: 23 + label: OPT + CONFIGURE_ARGS: --disable-debug + container: phhargrove/llvm-flang:23.1.0-latest + - os: ubuntu-22.04 + compiler: lfortran + version: 0.65 + label: OPT + CONFIGURE_ARGS: --disable-debug + container: ghcr.io/lfortran/lfortran:v0.65.0 + # --- PRIF-old coverage --- - os: ubuntu-24.04 compiler: flang @@ -280,10 +294,9 @@ jobs: COMPILER_VERSION: ${{ matrix.version || needs.setup.outputs.BREW_FLANG_VERSION }} FFLAGS: ${{ matrix.FFLAGS }} ${{ inputs.fflags }} CFLAGS: ${{ matrix.CFLAGS }} ${{ inputs.cflags }} - PREFIX: install NETWORK_ARG: ${{ matrix.network && format('--network={0}',matrix.network) || '' }} CURL_OPTIONS: -L --retry 10 --retry-all-errors --fail - GASNET_CONFIGURE_ARGS: --enable-rpath --enable-debug + CONFIGURE_ARGS: --prefix=install --enable-rpath --enable-debug --verbose ${{ matrix.CONFIGURE_ARGS }} GASNET_SPAWN_VERBOSE: 1 GASNET_SPAWNFN: L GASNET_MASTERIP: 127.0.0.1 @@ -416,7 +429,7 @@ jobs: echo "CXX=g++-${COMPILER_VERSION}" >> "$GITHUB_ENV" # XCode 26 / gfortran bug workaround if [[ ${{ matrix.os }} =~ macos-26 ]] ; then - echo "GASNET_CONFIGURE_ARGS=$GASNET_CONFIGURE_ARGS --enable-force-posix-realtime" >> "$GITHUB_ENV" + echo "CONFIGURE_ARGS=$CONFIGURE_ARGS --enable-force-posix-realtime" >> "$GITHUB_ENV" fi - name: Set flang variables @@ -509,7 +522,7 @@ jobs: run: | for var in FC CC CXX FFLAGS CPPFLAGS CFLAGS CXXFLAGS LDFLAGS LIBS GASNET_CONFIGURE_ARGS ; do eval echo "$var=\$$var"; done - ./install.sh --prefix=${PREFIX} ${NETWORK_ARG} --verbose \ + ./install.sh ${CONFIGURE_ARGS} ${NETWORK_ARG} \ ${{ inputs.install_args }} ${{ matrix.install_filter }} if ! grep -q 'NATIVEFLAGS=""' run-fpm.sh ; then echo "NATIVE_MULTI_IMAGE=true" >> "$GITHUB_ENV" @@ -521,6 +534,8 @@ jobs: - name: Version info (run-fpm) run: | ./run-fpm.sh info + ./install/bin/ident ./install/lib/libcaffeine.a | tee output + test ${PIPESTATUS[0]} = 0 && grep -q "CaffeineAssertions" output - name: Run examples run: | @@ -593,7 +608,7 @@ jobs: run: | for var in FC CC CXX FFLAGS CPPFLAGS CFLAGS LDFLAGS LIBS GASNET_CONFIGURE_ARGS ; do eval echo "$var=\$$var"; done - ./install.sh --prefix=${PREFIX} ${NETWORK_ARG} --enable-threads --verbose \ + ./install.sh ${CONFIGURE_ARGS} ${NETWORK_ARG} --enable-threads \ ${{ inputs.install_args }} ${{ matrix.install_filter }} ./run-fpm.sh test --verbose -- ${{ inputs.julienne_args }} From 349ed2444313841257152efcbc647f51c264b474 Mon Sep 17 00:00:00 2001 From: bonachea Date: Thu, 3 Sep 2026 15:49:35 -0700 Subject: [PATCH 11/24] install.sh: Fix an outdated warning message --- install.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/install.sh b/install.sh index 1629d30cb..7a3c4a640 100755 --- a/install.sh +++ b/install.sh @@ -332,9 +332,9 @@ if [ -z ${FC:+x} ] || [ -z ${CC:+x} ] || [ -z ${PKG_CONFIG:+x} ] || [ -z ${MAKE: if [ -p /dev/stdin ] && [ $CI = false ]; then cat << EOF -Pipe detected. Installing Homebrew requires sudo privileges, which most likely will -not work if you are installing non-interactively, e.g., via 'yes | ./install.sh'. -To install Caffeine non-interactiely, please rerun the Caffeine installer after +ERROR: Pipe detected. Installing Homebrew requires sudo privileges, +which is unlikely to work if you are installing non-interactively. +To install Caffeine non-interactively, please rerun the Caffeine installer after executing the following command to install Homebrew: "./$DEPENDENCIES_DIR/install-homebrew.sh" EOF From b6c60eeb19d215ced48b5a6eeadcc8cfd59696b6 Mon Sep 17 00:00:00 2001 From: bonachea Date: Thu, 3 Sep 2026 16:00:21 -0700 Subject: [PATCH 12/24] install.sh: Fix Homebrew compiler detection logic The previous logic didn't generate the intended error message when an expected compiler wasn't found, it just exited without a message due to set -e --- install.sh | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/install.sh b/install.sh index 7a3c4a640..26f3c7a4c 100755 --- a/install.sh +++ b/install.sh @@ -366,13 +366,15 @@ EOF # 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 + CC="clang" + CXX="clang++" + FC="flang-new" + for tool in CC CXX FC ; do + if ! command -v ${!tool} > /dev/null 2>&1 ; then + eval echo ERROR: Failed to detect Homebrew compiler install at ${!tool} exit 1 + else + eval $tool=`which ${!tool}` fi done fi From 17dca2b72fd43184fa4c6de8d45daabb40e55b4c Mon Sep 17 00:00:00 2001 From: bonachea Date: Thu, 3 Sep 2026 16:19:43 -0700 Subject: [PATCH 13/24] install.sh: Improve C compiler integration with GASNet Ensure we pass CC to GASNet via full canonical path, and update the mismatch error message to be more informative. Also expand C++ compiler detection to handle Macports clang++, which can have a name like clang++-mp-23 --- install.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/install.sh b/install.sh index 26f3c7a4c..e5e101075 100755 --- a/install.sh +++ b/install.sh @@ -217,7 +217,7 @@ if [ -z ${CXX:+x} ] && [ -n "$CC" ] ; then else CXX_guess=g++ fi - if [[ $CC =~ (-[0-9]+)$ ]] ; then + if [[ $CC =~ (-[0-9a-z-]+)$ ]] ; then CXX_guess=${CXX_guess}${BASH_REMATCH[0]} fi if command -v $CXX_guess > /dev/null 2>&1; then @@ -412,13 +412,16 @@ else PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH" fi echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH" +export PKG_CONFIG_PATH FPM_FC="$(realpath $(command -v $FC))" if [[ $FPM_FC == *flang* ]]; then # issue #358: pattern must only match the end, to avoid false positives on directory components FPM_FC=${FPM_FC/%flang-[1-9][0-9]/flang-new} fi -FPM_CC="$(realpath $(command -v $CC))" +CC="$(realpath $(command -v $CC))" +FPM_CC="$CC" +export FPM_CC if [ "${BREW_PREFIX:-unset}" != unset ] ; then # fixups necessitated by using Brew flang: @@ -434,7 +437,6 @@ if [ "${BREW_PREFIX:-unset}" != unset ] ; then fi pkg="gasnet-$GASNET_CONDUIT-$GASNET_THREADMODE" -export PKG_CONFIG_PATH if ! $PKG_CONFIG $pkg ; then GASNET_TAR_FILE="$DEPENDENCIES_DIR/GASNet-$GASNET_VERSION.tar.gz" @@ -516,8 +518,8 @@ esac GASNET_CC_STRIPPED="$(echo $GASNET_CC | awk '{print $1};')" GASNET_CC_REAL="$(realpath $GASNET_CC_STRIPPED)" -if [ "$GASNET_CC_REAL" != "$FPM_CC" ]; then - echo "GASNET_CC=$GASNET_CC_REAL" and "FPM_CC=$FPM_CC don't match" +if [ "$GASNET_CC_REAL" != "$CC" ]; then + echo "ERROR: C Compiler mismatch: GASNET_CC=$GASNET_CC_REAL and CC=$CC don't match" exit 1; fi From 93bb629e5a6856fbd37123837c9e6122aded65c2 Mon Sep 17 00:00:00 2001 From: bonachea Date: Thu, 3 Sep 2026 18:33:57 -0700 Subject: [PATCH 14/24] CI: Add coverage for older FPM --- .github/workflows/build.yml | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0a2eae943..d24e863bd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -250,6 +250,8 @@ jobs: - os: macos-15 compiler: flang network: udp + label: FPM-0.10 + FPM_VERSION: 0.10.0 - os: macos-26 compiler: flang network: udp @@ -279,6 +281,8 @@ jobs: version: 23 network: udp container: phhargrove/llvm-flang:23.1.0-latest + label: FPM-0.10 + FPM_VERSION: 0.10.0 - os: ubuntu-24.04 compiler: flang version: latest @@ -294,6 +298,7 @@ jobs: COMPILER_VERSION: ${{ matrix.version || needs.setup.outputs.BREW_FLANG_VERSION }} FFLAGS: ${{ matrix.FFLAGS }} ${{ inputs.fflags }} CFLAGS: ${{ matrix.CFLAGS }} ${{ inputs.cflags }} + FPM_VERSION: ${{ matrix.FPM_VERSION || '0.13.0' }} NETWORK_ARG: ${{ matrix.network && format('--network={0}',matrix.network) || '' }} CURL_OPTIONS: -L --retry 10 --retry-all-errors --fail CONFIGURE_ARGS: --prefix=install --enable-rpath --enable-debug --verbose ${{ matrix.CONFIGURE_ARGS }} @@ -402,17 +407,25 @@ jobs: # Prepend Macports clang to PATH: echo "PATH=/opt/local/bin:${PATH}" >> "$GITHUB_ENV" + - name: Choose FPM + if: ${{ !matrix.brew_via_install }} + run: | + if [[ ${{ runner.arch == 'ARM64' && (runner.os == 'Linux' || env.FPM_VERSION < '0.13.0') }} == true ]] ; then + echo "FPM_BUILD=true" >> "$GITHUB_ENV" + else + echo "FPM_SETUP=true" >> "$GITHUB_ENV" + fi + - name: Setup FPM - if: ${{ !matrix.brew_via_install && !(runner.os == 'Linux' && runner.arch == 'ARM64') }} + if: env.FPM_SETUP uses: fortran-lang/setup-fpm@main with: github-token: ${{ secrets.GITHUB_TOKEN }} - fpm-version: latest + fpm-version: v${{ env.FPM_VERSION }} - name: Build FPM - if: ${{ !matrix.brew_via_install && runner.os == 'Linux' && runner.arch == 'ARM64' }} + if: env.FPM_BUILD run: | - export FPM_VERSION=0.13.0 curl --retry 5 -LOsS https://github.com/fortran-lang/fpm/releases/download/v$FPM_VERSION/fpm-$FPM_VERSION.F90 mkdir fpm-temp gfortran-14 -o fpm-temp/fpm fpm-$FPM_VERSION.F90 From 05d249aa2abc2b393a7775084446ce2835c5d852 Mon Sep 17 00:00:00 2001 From: bonachea Date: Thu, 3 Sep 2026 20:01:02 -0700 Subject: [PATCH 15/24] install.sh: Make the flang-new rewrite more robust Only rewrite flang(-[1-9][0-9])? to flang-new when the resulting file exists and shares a real path. --- install.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/install.sh b/install.sh index e5e101075..67c9b0c16 100755 --- a/install.sh +++ b/install.sh @@ -415,9 +415,14 @@ echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH" export PKG_CONFIG_PATH FPM_FC="$(realpath $(command -v $FC))" -if [[ $FPM_FC == *flang* ]]; then - # issue #358: pattern must only match the end, to avoid false positives on directory components - FPM_FC=${FPM_FC/%flang-[1-9][0-9]/flang-new} +if [[ $(basename $FPM_FC) == *flang* ]]; then + # old versions of fpm rely on basename 'flang-new' to recognize LLVM flang, + # so look for a corresponding symlink to the same compiler + TRY_FC=${FPM_FC/%flang-[1-9][0-9]/flang-new} + TRY_FC=${TRY_FC/%flang/flang-new} + if [[ -x $TRY_FC ]] && [[ $(realpath $TRY_FC) == $(realpath $FPM_FC) ]] ; then + FPM_FC=$TRY_FC + fi fi CC="$(realpath $(command -v $CC))" FPM_CC="$CC" From 45d2621ae06f6f8959db864693f839b0791f7c8d Mon Sep 17 00:00:00 2001 From: bonachea Date: Thu, 3 Sep 2026 20:39:05 -0700 Subject: [PATCH 16/24] install.sh: Cleanup use of realpath, which, command and absolute paths Excise most uses of `realpath`: canonical pathnames are only necessary when we need to compare two executables for equality. Some compiler wrappers (and possibly other tools) can change behavior when you unwrap a basename symlink, so stop doing that: we should no longer invoke the result of `realpath`. New function `abspath` returns a non-canonical absolute pathname for a (possibly relative) pathname, without removing symlinks. Don't use `command -v` because it will pick up shell functions and we're always looking for on-disk executables. Use `type -P` instead to check for executables in $PATH. Both `type -P` and `which` can return relative paths (when there are relative paths in $PATH), so don't rely on either to retrieve absolute paths, new function `abswhich` does that. Remove unnecessary/redundant variables FPM_FC and FPM_CC --- install.sh | 121 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 73 insertions(+), 48 deletions(-) diff --git a/install.sh b/install.sh index 67c9b0c16..577bc6762 100755 --- a/install.sh +++ b/install.sh @@ -74,10 +74,9 @@ the latest versions using Homebrew: LLVM flang (or another supported Fortran compiler) fpm - git (used to clone dependencies) - curl pkg-config GNU Make + git + curl (used to download library dependencies) The installer will also download and build the following library dependencies, which are installed along with the Caffeine library to the install prefix: @@ -92,6 +91,35 @@ which are installed along with the Caffeine library to the install prefix: EOF } + +# expand to an absolute path for $1, possibly including symlinks +abspath() { + if [ -z "$1" ]; then + echo "ERROR: expected a non-empty pathname" >&2 + return 1 + fi + + if [[ "$1" == /* ]] ; then + echo "$1" + else + echo "$PWD/$1" + fi +} + +# like `which` but always returns an absolute path or empty +# If $2 is set then failure is suppressed in the exit code +abswhich() { + local cmd_path + if [ -z "$1" ]; then + echo "ERROR: expected a non-empty pathname" >&2 + return 1 + fi + cmd_path=$(type -P -- "$1") || return $( [[ -n "${2:-}" ]] ) + + echo "$(abspath $cmd_path)" +} + +# expand to the absolute path of $1 with all symlinks and non-canonical elements removed realpath() { set +x if [ -z "$1" ]; then @@ -179,7 +207,7 @@ fi # Early check for pre-installed Homebrew BREW="${BREW:-brew}" -if command -v "$BREW" > /dev/null 2>&1; then +if type -P "$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 @@ -188,24 +216,24 @@ if command -v "$BREW" > /dev/null 2>&1; then fi if [ -z ${FC:+x} ] || [ -z ${CC:+x} ]; then - if command -v flang > /dev/null 2>&1; then - FC=`which flang` + if type -P flang > /dev/null 2>&1; then + FC=$(abswhich 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 clang > /dev/null 2>&1; then - CC=`which clang` + if type -P clang > /dev/null 2>&1; then + CC=$(abswhich clang) echo "Setting CC=$CC" fi fi -if [ -n "$CC" ] && ! command -v "$CC" > /dev/null 2>&1; then +if [ -n "$CC" ] && ! type -P "$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 +if [ -n "$FC" ] && ! type -P "$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 @@ -220,35 +248,35 @@ if [ -z ${CXX:+x} ] && [ -n "$CC" ] ; then if [[ $CC =~ (-[0-9a-z-]+)$ ]] ; then CXX_guess=${CXX_guess}${BASH_REMATCH[0]} fi - if command -v $CXX_guess > /dev/null 2>&1; then - CXX=`which $CXX_guess` + if type -P $CXX_guess > /dev/null 2>&1; then + CXX=$(abswhich $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 +# find dependencies, which we might need to install +# allow overrides via envvar +PKG_CONFIG=$(abswhich ${PKG_CONFIG:-pkg-config} silent) -if command -v gmake > /dev/null 2>&1; then - MAKE=`which gmake` -elif command -v make > /dev/null 2>&1; then - MAKE=`which make` -fi +MAKE=$(abswhich ${MAKE:-gmake} silent) # prefer 'gmake' over 'make' +MAKE=$(abswhich ${MAKE:-make} silent) -if command -v fpm > /dev/null 2>&1; then - FPM=`which fpm` -fi +FPM=$(abswhich ${FPM:-fpm} silent) -if ! command -v git > /dev/null 2>&1; then +# FPM disallows override of the git command, so don't allow it here either +# Homebrew requires git and curl to operate, so cannot be used to provide them when they are missing +GIT=$(abswhich git silent) +if [[ -z ${GIT:-} ]] ; then echo "git not found. Building Caffeine requires fpm, which uses git to download dependencies." echo "Please install git, ensure it is in your PATH, and rerun ./install.sh" exit 1 fi -if ! command -v curl > /dev/null 2>&1; then +# FPM disallows override of the curl command, so don't allow it here either +CURL=$(abswhich curl silent) +if [[ -z ${CURL:-} ]] ; then echo "curl not found. Please install curl, ensure it is in your PATH, and rerun ./install.sh" exit 1 fi @@ -321,12 +349,12 @@ if [ -z ${FC:+x} ] || [ -z ${CC:+x} ] || [ -z ${PKG_CONFIG:+x} ] || [ -z ${MAKE: ask_permission_to_use_homebrew exit_if_user_declines "brew" - if ! command -v $BREW > /dev/null 2>&1; then + if ! type -P $BREW > /dev/null 2>&1; then ask_permission_to_install_homebrew exit_if_user_declines "brew" - curl -L https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh -o $DEPENDENCIES_DIR/install-homebrew.sh --create-dirs + $CURL -L https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh -o $DEPENDENCIES_DIR/install-homebrew.sh --create-dirs chmod u+x $DEPENDENCIES_DIR/install-homebrew.sh if [ -p /dev/stdin ] && [ $CI = false ]; then @@ -370,11 +398,11 @@ EOF CXX="clang++" FC="flang-new" for tool in CC CXX FC ; do - if ! command -v ${!tool} > /dev/null 2>&1 ; then + if ! type -P ${!tool} > /dev/null 2>&1 ; then eval echo ERROR: Failed to detect Homebrew compiler install at ${!tool} exit 1 else - eval $tool=`which ${!tool}` + eval $tool=$(abswhich ${!tool}) fi done fi @@ -383,27 +411,27 @@ EOF ask_permission_to_install_homebrew_package "'make'" exit_if_user_declines "make" $BREW install make - MAKE=`which gmake` + MAKE=$(abswhich gmake) fi if [ -z ${PKG_CONFIG:+x} ]; then ask_permission_to_install_homebrew_package "'pkg-config'" exit_if_user_declines "pkg-config" $BREW install pkg-config - PKG_CONFIG=`which pkg-config` + PKG_CONFIG=$(abswhich pkg-config) fi if [ -z ${FPM:+x} ] ; then ask_permission_to_install_homebrew_package "'fpm'" exit_if_user_declines "fpm" $BREW install fpm - FPM=`which fpm` + FPM=$(abswhich fpm) fi fi PREFIX=${PREFIX:-"${HOME}/.local"} mkdir -p "$PREFIX" -PREFIX=$(realpath "$PREFIX") +PREFIX=$(abspath "$PREFIX") echo "PREFIX=$PREFIX" if [ -z ${PKG_CONFIG_PATH:+x} ]; then @@ -414,23 +442,22 @@ fi echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH" export PKG_CONFIG_PATH -FPM_FC="$(realpath $(command -v $FC))" -if [[ $(basename $FPM_FC) == *flang* ]]; then +FC="$(abswhich $FC)" +if [[ $(basename $FC) == *flang* ]]; then # old versions of fpm rely on basename 'flang-new' to recognize LLVM flang, # so look for a corresponding symlink to the same compiler - TRY_FC=${FPM_FC/%flang-[1-9][0-9]/flang-new} + TRY_FC=${FC/%flang-[1-9][0-9]/flang-new} TRY_FC=${TRY_FC/%flang/flang-new} - if [[ -x $TRY_FC ]] && [[ $(realpath $TRY_FC) == $(realpath $FPM_FC) ]] ; then - FPM_FC=$TRY_FC + if [[ -x $TRY_FC ]] && [[ $(realpath $TRY_FC) == $(realpath $FC) ]] ; then + FC="$(abswhich $TRY_FC)" fi fi -CC="$(realpath $(command -v $CC))" -FPM_CC="$CC" -export FPM_CC +CC="$(abswhich $CC)" +CXX="$(abswhich $CXX)" if [ "${BREW_PREFIX:-unset}" != unset ] ; then # fixups necessitated by using Brew flang: - if [[ $FPM_FC =~ flang ]] && [[ $FPM_FC =~ $BREW_PREFIX ]] ; then + if [[ $FC =~ flang ]] && [[ $FC =~ $BREW_PREFIX ]] ; then # workaround issue #228: clang cannot find Homebrew flang's C header APPEND_CFLAGS="-I$(dirname $(find "$BREW_PREFIX/Cellar/flang" -name ISO_Fortran_binding.h | head -1))" @@ -454,7 +481,7 @@ if ! $PKG_CONFIG $pkg ; then rm -Rf $GASNET_DIR fi - curl -L $VERBOSE --retry 10 --retry-all-errors --fail $GASNET_SOURCE_URL -o $GASNET_TAR_FILE + $CURL -L $VERBOSE --retry 10 --retry-all-errors --fail $GASNET_SOURCE_URL -o $GASNET_TAR_FILE tar xvzf $GASNET_TAR_FILE -C $DEPENDENCIES_DIR ( @@ -521,10 +548,8 @@ esac # Strip compiler flags # Warning: This assumes the full path doesn't contain any spaces! GASNET_CC_STRIPPED="$(echo $GASNET_CC | awk '{print $1};')" -GASNET_CC_REAL="$(realpath $GASNET_CC_STRIPPED)" - -if [ "$GASNET_CC_REAL" != "$CC" ]; then - echo "ERROR: C Compiler mismatch: GASNET_CC=$GASNET_CC_REAL and CC=$CC don't match" +if [ "$(realpath $GASNET_CC_STRIPPED)" != "$(realpath $CC)" ]; then + echo "ERROR: C Compiler mismatch: GASNET_CC=$(realpath $GASNET_CC_STRIPPED) and CC=$(realpath $CC) don't match" exit 1; fi @@ -543,7 +568,7 @@ echo "${FPM_TOML_LINK_ENTRY}" >> $FPM_TOML CAFFEINE_PC="$PREFIX/lib/pkgconfig/caffeine.pc" cat << EOF > $CAFFEINE_PC CAFFEINE_FPM_LDFLAGS=$GASNET_LDFLAGS $GASNET_LIB_LOCATIONS $APPEND_LDFLAGS -CAFFEINE_FPM_FC=$FPM_FC +CAFFEINE_FPM_FC=$FC CAFFEINE_FPM_CC=$GASNET_CC CAFFEINE_FPM_CFLAGS=$GASNET_CFLAGS $GASNET_CPPFLAGS $APPEND_CFLAGS Name: caffeine @@ -560,7 +585,7 @@ user_compiler_flags="${CPPFLAGS:-} ${FFLAGS:-}" compiler_flag="-g" compiler_flag_debug="-O0" compiler_flag_opt="-O3" -compiler_version=$($FPM_FC --version) +compiler_version=$($FC --version) if [[ $compiler_version =~ 'flang' ]]; then : # use defaults elif [[ $compiler_version =~ 'GNU Fortran' ]]; then From cd9dead1ff76a8b9a4bdc89c5870b8ff22abc60b Mon Sep 17 00:00:00 2001 From: bonachea Date: Thu, 3 Sep 2026 21:34:14 -0700 Subject: [PATCH 17/24] CI: Stop explicitly setting FC=flang-new Setting FC=flang-new for the benefit of fpm should now always be handled by the install script as appropriate. The only exception is flang versions before 20, where the only executable was named flang-new --- .github/workflows/build.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d24e863bd..914074f07 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -449,7 +449,11 @@ jobs: if: ${{ matrix.compiler == 'flang' }} run: | if [ -z "${{ matrix.brew_via_install }}" ] ; then - echo "FC=flang-new" >> "$GITHUB_ENV" + if [[ $COMPILER_VERSION -le 19 ]] ; then + echo "FC=flang-new" >> "$GITHUB_ENV" + else + echo "FC=flang" >> "$GITHUB_ENV" + fi echo "CC=clang" >> "$GITHUB_ENV" echo "CXX=clang++" >> "$GITHUB_ENV" fi From 0e71bf0109462970aa504ff4c069225e997c71c2 Mon Sep 17 00:00:00 2001 From: bonachea Date: Fri, 4 Sep 2026 15:41:53 -0700 Subject: [PATCH 18/24] install.sh: pkg-config enhancements * Relocate and simplify pkg-config file generation * Additional new pkg-config fields to provide more information * Generate threadmode-codemode variant of the .pc file * Add the gasnet pkg-config dependency, and remove the redundant flags that will be inherited from the gasnet.pc file --- install.sh | 66 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/install.sh b/install.sh index 577bc6762..a8257918e 100755 --- a/install.sh +++ b/install.sh @@ -340,9 +340,7 @@ exit_if_user_declines() } DEPENDENCIES_DIR="build/dependencies" -if [ ! -d $DEPENDENCIES_DIR ]; then - mkdir -p $DEPENDENCIES_DIR -fi +mkdir -p $DEPENDENCIES_DIR if [ -z ${FC:+x} ] || [ -z ${CC:+x} ] || [ -z ${PKG_CONFIG:+x} ] || [ -z ${MAKE:+x} ] || [ -z ${FPM:+x} ] ; then @@ -434,6 +432,8 @@ mkdir -p "$PREFIX" PREFIX=$(abspath "$PREFIX") echo "PREFIX=$PREFIX" +PKG_CONFIG_DIR="$PREFIX/lib/pkgconfig" +mkdir -p "$PKG_CONFIG_DIR" if [ -z ${PKG_CONFIG_PATH:+x} ]; then PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig" else @@ -472,9 +472,6 @@ pkg="gasnet-$GASNET_CONDUIT-$GASNET_THREADMODE" if ! $PKG_CONFIG $pkg ; then GASNET_TAR_FILE="$DEPENDENCIES_DIR/GASNet-$GASNET_VERSION.tar.gz" - if [ ! -d $DEPENDENCIES_DIR ]; then - mkdir -pv $DEPENDENCIES_DIR - fi GASNET_DIR=$DEPENDENCIES_DIR/GASNet-$GASNET_VERSION if [ -d $GASNET_DIR ]; then # clean any existing GASNet build dir we are overwriting @@ -565,20 +562,6 @@ fi FPM_TOML_LINK_ENTRY="link = [\"$(echo ${GASNET_LIB_NAMES} | sed 's/ /", "/g')\"]" echo "${FPM_TOML_LINK_ENTRY}" >> $FPM_TOML -CAFFEINE_PC="$PREFIX/lib/pkgconfig/caffeine.pc" -cat << EOF > $CAFFEINE_PC -CAFFEINE_FPM_LDFLAGS=$GASNET_LDFLAGS $GASNET_LIB_LOCATIONS $APPEND_LDFLAGS -CAFFEINE_FPM_FC=$FC -CAFFEINE_FPM_CC=$GASNET_CC -CAFFEINE_FPM_CFLAGS=$GASNET_CFLAGS $GASNET_CPPFLAGS $APPEND_CFLAGS -Name: caffeine -Description: The CoArray Fortran Framework of Efficient Interfaces to Network Environments (Caffeine) implements the Parallel Runtime Interface for Fortran (PRIF), providing runtime support for multi-image features in modern Fortran compilers. -URL: https://go.lbl.gov/caffeine -Version: 0.8.1 -EOF - -exit_if_pkg_config_pc_file_missing "caffeine" - user_compiler_flags="${CPPFLAGS:-} ${FFLAGS:-}" # compiler-specific flag defaults @@ -627,7 +610,6 @@ compiler_flag+=" -DCAF_NETWORK_$GASNET_CONDUIT_UPPER" compiler_flag+=" $user_compiler_flags" # Ensure that certain preprocessor settings in FFLAGS are always appended to CFLAGS -APPEND_CFLAGS="" for opt in $compiler_flag; do case "$opt" in -DASSERTIONS* | -UASSERTIONS* | -DFORCE_PRIF_* | -UFORCE_PRIF_*) @@ -636,6 +618,38 @@ for opt in $compiler_flag; do esac done +# flag outputs +CAFFEINE_CFLAGS="$GASNET_CFLAGS $GASNET_CPPFLAGS $APPEND_CFLAGS" +CAFFEINE_LDFLAGS="$GASNET_LDFLAGS $GASNET_LIB_LOCATIONS $APPEND_LDFLAGS" + +CAFFEINE_PC="caffeine-$GASNET_CONDUIT-$GASNET_THREADMODE.pc" +cat << EOF > "$PKG_CONFIG_DIR/$CAFFEINE_PC" +# WARNING: This file is automatically generated - do NOT edit directly +# Copyright 2026, The Regents of the University of California +# Terms of use are as specified in license.txt + +CAFFEINE_FC=$FC +CAFFEINE_CC=$CC +CAFFEINE_CFLAGS=$APPEND_CFLAGS +CAFFEINE_LDFLAGS="-L$PREFIX/lib $APPEND_LDFLAGS" +CAFFEINE_NETWORK=$GASNET_CONDUIT +CAFFEINE_THREADMODE=$GASNET_THREADMODE +CAFFEINE_CODEMODE=$GASNET_CODEMODE + +Name: caffeine +Description: The CoArray Fortran Framework of Efficient Interfaces to Network Environments (Caffeine) implements the Parallel Runtime Interface for Fortran (PRIF), providing runtime support for multi-image features in modern Fortran compilers. +URL: https://go.lbl.gov/caffeine +Version: 0.8.1 +Requires: gasnet-$GASNET_CONDUIT-$GASNET_THREADMODE +Cflags: \${CAFFEINE_CFLAGS} +Libs: \${CAFFEINE_LDFLAGS} -lcaffeine-$GASNET_CONDUIT-$GASNET_THREADMODE +EOF +ln -sf "$CAFFEINE_PC" "$PKG_CONFIG_DIR/caffeine-$GASNET_CONDUIT.pc" +ln -sf "$CAFFEINE_PC" "$PKG_CONFIG_DIR/caffeine.pc" + +exit_if_pkg_config_pc_file_missing "caffeine" + + case $GASNET_CONDUIT in ibv|ofi|ucx) GASNET_RUNNER_ARG="${GASNET_RUNNER_ARG:-$GASNET_PREFIX/bin/gasnetrun_$GASNET_CONDUIT -n \${CAF_IMAGES:-2}}" @@ -658,14 +672,14 @@ RUN_FPM_SH="run-fpm.sh" cat << EOF > $RUN_FPM_SH #!/bin/bash #-- DO NOT EDIT -- created by caffeine/install.sh -FPM="${FPM}" -FC="`$PKG_CONFIG caffeine --variable=CAFFEINE_FPM_FC`" -CC="`$PKG_CONFIG caffeine --variable=CAFFEINE_FPM_CC`" +FPM="$FPM" +FC="$FC" +CC="$CC" NATIVEFLAGS="" RAWFLAGS="$compiler_flag" FFLAGS="\$NATIVEFLAGS \$RAWFLAGS" -CFLAGS="`$PKG_CONFIG caffeine --variable=CAFFEINE_FPM_CFLAGS` $APPEND_CFLAGS" -LDFLAGS="`$PKG_CONFIG caffeine --variable=CAFFEINE_FPM_LDFLAGS`" +CFLAGS="$CAFFEINE_CFLAGS" +LDFLAGS="$CAFFEINE_LDFLAGS" FPM_DRIVER=\${FPM_DRIVER:-\$([[ "\$0" == /* ]] && echo "\$0" || echo "\$PWD/\$0")} export FPM_DRIVER fpm_sub_cmd=\$1; shift From d3073b857adf0887a089119b13c3d782eb9c5e6f Mon Sep 17 00:00:00 2001 From: bonachea Date: Fri, 4 Sep 2026 19:29:00 -0700 Subject: [PATCH 19/24] install.sh: Refine FFLAGS computation --- install.sh | 52 +++++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/install.sh b/install.sh index a8257918e..c2aab24d0 100755 --- a/install.sh +++ b/install.sh @@ -562,55 +562,56 @@ fi FPM_TOML_LINK_ENTRY="link = [\"$(echo ${GASNET_LIB_NAMES} | sed 's/ /", "/g')\"]" echo "${FPM_TOML_LINK_ENTRY}" >> $FPM_TOML +# save Fortran flag user inputs user_compiler_flags="${CPPFLAGS:-} ${FFLAGS:-}" # compiler-specific flag defaults -compiler_flag="-g" -compiler_flag_debug="-O0" -compiler_flag_opt="-O3" +FFLAGS="-g" +FFLAGS_debug="-O0" +FFLAGS_opt="-O3" compiler_version=$($FC --version) if [[ $compiler_version =~ 'flang' ]]; then : # use defaults elif [[ $compiler_version =~ 'GNU Fortran' ]]; then - compiler_flag="-g -ffree-line-length-0 -Wno-unused-dummy-argument" + FFLAGS="-g -ffree-line-length-0 -Wno-unused-dummy-argument" elif [[ $compiler_version =~ 'LFortran' ]]; then - compiler_flag="--cpp --realloc-lhs-arrays --separate-compilation --no-style-suggestions --implicit-argument-casting" - compiler_flag_debug="" # LFortran -g not always available and leads to bizarre errors when it's not + # LFortran -g deliberately omitted: not always available, and leads to bizarre errors when it's not + FFLAGS="--cpp --realloc-lhs-arrays --separate-compilation --no-style-suggestions --implicit-argument-casting" else # unknown compiler - compiler_flag_opt=-O2 + FFLAGS_opt=-O2 echo "WARNING: Failed to detect a recognized Fortran compiler" fi if [[ "$GASNET_CODEMODE" == "debug" ]] ; then - compiler_flag="$compiler_flag_debug $compiler_flag" + FFLAGS="$FFLAGS_debug $FFLAGS" else - compiler_flag="$compiler_flag_opt $compiler_flag" + FFLAGS="$FFLAGS_opt $FFLAGS" fi # enable Assert's multi-image support with PRIF callbacks provided by libcaffeine -compiler_flag+=" -DASSERT_MULTI_IMAGE -DASSERT_PARALLEL_CALLBACKS" +FFLAGS+=" -DASSERT_MULTI_IMAGE -DASSERT_PARALLEL_CALLBACKS" # enable Julienne's multi-image support with PRIF callbacks provided by julienne-driver -compiler_flag+=" -DHAVE_MULTI_IMAGE_SUPPORT -DJULIENNE_PARALLEL_CALLBACKS" - -if ! [[ "$user_compiler_flags " =~ -[DU]ASSERTIONS[=\ ] ]] ; then - # assertions not explicitly enabled or disabled on the command-line - # default assertions based on codemode (--enable-debug) - if [[ "$GASNET_CODEMODE" == "debug" ]] ; then - compiler_flag+=" -DASSERTIONS" - fi -fi +FFLAGS+=" -DHAVE_MULTI_IMAGE_SUPPORT -DJULIENNE_PARALLEL_CALLBACKS" if [[ $GASNET_THREADMODE == "par" ]] ; then - compiler_flag+=" -DCAF_THREAD_SAFE" + FFLAGS+=" -DCAF_THREAD_SAFE" fi GASNET_CONDUIT_UPPER=$(tr '[:lower:]' '[:upper:]' <<<$GASNET_CONDUIT) -compiler_flag+=" -DCAF_NETWORK_$GASNET_CONDUIT_UPPER" +FFLAGS+=" -DCAF_NETWORK_$GASNET_CONDUIT_UPPER" -# Should come last to allow command-line overrides -compiler_flag+=" $user_compiler_flags" +# Append user flags last to allow command-line overrides +FFLAGS+=" $user_compiler_flags" + +if ! [[ "$FFLAGS " =~ -[DU]ASSERTIONS[=\ ] ]] ; then + # assertions not explicitly enabled or disabled on the command-line + # default assertions based on codemode (--enable-debug) + if [[ "$GASNET_CODEMODE" == "debug" ]] ; then + FFLAGS+=" -DASSERTIONS" + fi +fi # Ensure that certain preprocessor settings in FFLAGS are always appended to CFLAGS -for opt in $compiler_flag; do +for opt in $FFLAGS; do case "$opt" in -DASSERTIONS* | -UASSERTIONS* | -DFORCE_PRIF_* | -UFORCE_PRIF_*) APPEND_CFLAGS+=" $opt" @@ -630,6 +631,7 @@ cat << EOF > "$PKG_CONFIG_DIR/$CAFFEINE_PC" CAFFEINE_FC=$FC CAFFEINE_CC=$CC +CAFFEINE_FFLAGS=$FFLAGS CAFFEINE_CFLAGS=$APPEND_CFLAGS CAFFEINE_LDFLAGS="-L$PREFIX/lib $APPEND_LDFLAGS" CAFFEINE_NETWORK=$GASNET_CONDUIT @@ -676,7 +678,7 @@ FPM="$FPM" FC="$FC" CC="$CC" NATIVEFLAGS="" -RAWFLAGS="$compiler_flag" +RAWFLAGS="$FFLAGS" FFLAGS="\$NATIVEFLAGS \$RAWFLAGS" CFLAGS="$CAFFEINE_CFLAGS" LDFLAGS="$CAFFEINE_LDFLAGS" From aca87a60b61d72b288f6563819820f9a64c57af9 Mon Sep 17 00:00:00 2001 From: bonachea Date: Mon, 7 Sep 2026 12:22:47 -0700 Subject: [PATCH 20/24] install.sh: Cosmetic improvements to --help output --- install.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/install.sh b/install.sh index c2aab24d0..7ceef9a5d 100755 --- a/install.sh +++ b/install.sh @@ -7,11 +7,11 @@ print_usage_info() cat <<'EOF' Caffeine Installation Script -USAGE: -./install.sh [--help | [--prefix=PREFIX] +Usage: ./install.sh [OPTION]... +Options: --help Display this help text - --prefix=PREFIX Install library into 'PREFIX' directory + --prefix= Install libraries into directory Default prefix='\$HOME/.local/bin' --network= Build Caffeine to target given GASNet network conduit. should be one of: @@ -22,7 +22,7 @@ USAGE: ucx: Unified Communication X --prereqs Display a list of prerequisite software. --verbose Show verbose build commands - --yes Assume (yes) to all prompts for non-interactive build + --yes Assume (yes) to all prompts for non-interactive install --enable-debug Build Caffeine and GASNet in LOW-PERFORMANCE debug mode, disabling optimization and enabling assertions to help find defects. --enable-threads Build a thread-safe Caffeine library and link to @@ -41,7 +41,7 @@ Some influential environment variables: nonstandard directory LIBS libraries to pass to the linker, e.g. -l Use these variables to override the choices made by the installer or to help -it to find libraries and programs with nonstandard names/locations. +it to find programs with nonstandard names/locations. Report bugs to fortran@lbl.gov or at https://go.lbl.gov/caffeine From c92ccdc7acd2bb049769862871b0e938dbaf46de Mon Sep 17 00:00:00 2001 From: bonachea Date: Mon, 7 Sep 2026 12:48:20 -0700 Subject: [PATCH 21/24] install.sh: Fix defaulting of CAF_IMAGES for smp-conduit This was previously defaulting to empty when neither CAF_IMAGES nor GASNET_PSHM_NODES was set, leading to a warning from GASNet at run time. --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 7ceef9a5d..fd5b89c69 100755 --- a/install.sh +++ b/install.sh @@ -663,7 +663,7 @@ case $GASNET_CONDUIT in GASNET_RUNNER_ARG="${GASNET_RUNNER_ARG:-mpirun -n \${CAF_IMAGES:-2}}" ;; smp) - GASNET_RUNNER_ARG="${GASNET_RUNNER_ARG:-env GASNET_PSHM_NODES=\${CAF_IMAGES:-\${GASNET_PSHM_NODES:-}}}" + GASNET_RUNNER_ARG="${GASNET_RUNNER_ARG:-env GASNET_PSHM_NODES=\${CAF_IMAGES:-\${GASNET_PSHM_NODES:-2}}}" ;; *) GASNET_RUNNER_ARG="${GASNET_RUNNER_ARG:-}" From 428f3b634c14924fc2ed24d328d54f1833c8c193 Mon Sep 17 00:00:00 2001 From: bonachea Date: Mon, 7 Sep 2026 14:43:17 -0700 Subject: [PATCH 22/24] install.sh: Misc bash style improvements --- install.sh | 71 ++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/install.sh b/install.sh index fd5b89c69..195b393c8 100755 --- a/install.sh +++ b/install.sh @@ -150,8 +150,8 @@ append_gasnet_configure_arg() { while [ "$1" != "" ]; do orig_arg="$1" - PARAM=$(echo "$1" | awk -F= '{print $1}') - VALUE=$(echo "$1" | awk -F= '{print $2}') + PARAM=$(awk -F= '{print $1}' <<< $1) + VALUE=$(awk -F= '{print $2}' <<< $1) case $PARAM in -h | --help) print_usage_info @@ -208,7 +208,7 @@ fi # Early check for pre-installed Homebrew BREW="${BREW:-brew}" if type -P "$BREW" > /dev/null 2>&1; then - BREW_PREFIX=`$BREW --prefix || exit 0` + BREW_PREFIX=$($BREW --prefix || exit 0) if [ -z ${BREW_PREFIX:+x} ] || [ ! -d "$BREW_PREFIX" ] ; then echo Warning: Failed to detect Homebrew prefix BREW_PREFIX= @@ -229,11 +229,11 @@ if [ -z ${FC:+x} ] || [ -z ${CC:+x} ]; then echo "Setting CC=$CC" fi fi -if [ -n "$CC" ] && ! type -P "$CC" > /dev/null 2>&1; then +if [ -n "${CC:+x}" ] && ! type -P "$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" ] && ! type -P "$FC" > /dev/null 2>&1; then +if [ -n "${FC:+x}" ] && ! type -P "$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 @@ -268,15 +268,15 @@ FPM=$(abswhich ${FPM:-fpm} silent) # FPM disallows override of the git command, so don't allow it here either # Homebrew requires git and curl to operate, so cannot be used to provide them when they are missing GIT=$(abswhich git silent) -if [[ -z ${GIT:-} ]] ; then - echo "git not found. Building Caffeine requires fpm, which uses git to download dependencies." +if [[ -z "$GIT" ]] ; then + echo "git not found. Building Caffeine requires git to download dependencies." echo "Please install git, ensure it is in your PATH, and rerun ./install.sh" exit 1 fi # FPM disallows override of the curl command, so don't allow it here either CURL=$(abswhich curl silent) -if [[ -z ${CURL:-} ]] ; then +if [[ -z "$CURL" ]] ; then echo "curl not found. Please install curl, ensure it is in your PATH, and rerun ./install.sh" exit 1 fi @@ -376,7 +376,7 @@ EOF fi fi - BREW_PREFIX=`$BREW --prefix || exit 0` + BREW_PREFIX=$($BREW --prefix || exit 0) if [ -z ${BREW_PREFIX:+x} ] || [ ! -d "$BREW_PREFIX" ] ; then echo Failed to detect Homebrew prefix echo 1 @@ -510,41 +510,38 @@ exit_if_pkg_config_pc_file_missing() exit_if_pkg_config_pc_file_missing "$pkg" -GASNET_LDFLAGS="`$PKG_CONFIG $pkg --variable=GASNET_LDFLAGS`" -GASNET_LIBS="`$PKG_CONFIG $pkg --variable=GASNET_LIBS`" -GASNET_CC="`$PKG_CONFIG $pkg --variable=GASNET_CC`" -GASNET_CFLAGS="`$PKG_CONFIG $pkg --variable=GASNET_CFLAGS`" -GASNET_CPPFLAGS="`$PKG_CONFIG $pkg --variable=GASNET_CPPFLAGS`" - -# Check whether GASNet was installed using Spack. If yes, bail out. -# Note: relies on the fact that most Spack installations have "opt/spack" -# in the directory path, and assumes that the first directory returned -# by pkg-config contains the GASNet lib directory -GASNET_LIBDIR="$(echo $GASNET_LIBS | awk '{print $1};')" +GASNET_LDFLAGS=$($PKG_CONFIG $pkg --variable=GASNET_LDFLAGS) +GASNET_LIBS=$($PKG_CONFIG $pkg --variable=GASNET_LIBS) +GASNET_CC=$($PKG_CONFIG $pkg --variable=GASNET_CC) +GASNET_CFLAGS=$($PKG_CONFIG $pkg --variable=GASNET_CFLAGS) +GASNET_CPPFLAGS=$($PKG_CONFIG $pkg --variable=GASNET_CPPFLAGS) + +# Relies on the first directory in GASNET_LIBS is the GASNet lib directory +GASNET_LIBDIR=$(awk '{print $1};' <<< $GASNET_LIBS) GASNET_LIBDIR=${GASNET_LIBDIR#-L} -case "$GASNET_LIBDIR" in - *spack* ) - cat << EOF + +# Check whether GASNet appears to be a Spack install. If yes, bail out. +# Note: most Spack installations have "opt/spack" in the directory path. +if [[ $GASNET_LIBDIR == *spack* ]] && \ + [[ $(realpath $GASNET_LIBDIR) != $(realpath "$PREFIX/lib") ]]; then + cat << EOF ***NOTICE***: The GASNet library built by Spack is ONLY intended for unit-testing purposes, and is generally UNSUITABLE FOR PRODUCTION USE. The RECOMMENDED way to build GASNet is as an embedded library as configured by the higher-level client runtime package (i.e. Caffeine), including system-specific configuration. Exiting install.sh EOF - exit 1 - ;; - * ) - GASNET_PREFIX=$(dirname $GASNET_LIBDIR) - if [ ! -r "$GASNET_PREFIX/include/gasnetex.h" ] ; then - echo "ERROR: Failed to detect GASNet install prefix from $GASNET_LIBS" - exit 1 - fi - ;; -esac + exit 1 +fi +GASNET_PREFIX=$(dirname $GASNET_LIBDIR) +if [ ! -r "$GASNET_PREFIX/include/gasnetex.h" ] ; then + echo "ERROR: Failed to detect GASNet install prefix from $GASNET_LIBS" + exit 1 +fi # Strip compiler flags # Warning: This assumes the full path doesn't contain any spaces! -GASNET_CC_STRIPPED="$(echo $GASNET_CC | awk '{print $1};')" +GASNET_CC_STRIPPED=$(awk '{print $1};' <<< $GASNET_CC) if [ "$(realpath $GASNET_CC_STRIPPED)" != "$(realpath $CC)" ]; then echo "ERROR: C Compiler mismatch: GASNET_CC=$(realpath $GASNET_CC_STRIPPED) and CC=$(realpath $CC) don't match" exit 1; @@ -554,12 +551,12 @@ FPM_TOML="fpm.toml" rm -f $FPM_TOML echo "# DO NOT EDIT OR COMMIT -- Created by caffeine/install.sh" > $FPM_TOML cat manifest/fpm.toml.template >> $FPM_TOML -GASNET_LIB_LOCATIONS=`echo $GASNET_LIBS | awk '{locs=""; for(i = 1; i <= NF; i++) if ($i ~ /^-L/) {locs=(locs " " $i);}; print locs; }'` -GASNET_LIB_NAMES=`echo $GASNET_LIBS | awk '{names=""; for(i = 1; i <= NF; i++) if ($i ~ /^-l/) {names=(names " " $i);}; print names; }' | sed 's/-l//g'` +GASNET_LIB_LOCATIONS=$(awk '{locs=""; for(i = 1; i <= NF; i++) if ($i ~ /^-L/) {locs=(locs " " $i);}; print locs; }' <<< $GASNET_LIBS) +GASNET_LIB_NAMES=$(awk '{names=""; for(i=1; i<=NF; i++) if(sub(/^-l/, "", $i)) names=(names ? names " " : "") $i; print names}' <<< $GASNET_LIBS) if [[ $GASNET_CONDUIT == "udp" ]] ; then GASNET_LIB_NAMES+=" stdc++" # udp-conduit requires C++ libraries fi -FPM_TOML_LINK_ENTRY="link = [\"$(echo ${GASNET_LIB_NAMES} | sed 's/ /", "/g')\"]" +FPM_TOML_LINK_ENTRY="link = [\"$(sed 's/ /", "/g' <<< $GASNET_LIB_NAMES)\"]" echo "${FPM_TOML_LINK_ENTRY}" >> $FPM_TOML # save Fortran flag user inputs From 173a92544d5b6bfac5cbc39ce5c806c4b2c4ba8f Mon Sep 17 00:00:00 2001 From: bonachea Date: Mon, 7 Sep 2026 13:18:40 -0700 Subject: [PATCH 23/24] run-fpm.sh: Deploy bash-isms to simplify Also prohibit `run-fpm.sh install`, which does not complete a full install --- install.sh | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/install.sh b/install.sh index 195b393c8..54e78d340 100755 --- a/install.sh +++ b/install.sh @@ -682,13 +682,19 @@ LDFLAGS="$CAFFEINE_LDFLAGS" FPM_DRIVER=\${FPM_DRIVER:-\$([[ "\$0" == /* ]] && echo "\$0" || echo "\$PWD/\$0")} export FPM_DRIVER fpm_sub_cmd=\$1; shift -if echo "--help -help --version -version --list -list new update list clean publish" | grep -w -q -e "\$fpm_sub_cmd" ; then +if [[ "\$fpm_sub_cmd" == "install" && "\$1" != "--list" ]] ; then + echo "ERROR: Please use install.sh to install Caffeine." + exit 1 +fi +case "\$fpm_sub_cmd" in +--help|-help|help|--version|-version|--list|-list|new|update|list|clean|publish) set -x exec "\$FPM" "\$fpm_sub_cmd" "\$@" -elif echo "build test run install" | grep -w -q -e "\$fpm_sub_cmd" ; then + ;; +build|test|run|install) sed -i.bak 's/^link = .*\$/$FPM_TOML_LINK_ENTRY/' $FPM_TOML rm -f $FPM_TOML.bak # issue 282: this is the only portable way to use sed -i - if test -n "$GASNET_RUNNER_ARG" && echo "test run" | grep -w -q -e "\$fpm_sub_cmd" ; then + if [[ -n "$GASNET_RUNNER_ARG" && " test run " == *" \$fpm_sub_cmd "* ]]; then set -- "--runner=$GASNET_RUNNER_ARG" "\$@" fi set -x @@ -700,17 +706,19 @@ elif echo "build test run install" | grep -w -q -e "\$fpm_sub_cmd" ; then --c-flag "\$CFLAGS" \\ --link-flag "\$LDFLAGS" \\ "\$@" -elif echo "set-native" | grep -w -q -e "\$fpm_sub_cmd" ; then + ;; +set-native) set -e mkdir -p build cmd="\$FC \$RAWFLAGS app/print-native-flags.F90 -o build/print-native-flags $APPEND_LDFLAGS" eval \$cmd || (set -x ; eval \$cmd) - NATIVEFLAGS="\`build/print-native-flags\`" + NATIVEFLAGS=\$(build/print-native-flags) rm -f build/print-native-flags sed -i.bak 's/^NATIVEFLAGS=.*\$/NATIVEFLAGS="'"\$NATIVEFLAGS"'"/' \$FPM_DRIVER rm -f \$FPM_DRIVER.bak echo NATIVEFLAGS=\"\$NATIVEFLAGS\" -elif echo "info" | grep -w -q -e "\$fpm_sub_cmd" ; then + ;; +info) LINE=-------------------------------------------------- SRCDIR=\$(dirname \$FPM_DRIVER) GASNETDIR="$GASNET_PREFIX" @@ -718,21 +726,19 @@ elif echo "info" | grep -w -q -e "\$fpm_sub_cmd" ; then echo \$LINE echo Version info: echo Caffeine \$(grep version \$SRCDIR/fpm.toml) - if test -d \$SRCDIR/.git ; then + if [[ -d \$SRCDIR/.git ]]; then GITVER=\$( ( cd \$SRCDIR && git describe --long --dirty --always ) 2> /dev/null) - if test -n "\$GITVER"; then - echo " git describe: \$GITVER" - fi + [[ -n "\$GITVER" ]] && echo " git describe: \$GITVER" fi - if test -r "\$GASNETCONFIG"; then + if [[ -r "\$GASNETCONFIG" ]]; then echo GASNet version \$(grep GASNETI_RELEASE_VERSION \$GASNETCONFIG | cut -d' ' -f3-) fi grep -e assert -e julienne \$SRCDIR/fpm.toml echo \$LINE echo Platform info: uname -a - if test -r /etc/os-release ; then grep -e NAME -e VERSION /etc/os-release ; fi - if test -x /usr/bin/sw_vers ; then /usr/bin/sw_vers ; fi + [[ -r /etc/os-release ]] && grep -e NAME -e VERSION /etc/os-release + [[ -x /usr/bin/sw_vers ]] && /usr/bin/sw_vers echo \$LINE echo Install settings: echo ID="\$(date) \$(whoami)" @@ -748,7 +754,7 @@ elif echo "info" | grep -w -q -e "\$fpm_sub_cmd" ; then echo GASNET_CONDUIT=$GASNET_CONDUIT echo GASNET_CODEMODE=$GASNET_CODEMODE echo GASNET_THREADMODE=$GASNET_THREADMODE - if test -r "\$GASNETCONFIG"; then + if [[ -r "\$GASNETCONFIG" ]]; then grep -e GASNETI_BUILD_ID -e GASNETI_CONFIGURE_ARGS \$GASNETCONFIG | cut -d' ' -f2- fi for tool in FPM FC CC ; do @@ -762,11 +768,12 @@ elif echo "info" | grep -w -q -e "\$fpm_sub_cmd" ; then \$toolval --version done echo \$LINE -else + ;; +*) echo "ERROR: Unrecognized fpm subcommand \$fpm_sub_cmd" \$FPM list exit 1 -fi +esac EOF chmod u+x $RUN_FPM_SH # for backwards-compatibility of instructions/scripting: From aebea3f702de4fef44fef92655bb3f5a87cf5f9a Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Tue, 8 Sep 2026 09:45:23 -0700 Subject: [PATCH 24/24] README: Update documentation --- README.md | 67 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 57454e3c4..0ad987d0f 100644 --- a/README.md +++ b/README.md @@ -48,19 +48,24 @@ their solution to support Fortran's multi-image parallel features. Prerequisites & Dependencies ------------- +Caffeine supports recent versions of Linux and macOS, running on x86\_64 (amd64) or ARM64 (aarch64) architectures. +Other architectures and POSIX-like environments may also work, but are not regularly tested. + ### Build prerequisites -The `install.sh` script uses the following packages: -* Fortran and C compilers - * We regularly test with: LLVM Flang versions 19:22 and GNU Fortran versions 13:15 -* [Fortran package manager] `fpm` -* [pkg-config] -* [realpath] -* [make] -* [git] -* [curl] - -The script will invoke these if present in a user's `PATH`. -If not present, the script will ask permission to use [Homebrew] to install the relevant package + +The `install.sh` script uses the following packages to build Caffeine: +* Fortran and C compilers. We [regularly test](https://github.com/BerkeleyLab/caffeine/actions?query=branch%3Amain) with: + - LLVM Flang versions 19:23, + - GNU Fortran versions 13:16, and + - LFortran versions 0.64: +* [`fpm`](https://github.com/fortran-lang/fpm), the Fortran package manager +* [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) +* [GNU make](https://www.gnu.org/software/make/) +* [git](https://git-scm.com) +* [curl](https://curl.se) + +The `install.sh` script will invoke these if found in the user's `PATH`. +If not present, the script will ask permission to use [Homebrew](https://brew.sh) to install the relevant package or, in some cases, ask the user to install the package. ### Build dependencies @@ -68,9 +73,9 @@ or, in some cases, ask the user to install the package. Caffeine also depends on the following packages that will be automatically installed as part of the build process. -* [GASNet-EX] exascale networking middleware -* [assert](https://go.lbl.gov/assert) -* [julienne](https://go.lbl.gov/julienne) +* [GASNet-EX] : exascale networking middleware, providing communication services +* [assert](https://go.lbl.gov/assert) : Fortran assertion package, enforces invariants in debug mode +* [julienne](https://go.lbl.gov/julienne) : Fortran test infrastructure (only for unit tests) Caffeine leverages the following non-parallel features of Fortran to simplify the writing of a portable, compact runtime-library that supports Fortran's parallel features: @@ -131,6 +136,16 @@ written in Fortran, simulating the PRIF calls that a theoretical source-to-source Fortran compiler might generate for a simple program written using Fortran's multi-image features to print a message from each image. +Caffeine also includes a broad "smoke test" of multi-image Fortran features. +When Caffeine was installed using a PRIF-compatible Fortran compiler (currently +LLVM Flang 22+ or LFortran 0.64+) the following command will invoke this smoke +test: +```bash +env CAF_IMAGES=8 ./run-fpm.sh run +``` +This will exercise the available PRIF feature set of the compiler version +detected at install time. + Run tests --------- @@ -168,6 +183,21 @@ Here are *a few* of the most useful GASNet knobs: See [GASNet documentation](https://gasnet.lbl.gov/dist-ex/README) for full details on all settings. +Troubleshooting +--------------- + +The Caffeine `./install.sh` script defaults to building the library in an optimized production mode, +which is generally suitable for end users and should be preferred for any performance-oriented runs. + +If you're developing compiler transformations targeting PRIF, or if you encounter a correctness +problem at runtime, then its **highly** recommended to instead build Caffeine in debug mode: +``` +./install.sh --enable-debug +``` +The `--enable-debug` flag disables compiler optimization and enables thousands +of correctness checks system-wide. This includes sanity checking of PRIF subroutine +arguments, and often provides an automated diagnosis that can pinpoint the problem. + PRIF Implementation Status -------------------------- @@ -228,10 +258,3 @@ See [LICENSE.txt](LICENSE.txt) for usage terms and conditions. [CLaSS]: https://go.lbl.gov/class [Berkeley Lab]: https://lbl.gov [MPI]: https://www.mpi-forum.org -[Homebrew]: https://brew.sh -[Fortran package manager]: https://github.com/fortran-lang/fpm -[pkg-config]: https://www.freedesktop.org/wiki/Software/pkg-config/ -[realpath]: https://man7.org/linux/man-pages/man3/realpath.3.html -[make]: https://www.gnu.org/software/make/ -[git]: https://git-scm.com -[curl]: https://curl.se