From 4f81ad333c6e5e1c9c7090ba927b23651fcbaab5 Mon Sep 17 00:00:00 2001 From: bonachea Date: Fri, 4 Sep 2026 12:28:11 -0700 Subject: [PATCH 01/11] install.sh: Add support for CMake-driven build of libcaffeine Details: * New `install.sh` option `--enable-cmake` (aka `--disable-fpm`) activates the internal use of CMake instead of FPM to drive the build. * Homebrew support is extended to optionally install CMake instead FPM, as appropriate. * Still generates `run-fpm.sh`, which can optionally be used to invoke an FPM-driven build of the library or tests after running `install.sh` (e.g. if FPM is later installed) Limitations: * Does not support CMake-driven build of Caffeine unit tests or examples. Caffeine developers should install FPM and use `run-fpm.sh test` (or leverage the FPM in GitHub Actions CI). --- install.sh | 114 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 16 deletions(-) diff --git a/install.sh b/install.sh index 83342353..c97741d6 100755 --- a/install.sh +++ b/install.sh @@ -27,6 +27,8 @@ Options: 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. + --enable-cmake or --disable-fpm + Build Caffeine library using CMake instead of FPM (the default). All unrecognized arguments will be passed to GASNet's configure. @@ -59,6 +61,7 @@ JULIENNE_GIT=$(awk -F'"' '/^julienne =/ {print $2}' manifest/fpm.toml.template) JULIENNE_VERSION=$(awk -F'"' '/^julienne =/ {print $4}' manifest/fpm.toml.template) VERBOSE="" YES=false +USE_FPM=true APPEND_CFLAGS="" APPEND_LDFLAGS="" # these variables deliberately inherited from the caller environment @@ -193,6 +196,9 @@ while [ "$1" != "" ]; do --enable-threads) GASNET_THREADMODE=par ;; --disable-threads) GASNET_THREADMODE=seq ;; + --enable-cmake | --disable-fpm) USE_FPM= ;; + --disable-cmake | --enable-fpm) USE_FPM=true ;; + --enable-debug) GASNET_CODEMODE=debug ; append_gasnet_configure_arg "$orig_arg" ;; --disable-debug) GASNET_CODEMODE=opt ; append_gasnet_configure_arg "$orig_arg" ;; @@ -279,7 +285,12 @@ PKG_CONFIG=$(abswhich ${PKG_CONFIG:-pkg-config} silent) MAKE=$(abswhich ${MAKE:-gmake} silent) # prefer 'gmake' over 'make' MAKE=$(abswhich ${MAKE:-make} silent) +CMAKE=$(abswhich ${CMAKE:-cmake} silent) + FPM=$(abswhich ${FPM:-fpm} silent) +if [[ -z $FPM && -z $USE_FPM ]] ; then + FPM="fpm" # deliberately NOT path-expanded +fi # 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 @@ -302,10 +313,11 @@ fi ask_permission_to_use_homebrew() { + BUILDER=$( [[ $USE_FPM ]] && echo "fpm" || echo "cmake" ) 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, make, fpm. +one or more of the following packages are not in the PATH: pkg-config, make, $BUILDER. If you grant permission to install prerequisites, you will be prompted before each installation. Press 'Enter' to choose the square-bracketed default answer: @@ -359,7 +371,8 @@ exit_if_user_declines() DEPENDENCIES_DIR="build/dependencies" mkdir -p $DEPENDENCIES_DIR -if [ -z ${FC:+x} ] || [ -z ${CC:+x} ] || [ -z ${PKG_CONFIG:+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} ] || [[ -z ${CMAKE:+x} && -z ${USE_FPM:+x} ]] ; then ask_permission_to_use_homebrew exit_if_user_declines "brew" @@ -442,6 +455,13 @@ EOF $BREW install fpm FPM=$(abswhich fpm) fi + + if [ -z ${CMAKE:+x} -a -z ${USE_FPM:+x} ] ; then + ask_permission_to_install_homebrew_package "'cmake'" + exit_if_user_declines "cmake" + $BREW install cmake + CMAKE=$(abswhich cmake) + fi fi # --------------------------------------------------------------- @@ -680,8 +700,8 @@ cat << EOF > "$PKG_CONFIG_DIR/$CAFFEINE_PC" CAFFEINE_FC=$FC CAFFEINE_CC=$CC -CAFFEINE_FFLAGS=$FFLAGS -CAFFEINE_CFLAGS=$APPEND_CFLAGS +CAFFEINE_FFLAGS="$FFLAGS" +CAFFEINE_CFLAGS="$APPEND_CFLAGS" CAFFEINE_LDFLAGS="-L$PREFIX/lib $APPEND_LDFLAGS" CAFFEINE_NETWORK=$GASNET_CONDUIT CAFFEINE_THREADMODE=$GASNET_THREADMODE @@ -775,6 +795,8 @@ info) SRCDIR=\$(dirname \$FPM_DRIVER) GASNETDIR="$GASNET_PREFIX" GASNETCONFIG="\$GASNETDIR/include/gasnet_config.h" + MAKE=$MAKE + CMAKE=${CMAKE:-} echo \$LINE echo Version info: echo Caffeine \$(grep version \$SRCDIR/fpm.toml) @@ -796,6 +818,8 @@ info) echo ID="\$(date) \$(whoami)" echo PREFIX=$PREFIX echo FPM=\$FPM + echo CMAKE=\$CMAKE + echo MAKE=\$MAKE echo FC=\$FC echo CC=\$CC echo FFLAGS=\$FFLAGS @@ -809,7 +833,7 @@ info) 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 + for tool in FC CC $( [[ $USE_FPM ]] && echo "FPM" || echo "CMAKE" ) MAKE ; do echo \$LINE eval toolval="\\$\$tool" echo \$tool : \$toolval @@ -832,12 +856,10 @@ chmod u+x $RUN_FPM_SH ( cd build && ln -f -s ../$RUN_FPM_SH run-fpm.sh ) # --------------------------------------------------------------- -# Caffeine build - -./$RUN_FPM_SH set-native - -./$RUN_FPM_SH build $VERBOSE || \ -( set +x +# Install an ERR handler for build failures +error_handler() { + set +ex + echo "Error: Command '$BASH_COMMAND' failed on line $1 with exit code $?." echo "Defect reporting information:" ./$RUN_FPM_SH info echo @@ -845,16 +867,76 @@ chmod u+x $RUN_FPM_SH echo Please paste the ENTIRE output above into a new issue here: echo " https://github.com/berkeleylab/caffeine/issues" exit 1 -) +} + +trap 'error_handler $LINENO' ERR # --------------------------------------------------------------- -# Caffeine installation +# Caffeine build LIBCAFFEINE_DST=libcaffeine-$GASNET_CONDUIT-$GASNET_THREADMODE.a -LIBCAFFEINE_SRC=$(./$RUN_FPM_SH install --list 2>/dev/null | grep libcaffeine | cut -d' ' -f2) -if [ -z "$LIBCAFFEINE_SRC" ]; then - echo "ERROR: Failed to detect libcaffeine.a from fpm" +./$RUN_FPM_SH set-native + +if [[ -n $USE_FPM ]] ; then + ./$RUN_FPM_SH build $VERBOSE + + LIBCAFFEINE_SRC=$(./$RUN_FPM_SH install --list 2>/dev/null | grep libcaffeine | cut -d' ' -f2) +else # Using CMake instead of FPM to build + ASSERT_DIR=$DEPENDENCIES_DIR/assert + mkdir -p $ASSERT_DIR + if ! [[ -r $ASSERT_DIR/fpm.toml ]] ; then + # Download Assert: Assumes git version 1.7.7 (2011-09) or later + $GIT clone -c advice.detachedHead=false --depth 1 --branch $ASSERT_VERSION $ASSERT_GIT $ASSERT_DIR + ( cd $ASSERT_DIR && $GIT log -n 1 --oneline ) + fi + + # CMake botches module name analysis unless we match the name in the source file: + ASSERT_SRC="$ASSERT_DIR/src/caf_caffiene_assert_m.F90" + $FC $FFLAGS -I$ASSERT_DIR/include -E $ASSERT_DIR/src/assert_m.F90 > $ASSERT_SRC + + # Generate CMakeLists.txt + cat << EOF > CMakeLists.txt +cmake_minimum_required(VERSION 3.0...4.4 FATAL_ERROR) + +# Provide the compilers BEFORE the project() command +set(CMAKE_C_COMPILER "$CC") +set(CMAKE_Fortran_COMPILER "$FC") + +project(Caffeine LANGUAGES C Fortran) + +# Set the command-line options for the compilers +set(CMAKE_C_FLAGS "$CAFFEINE_CFLAGS -I$(abspath include)") +set(CMAKE_Fortran_FLAGS "$FFLAGS -I$(abspath include) -I$(abspath $ASSERT_DIR)/include") + +add_library(caffeine-$GASNET_CONDUIT-$GASNET_THREADMODE STATIC +EOF + echo $ASSERT_SRC >> CMakeLists.txt + # Ownership check to avoid "fatal: detected dubious ownership in repository" in containers + if [[ -d .git ]] && [[ $(ls -ld .git | awk '{print $3}') == $(id -un) ]] ; then + $GIT ls-files src | grep -e '.F90$' -e '.c$' >> CMakeLists.txt + else + find src -name '*.F90' -or -name '*.c' >> CMakeLists.txt + fi + echo ")" >> CMakeLists.txt + + rm -Rf build/cmake + mkdir -p build/cmake + ( + cd build/cmake + $CMAKE ../.. + $MAKE -j 8 ${VERBOSE:+VERBOSE=1} + ) + + LIBCAFFEINE_SRC=build/cmake/$LIBCAFFEINE_DST +fi + +# --------------------------------------------------------------- +# Caffeine installation + + +if ! [ -r "$LIBCAFFEINE_SRC" ]; then + echo "ERROR: Failed to build/detect libcaffeine" exit 1 else mkdir -p "$PREFIX/lib" From d348e983c2702242bcce8d5c133a597ffded4626 Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Fri, 18 Sep 2026 22:17:39 -0700 Subject: [PATCH 02/11] caffeine.pc: Add missing -lstdc++ for udp-conduit --- install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/install.sh b/install.sh index c97741d6..8bf9b235 100755 --- a/install.sh +++ b/install.sh @@ -684,6 +684,7 @@ GASNET_LIB_LOCATIONS=$(awk '{locs=""; for(i = 1; i <= NF; i++) if ($i ~ /^-L/) { 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 + APPEND_LDFLAGS+=" -lstdc++" fi FPM_TOML_LINK_ENTRY="link = [\"$(sed 's/ /", "/g' <<< $GASNET_LIB_NAMES)\"]" echo "${FPM_TOML_LINK_ENTRY}" >> $FPM_TOML From ab856daf36415e60d82b74354cb0ccc0bc97917f Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Thu, 17 Sep 2026 18:59:23 -0700 Subject: [PATCH 03/11] CI: Add coverage for CMake build and pkg-config outputs --- .github/workflows/build.yml | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 351a899e..6200ce9d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -300,6 +300,7 @@ jobs: GASNET_MASTERIP: 127.0.0.1 CAF_IMAGES: 8 BREW_WARNING_FILTER: 's/^[[:punct:]]*warning[[:punct:]]*(You are using macOS on Intel)/warn: \1/i' + INSTALL_VARS: FC CC CXX FFLAGS CPPFLAGS CFLAGS CXXFLAGS LDFLAGS LIBS GASNET_CONFIGURE_ARGS FPM CMAKE MAKE PKG_CONFIG steps: - name: Checkout code @@ -312,7 +313,7 @@ jobs: if: ${{ contains(matrix.os, 'ubuntu') && matrix.container != '' && !contains(matrix.container, 'phhargrove') }} run: | apt update - apt install -y build-essential pkg-config make git curl + apt install -y build-essential pkg-config make git curl cmake - name: Install Ubuntu Native Dependencies if: ${{ contains(matrix.os, 'ubuntu') && matrix.container == '' && !matrix.brew_via_install }} @@ -538,8 +539,7 @@ jobs: - name: Build Caffeine (install.sh) run: | - for var in FC CC CXX FFLAGS CPPFLAGS CFLAGS CXXFLAGS LDFLAGS LIBS GASNET_CONFIGURE_ARGS ; do - eval echo "$var=\$$var"; done + (set +x ; for var in ${{ env.INSTALL_VARS }} ; do eval echo "$var=\$$var"; done) ./install.sh ${CONFIGURE_ARGS} ${NETWORK_ARG} \ ${{ inputs.install_args }} ${{ matrix.install_filter }} if ! grep -q 'NATIVEFLAGS=""' run-fpm.sh ; then @@ -554,6 +554,8 @@ jobs: ./run-fpm.sh info ./install/bin/ident ./install/lib/libcaffeine.a | tee output test ${PIPESTATUS[0]} = 0 && grep -q "CaffeineAssertions" output + pkg-config --validate install/lib/pkgconfig/caffeine.pc | tee output + test ${PIPESTATUS[0]} = 0 && ! grep -q -v pkgconfig/gasnet output - name: Run examples run: | @@ -617,16 +619,33 @@ jobs: if: ${{ contains(matrix.os, 'ubuntu') && matrix.brew_via_install }} run: | # the first install.sh command established Linux Brew, so add it to the - # PATH to prevent pointless overwrites in the second install.sh below + # PATH to prevent pointless overwrites in subsequent install.sh below HOMEBREW_PREFIX="/home/linuxbrew/.linuxbrew" ( set +e ; ls -al ${HOMEBREW_PREFIX}/bin ; exit 0 ) echo "PATH=${HOMEBREW_PREFIX}/bin:${PATH}" >> "$GITHUB_ENV" - name: Build and Test Caffeine (thread-safe) run: | - for var in FC CC CXX FFLAGS CPPFLAGS CFLAGS LDFLAGS LIBS GASNET_CONFIGURE_ARGS ; do - eval echo "$var=\$$var"; done + rm -Rf build install/lib/libcaffeine* install/lib/pkgconfig/caffeine* + (set +x ; for var in ${{ env.INSTALL_VARS }} ; do eval echo "$var=\$$var"; done) ./install.sh ${CONFIGURE_ARGS} ${NETWORK_ARG} --enable-threads \ ${{ inputs.install_args }} ${{ matrix.install_filter }} ./run-fpm.sh test --verbose -- ${{ inputs.julienne_args }} + ./install/bin/ident ./install/lib/libcaffeine.a | tee output + test ${PIPESTATUS[0]} = 0 && grep -q "CaffeineAssertions" output + pkg-config --validate install/lib/pkgconfig/caffeine.pc | tee output + test ${PIPESTATUS[0]} = 0 && ! grep -q -v pkgconfig/gasnet output + + - name: Build Caffeine (CMake) + run: | + rm -Rf build install/lib/libcaffeine* install/lib/pkgconfig/caffeine* + (set +e ; rm -f $(type -P fpm) ) + (set +x ; for var in ${{ env.INSTALL_VARS }} ; do eval echo "$var=\$$var"; done) + ./install.sh ${CONFIGURE_ARGS} ${NETWORK_ARG} --enable-cmake \ + ${{ inputs.install_args }} ${{ matrix.install_filter }} + ./run-fpm.sh info + ./install/bin/ident ./install/lib/libcaffeine.a | tee output + test ${PIPESTATUS[0]} = 0 && grep -q "CaffeineAssertions" output + pkg-config --validate install/lib/pkgconfig/caffeine.pc | tee output + test ${PIPESTATUS[0]} = 0 && ! grep -q -v pkgconfig/gasnet output From ae02c5b34342680cfd47a8500bb55271cb085c5f Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Sat, 19 Sep 2026 17:38:19 -0700 Subject: [PATCH 04/11] install.sh: Split off _lib variants of FFLAGS and APPEND_CFLAGS Some FFLAGS and CFLAGS should not be exported via our pkg-config file, so separate those out into new *_lib variants and deploy appropriately. --- install.sh | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/install.sh b/install.sh index 8bf9b235..b02ae505 100755 --- a/install.sh +++ b/install.sh @@ -59,11 +59,12 @@ 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="" +VERBOSE= YES=false USE_FPM=true -APPEND_CFLAGS="" -APPEND_LDFLAGS="" +APPEND_CFLAGS= +APPEND_CFLAGS_lib= +APPEND_LDFLAGS= # these variables deliberately inherited from the caller environment GASNET_CONDUIT="${GASNET_CONDUIT:-smp}" GASNET_THREADMODE="${GASNET_THREADMODE:-seq}" @@ -515,7 +516,10 @@ fi user_compiler_flags="${CPPFLAGS:-} ${FFLAGS:-}" # compiler-specific flag defaults -FFLAGS="-g" +# FFLAGS is exported via pkg-config +# FFLAGS_lib adds flags for library build that should not be exported +FFLAGS= +FFLAGS_lib="-g" FFLAGS_debug="-O0" FFLAGS_opt="-O3" compiler_version=$($FC --version) @@ -526,11 +530,12 @@ if [[ $compiler_version =~ 'flang' ]]; then # flang-19 and older need extra args: awk "BEGIN { exit ($supported_version < 20) }" || FFLAGS+=" -mmlir -allow-assumed-rank" elif [[ $compiler_version =~ 'GNU Fortran' ]]; then - FFLAGS="-g -ffree-line-length-0 -Wno-unused-dummy-argument" + FFLAGS="-ffree-line-length-0 -Wno-unused-dummy-argument" supported_version=$(awk 'NR==1 && match($0, /) [0-9]+\.[0-9]+/){ v=substr($0, RSTART+2, RLENGTH-2); if (v+0 >= 13) print v; }' <<< "$compiler_version") elif [[ $compiler_version =~ 'LFortran' ]]; then # 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" + FFLAGS_lib="--cpp --realloc-lhs-arrays --no-style-suggestions --implicit-argument-casting" + FFLAGS="--separate-compilation" supported_version=$(awk 'NR==1 && match($0, /version: [0-9]+\.[0-9]+/){ v=substr($0, RSTART+9, RLENGTH-9); if (v+0 >= 0.63) print v; }' <<< "$compiler_version") else # unknown compiler FFLAGS_opt=-O2 @@ -548,9 +553,9 @@ if [[ -z "$supported_version" ]] ; then fi if [[ "$GASNET_CODEMODE" == "debug" ]] ; then - FFLAGS="$FFLAGS_debug $FFLAGS" + FFLAGS_lib="$FFLAGS_debug $FFLAGS_lib" else - FFLAGS="$FFLAGS_opt $FFLAGS" + FFLAGS_lib="$FFLAGS_opt $FFLAGS_lib" fi # Configure dependencies: @@ -560,9 +565,9 @@ fi # subsumed by the parallel callbacks, and we don't want native calls to # this_image() on compilers that might not support it through PRIF. # We do rename the assert module to reduce the chance of name conflicts: -FFLAGS+=" -Dassert_m=caf_caffiene_assert_m" +FFLAGS_lib+=" -Dassert_m=caf_caffiene_assert_m" # enable Julienne's multi-image support with PRIF callbacks provided by julienne-driver -FFLAGS+=" -DHAVE_MULTI_IMAGE_SUPPORT -DJULIENNE_PARALLEL_CALLBACKS" +FFLAGS_lib+=" -DHAVE_MULTI_IMAGE_SUPPORT -DJULIENNE_PARALLEL_CALLBACKS" if [[ $GASNET_THREADMODE == "par" ]] ; then FFLAGS+=" -DCAF_THREAD_SAFE" @@ -574,19 +579,19 @@ FFLAGS+=" -DCAF_NETWORK_$GASNET_CONDUIT_UPPER" # Append user flags last to allow command-line overrides FFLAGS+=" $user_compiler_flags" -if ! [[ "$FFLAGS " =~ -[DU]ASSERTIONS[=\ ] ]] ; then +if ! [[ "$FFLAGS_lib $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" + FFLAGS_lib+=" -DASSERTIONS" fi fi # Ensure that certain preprocessor settings in FFLAGS are always appended to CFLAGS -for opt in $FFLAGS; do +for opt in $FFLAGS_lib $FFLAGS; do case "$opt" in -DASSERTIONS* | -UASSERTIONS* | -DFORCE_PRIF_* | -UFORCE_PRIF_*) - APPEND_CFLAGS+=" $opt" + APPEND_CFLAGS_lib+=" $opt" ;; esac done @@ -690,7 +695,7 @@ FPM_TOML_LINK_ENTRY="link = [\"$(sed 's/ /", "/g' <<< $GASNET_LIB_NAMES)\"]" echo "${FPM_TOML_LINK_ENTRY}" >> $FPM_TOML # flag outputs -CAFFEINE_CFLAGS="$GASNET_CFLAGS $GASNET_CPPFLAGS $APPEND_CFLAGS" +CAFFEINE_CFLAGS="$GASNET_CFLAGS $GASNET_CPPFLAGS $APPEND_CFLAGS_lib $APPEND_CFLAGS" CAFFEINE_LDFLAGS="$GASNET_LDFLAGS $GASNET_LIB_LOCATIONS $APPEND_LDFLAGS" CAFFEINE_PC="caffeine-$GASNET_CONDUIT-$GASNET_THREADMODE.pc" @@ -703,7 +708,7 @@ CAFFEINE_FC=$FC CAFFEINE_CC=$CC CAFFEINE_FFLAGS="$FFLAGS" CAFFEINE_CFLAGS="$APPEND_CFLAGS" -CAFFEINE_LDFLAGS="-L$PREFIX/lib $APPEND_LDFLAGS" +CAFFEINE_LDFLAGS="-L$PREFIX/lib" CAFFEINE_NETWORK=$GASNET_CONDUIT CAFFEINE_THREADMODE=$GASNET_THREADMODE CAFFEINE_CODEMODE=$GASNET_CODEMODE @@ -714,7 +719,7 @@ 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 +Libs: \${CAFFEINE_LDFLAGS} -lcaffeine-$GASNET_CONDUIT-$GASNET_THREADMODE $APPEND_LDFLAGS EOF ln -sf "$CAFFEINE_PC" "$PKG_CONFIG_DIR/caffeine-$GASNET_CONDUIT.pc" ln -sf "$CAFFEINE_PC" "$PKG_CONFIG_DIR/caffeine.pc" @@ -748,7 +753,7 @@ FPM="$FPM" FC="$FC" CC="$CC" NATIVEFLAGS="" -RAWFLAGS="$FFLAGS" +RAWFLAGS="$FFLAGS_lib $FFLAGS" FFLAGS="\$NATIVEFLAGS \$RAWFLAGS" CFLAGS="$CAFFEINE_CFLAGS" LDFLAGS="$CAFFEINE_LDFLAGS" @@ -894,7 +899,7 @@ else # Using CMake instead of FPM to build # CMake botches module name analysis unless we match the name in the source file: ASSERT_SRC="$ASSERT_DIR/src/caf_caffiene_assert_m.F90" - $FC $FFLAGS -I$ASSERT_DIR/include -E $ASSERT_DIR/src/assert_m.F90 > $ASSERT_SRC + $FC $FFLAGS_lib $FFLAGS -I$ASSERT_DIR/include -E $ASSERT_DIR/src/assert_m.F90 > $ASSERT_SRC # Generate CMakeLists.txt cat << EOF > CMakeLists.txt @@ -908,7 +913,7 @@ project(Caffeine LANGUAGES C Fortran) # Set the command-line options for the compilers set(CMAKE_C_FLAGS "$CAFFEINE_CFLAGS -I$(abspath include)") -set(CMAKE_Fortran_FLAGS "$FFLAGS -I$(abspath include) -I$(abspath $ASSERT_DIR)/include") +set(CMAKE_Fortran_FLAGS "$FFLAGS_lib $FFLAGS -I$(abspath include) -I$(abspath $ASSERT_DIR)/include") add_library(caffeine-$GASNET_CONDUIT-$GASNET_THREADMODE STATIC EOF From 742d7317414a3c3a109458e9b499143b6d1cf053 Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Sat, 19 Sep 2026 18:00:00 -0700 Subject: [PATCH 05/11] install.sh: Tweak compiler detection When only FC is set, try to auto-detect appropriate CC. Also make the auto-suffixing logic a bit more robust. --- install.sh | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/install.sh b/install.sh index b02ae505..8a2be486 100755 --- a/install.sh +++ b/install.sh @@ -236,7 +236,15 @@ fi # --------------------------------------------------------------- # Initial compiler identification -if [ -z ${FC:+x} ] || [ -z ${CC:+x} ]; 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 +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 [ -z ${FC:+x} ] ; then # FC unset: default to LLVM if it's in PATH if type -P flang > /dev/null 2>&1; then FC=$(abswhich flang) echo "Setting FC=$FC" @@ -250,15 +258,26 @@ if [ -z ${FC:+x} ] || [ -z ${CC:+x} ]; then echo "Setting CC=$CC" fi fi -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:+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 +if [[ -n ${FC:+x} && -z ${CC:+x} ]] ; then # Have FC but missing CC + # try to auto-detect CC from FC + if [[ $(basename $FC) =~ flang ]] || [[ $(basename $FC) =~ lfortran ]] ; then + CC_guess=clang + else + CC_guess=gcc + fi + if ! [[ $(basename $FC) =~ lfortran ]] && [[ $FC =~ (-[0-9a-z-]+)$ ]] ; then + CC_guess_suff=$CC_guess${BASH_REMATCH[0]} + if type -P $CC_guess_suff > /dev/null 2>&1; then + CC=$(abswhich $CC_guess_suff) + echo "Setting CC=$CC" + fi + fi + if [ -z ${CC:+x} ] && type -P $CC_guess > /dev/null 2>&1; then + CC=$(abswhich $CC_guess) + echo "Setting CC=$CC" + fi fi -if [ -z ${CXX:+x} ] && [ -n "$CC" ] ; then +if [[ -z ${CXX:+x} && -n ${CC:+x} ]] ; then # C++ is an optional dependency # try to auto-detect from CC if [[ $(basename $CC) =~ clang ]] ; then @@ -267,9 +286,13 @@ if [ -z ${CXX:+x} ] && [ -n "$CC" ] ; then CXX_guess=g++ fi if [[ $CC =~ (-[0-9a-z-]+)$ ]] ; then - CXX_guess=${CXX_guess}${BASH_REMATCH[0]} + CXX_guess_suff=$CXX_guess${BASH_REMATCH[0]} + if type -P $CXX_guess_suff > /dev/null 2>&1; then + CXX=$(abswhich $CXX_guess_suff) + echo "Setting CXX=$CXX" + fi fi - if type -P $CXX_guess > /dev/null 2>&1; then + if [ -z ${CXX:+x} ] && type -P $CXX_guess > /dev/null 2>&1; then CXX=$(abswhich $CXX_guess) echo "Setting CXX=$CXX" fi From 67c74d700fdfd681f352d5cacad9ab532e1d5f25 Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Sat, 19 Sep 2026 20:36:57 -0700 Subject: [PATCH 06/11] install.sh: Ensure GASNet doesn't inject -g onto the LFortran link line --- install.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/install.sh b/install.sh index 8a2be486..e5f23d88 100755 --- a/install.sh +++ b/install.sh @@ -701,6 +701,18 @@ if [ "$(realpath $GASNET_CC_STRIPPED)" != "$(realpath $CC)" ]; then exit 1; fi +if [[ $compiler_version =~ 'LFortran' ]]; then + # Some LFortan builds issue a fatal error if -g appears on the Fortran compile or link line + # GASNet sometimes injects this linker option, so ensure we strip it out + for var in GASNET_LDFLAGS GASNET_LIBS ; do + space=' ' + eval $var="\$space\${$var}\$space" # surround start/end with space to avoid anchors + eval $var="\${$var// -g / }" # space is our option boundary + eval $var="\${$var%% }" # strip the space we added + eval $var="\${$var## }" # strip the space we added + done +fi + # --------------------------------------------------------------- # Output file generation From 534b61ea85fa0ccf7cc6ac95349ade27448ce807 Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Mon, 21 Sep 2026 19:50:07 -0700 Subject: [PATCH 07/11] install.sh: Automatically append LFortran include dir Ensure that Caffeine's C compilation (caffeine.c in particular) use LFortran's copy of ISO_Fortran_binding.h --- .github/workflows/build.yml | 7 ++----- install.sh | 2 ++ 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6200ce9d..e51a490c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -474,11 +474,8 @@ jobs: echo "FC=lfortran" >> "$GITHUB_ENV" echo "CC=clang" >> "$GITHUB_ENV" echo "CXX=clang++" >> "$GITHUB_ENV" - HEADER_NAME=ISO_Fortran_binding.h - HEADER_TARGET=include/$HEADER_NAME - HEADER_SOURCE=$(lfortran --print-c-include-dir)/$HEADER_NAME - echo "#include <$HEADER_SOURCE>" > $HEADER_TARGET - find / -name $HEADER_NAME -exec ls -al {} \; -exec md5sum {} \; -exec head {} \; -exec echo --- \; + ls -R $(lfortran --print-c-include-dir) + #find / -name $HEADER_NAME -exec ls -al {} \; -exec md5sum {} \; -exec head {} \; -exec echo --- \; - name: Set Caffeine variables run: | diff --git a/install.sh b/install.sh index e5f23d88..8a30cd74 100755 --- a/install.sh +++ b/install.sh @@ -702,6 +702,8 @@ if [ "$(realpath $GASNET_CC_STRIPPED)" != "$(realpath $CC)" ]; then fi if [[ $compiler_version =~ 'LFortran' ]]; then + # Ensure we use LFortran's copy of ISO_Fortran_binding.h + APPEND_CFLAGS+=-I$(lfortran --print-c-include-dir) # Some LFortan builds issue a fatal error if -g appears on the Fortran compile or link line # GASNet sometimes injects this linker option, so ensure we strip it out for var in GASNET_LDFLAGS GASNET_LIBS ; do From 9b975bf730ef7a10d556554c19a0938455189c3b Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Sat, 19 Sep 2026 22:08:58 -0700 Subject: [PATCH 08/11] install.sh: Export CAFFEINE_RUNCMD in the .pc file --- install.sh | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/install.sh b/install.sh index 8a30cd74..2e1e5dde 100755 --- a/install.sh +++ b/install.sh @@ -499,9 +499,9 @@ 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" + PKG_CONFIG_PATH="$PKG_CONFIG_DIR" else - PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH" + PKG_CONFIG_PATH="$PKG_CONFIG_DIR:$PKG_CONFIG_PATH" fi echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH" export PKG_CONFIG_PATH @@ -735,6 +735,24 @@ echo "${FPM_TOML_LINK_ENTRY}" >> $FPM_TOML CAFFEINE_CFLAGS="$GASNET_CFLAGS $GASNET_CPPFLAGS $APPEND_CFLAGS_lib $APPEND_CFLAGS" CAFFEINE_LDFLAGS="$GASNET_LDFLAGS $GASNET_LIB_LOCATIONS $APPEND_LDFLAGS" +case $GASNET_CONDUIT in + ibv|ofi|ucx) + GASNET_RUNNER_ARG="${GASNET_RUNNER_ARG:-$GASNET_PREFIX/bin/gasnetrun_$GASNET_CONDUIT -n \${CAF_IMAGES:-2}}" + ;; + udp) + GASNET_RUNNER_ARG="${GASNET_RUNNER_ARG:-$GASNET_PREFIX/bin/amudprun -n \${CAF_IMAGES:-2}}" + ;; + mpi) + 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:-2}}}" + ;; + *) + GASNET_RUNNER_ARG="${GASNET_RUNNER_ARG:-}" + ;; +esac + 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 @@ -749,6 +767,7 @@ CAFFEINE_LDFLAGS="-L$PREFIX/lib" CAFFEINE_NETWORK=$GASNET_CONDUIT CAFFEINE_THREADMODE=$GASNET_THREADMODE CAFFEINE_CODEMODE=$GASNET_CODEMODE +CAFFEINE_RUNCMD="${GASNET_RUNNER_ARG//'${CAF_IMAGES'*'}'/\$CAF_IMAGES}" 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. @@ -763,25 +782,6 @@ 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}}" - ;; - udp) - GASNET_RUNNER_ARG="${GASNET_RUNNER_ARG:-$GASNET_PREFIX/bin/amudprun -n \${CAF_IMAGES:-2}}" - ;; - mpi) - 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:-2}}}" - ;; - *) - GASNET_RUNNER_ARG="${GASNET_RUNNER_ARG:-}" - ;; -esac - RUN_FPM_SH="run-fpm.sh" cat << EOF > $RUN_FPM_SH #!/bin/bash From f6ff7962e09c0b1fae20fdf87f7b61ae62c43b1d Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Fri, 18 Sep 2026 21:43:16 -0700 Subject: [PATCH 09/11] app/Makefile: Expand to support PRIF execution Other misc cleanups --- .github/workflows/build.yml | 4 +- app/Makefile | 83 +++++++++++++++++++++++++++++++------ app/print-native-flags.F90 | 1 + install.sh | 18 +++++++- 4 files changed, 90 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e51a490c..e795d509 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -645,4 +645,6 @@ jobs: test ${PIPESTATUS[0]} = 0 && grep -q "CaffeineAssertions" output pkg-config --validate install/lib/pkgconfig/caffeine.pc | tee output test ${PIPESTATUS[0]} = 0 && ! grep -q -v pkgconfig/gasnet output - + if [[ -n $NATIVE_MULTI_IMAGE ]] ; then + make -C app prif + fi diff --git a/app/Makefile b/app/Makefile index 8e8d4f7d..b1d9dda5 100644 --- a/app/Makefile +++ b/app/Makefile @@ -1,33 +1,88 @@ -# This Makefile is for internal testing use only and not intended for end-users -# To run this test with Caffeine, please execute `./run-fpm.sh run` in the top-level directory +# See 'make all' for instructions # overridable settings NUM_IMAGES?=4 FLAGS= -NATIVE_FLAGS=$$($(MAKE) --no-print-directory print-flags FC=$$FC) +NATIVE_FLAGS=$$($(MAKE) --no-print-directory print-flags FC="$$FC") GFORTRAN=gfortran FC_FORCE= +PKG_CONFIG=pkg-config +CAFFEINE_PKG=caffeine +RUN_FPM_SH=../run-fpm.sh # ---------------------------------------------------------------- SHELL = bash -all: gcc +all: force + @echo "------------------------------------------------------------------------------" + @echo + @echo "This Makefile builds the native-multi-image smoke test that exercises" + @echo "native compiler support for multi-image features in Fortran." + @echo + @echo "The test is automatically adjusted to the known/expected feature support" + @echo "based on detected Fortran compiler version." + @echo "In all cases the Makefile attempts to choose appropriate compiler flags," + @echo "but these and other settings can be overridden (see top of Makefile)." + @echo "Execution commands for the built test are best-effort and might need" + @echo "adjustment based on your particular platform." + @echo + @echo "Make Targets:" + @echo + @echo "- 'make gcc' | 'make cce' | 'make intel' | 'make nag' :" + @echo " Build the test using commands appropriate for the selected compiler family," + @echo " to evaluate built-in multi-image feature support. The FC_FORCE variable" + @echo " can optionally be set to override the compiler command name." + @echo + @echo "- 'make prif' :" + @echo " Build the test and link the Caffeine library to provide multi-image feature" + @echo " support through PRIF. This uses pkg-config to find Caffeine and may require setting:" + @echo " PKG_CONFIG_PATH=/lib/pkgconfig" + @echo " Alternatively within an FPM-driven Caffeine build tree you simply can run:" + @echo " ./run-fpm.sh run" + @echo + @echo "------------------------------------------------------------------------------" -print-flags: - @$$FC print-native-flags.F90 -o print-native-flags - @./print-native-flags -s + +PRINT_FLAGS_STAND_ALONE?=-s +print-flags: force + @$$FC $(FLAGS) print-native-flags.F90 -o print-native-flags + @./print-native-flags $(PRINT_FLAGS_STAND_ALONE) @rm -f print-native-flags -gcc: + +prif: force + @export PRINT_FLAGS_STAND_ALONE= ; \ + if [[ -r $(RUN_FPM_SH) ]] ; then \ + FPM_PREFIX=$$(grep PREFIX= $(RUN_FPM_SH) | cut -d= -f2) ; \ + [[ -n $$FPM_PREFIX ]] && export PKG_CONFIG_PATH+=:$$FPM_PREFIX/lib/pkgconfig ; \ + fi ; $(MAKE) prif-doit + +prif-doit: force + $(PKG_CONFIG) --modversion $(CAFFEINE_PKG) >/dev/null + @( $(PKG_CONFIG) --path $(CAFFEINE_PKG) 2>/dev/null || exit 0 ) + @export FC=$(if $(FC_FORCE),$(FC_FORCE),$$($(PKG_CONFIG) --variable=CAFFEINE_FC $(CAFFEINE_PKG))) ; \ + if $$FC --version 2>&1 | grep -q LFortran ; then FC+=" --cpp" ; fi ; \ + set -x ; export NATIVE_FLAGS="$(NATIVE_FLAGS)" && \ + $$FC $$NATIVE_FLAGS native-multi-image.F90 -o native-multi-image-prif \ + $$($(PKG_CONFIG) --libs-only-L $(CAFFEINE_PKG)) \ + $$($(PKG_CONFIG) --libs-only-other $(CAFFEINE_PKG) | awk -v RS=' ' '/-Wl,-rpath/') \ + $$($(PKG_CONFIG) --libs-only-l $(CAFFEINE_PKG)) \ + $(FLAGS) + @export CAF_IMAGES=$(NUM_IMAGES) ; set -x ; eval $$($(PKG_CONFIG) --variable=CAFFEINE_RUNCMD $(CAFFEINE_PKG)) ./native-multi-image-prif + + +gcc: force @set -x ; \ export FC=$(if $(FC_FORCE),$(FC_FORCE),$(GFORTRAN)) ; \ export NATIVE_FLAGS="$(NATIVE_FLAGS)" && \ + ( [[ -n $$NATIVE_FLAGS ]] || \ + ( echo ERROR: Currently requires GFortran 16 or later. ; exit 1 ) ) && \ $$FC -g -fcoarray=lib $$NATIVE_FLAGS $(FLAGS) \ native-multi-image.F90 -o native-multi-image-gcc -lcaf_shmem env GFORTRAN_NUM_IMAGES=$(NUM_IMAGES) ./native-multi-image-gcc -nag: +nag: force @set -x ; \ export FC=$(if $(FC_FORCE),$(FC_FORCE),nagfor) ; \ export NATIVE_FLAGS="$(NATIVE_FLAGS)" && \ @@ -37,7 +92,7 @@ nag: @rm -f native-multi-image.i.F90 env NAGFORTRAN_NUM_IMAGES=$(NUM_IMAGES) ./native-multi-image-nag -cce: +cce: force @set -x ; \ export FC=$(if $(FC_FORCE),$(FC_FORCE),ftn) ; \ export NATIVE_FLAGS="$(NATIVE_FLAGS)" && \ @@ -46,7 +101,7 @@ cce: ./native-multi-image-cce srun -n $(NUM_IMAGES) ./native-multi-image-cce -intel: +intel: force @set -x ; \ export FC=$(if $(FC_FORCE),$(FC_FORCE),ifx) ; \ export NATIVE_FLAGS="$(NATIVE_FLAGS)" && \ @@ -55,6 +110,8 @@ intel: env FOR_COARRAY_NUM_IMAGES=$(NUM_IMAGES) ./native-multi-image-intel clean: - rm -f *.mod *.i.F90 native-multi-image-{gcc,nag,cce,intel} + rm -f *.mod *.i.F90 native-multi-image-{gcc,nag,cce,intel,prif} + +force: -.PHONY: nag gcc clean +.PHONY: force clean diff --git a/app/print-native-flags.F90 b/app/print-native-flags.F90 index 5a7b7a70..3ef237d4 100644 --- a/app/print-native-flags.F90 +++ b/app/print-native-flags.F90 @@ -73,6 +73,7 @@ subroutine write_flags ! no multi-image support before 0.64.0 # else call set("--coarray=true") + call set("--realloc-lhs-arrays") call no("EVENT") call no("LOCK") call no("NOTIFY") diff --git a/install.sh b/install.sh index 2e1e5dde..a20932f6 100755 --- a/install.sh +++ b/install.sh @@ -998,9 +998,23 @@ ________________ Caffeine has been dispensed! ________________ Caffeine is now installed in $PREFIX To rebuild or to run tests or examples via the Fortran Package -Manager (fpm) with the required compiler/linker flags, pass a +Manager (FPM) with the required compiler/linker flags, pass a fpm command to the run-fpm.sh script. For example, run the program example/hello.f90 as follows: -./$RUN_FPM_SH run --example hello + ./$RUN_FPM_SH run --example hello + EOF +if grep '^NATIVEFLAGS=' $RUN_FPM_SH | grep -q DHAVE_MULTI_IMAGE ; then +cat << EOF +To run the more comprehensive test program app/native-multi-image.F90, try: + + ./$RUN_FPM_SH run + +or alternatively (without FPM): + + make -C app prif + +EOF +fi + From 05bfafd235d956c90f2991b492f75acf9a4c9e46 Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Mon, 21 Sep 2026 19:49:52 -0700 Subject: [PATCH 10/11] install.sh: Respect CFLAGS and CPPFLAGS for Caffeine C invocations We were relying on GASNet's detection of CFLAGS and CPPFLAGS which get injected into GASNET_CC and used to build GASNet, however they don't appear in the GASNET_CFLAGS and GASNET_CPPFLAGS that we pass to FPM or CMake. install.sh now directly detects these upon invocations and appends them to the CFLAGS used by FPM or CMake. --- install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index a20932f6..c437d472 100755 --- a/install.sh +++ b/install.sh @@ -62,7 +62,7 @@ JULIENNE_VERSION=$(awk -F'"' '/^julienne =/ {print $4}' manifest/fpm.toml.templa VERBOSE= YES=false USE_FPM=true -APPEND_CFLAGS= +APPEND_CFLAGS="${CPPFLAGS:-} ${CFLAGS:-}" APPEND_CFLAGS_lib= APPEND_LDFLAGS= # these variables deliberately inherited from the caller environment @@ -523,7 +523,7 @@ if [ "${BREW_PREFIX:-unset}" != unset ] ; then # fixups necessitated by using Brew flang: 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))" + APPEND_CFLAGS+=" -I$(dirname $(find "$BREW_PREFIX/Cellar/flang" -name ISO_Fortran_binding.h | head -1))" if [ $(uname) = "Linux" ]; then # workaround brew's libflang_rt.runtime.so missing from default linker path on Linux From a504f6fb45587cbc960b682c52acd033a13067ce Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Mon, 21 Sep 2026 19:42:06 -0700 Subject: [PATCH 11/11] Update documentation --- README.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d8b0787e..980bcde7 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,8 @@ The `install.sh` script uses the following packages to build Caffeine: - LLVM Flang versions 19 or newer, - GNU Fortran versions 13 or newer, and - LFortran versions 0.64 or newer -* [`fpm`](https://github.com/fortran-lang/fpm), the Fortran package manager +* [`fpm`](https://github.com/fortran-lang/fpm), the Fortran package manager (optional) + * -*or*- [`cmake`](https://cmake.org/) * [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) * [GNU make](https://www.gnu.org/software/make/) * [git](https://git-scm.com) @@ -102,6 +103,12 @@ env FC= CC= CXX= ./install.sh CC= CXX= ./install.sh --enable-cmake +make -C app prif +``` + If `$FC` or `$CC` are unset, then `install.sh` will look for LLVM-based compilers in the `PATH`, and failing that, offer to install such compilers using Homebrew. @@ -139,18 +146,23 @@ 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: +test using FPM: ```bash env CAF_IMAGES=8 ./run-fpm.sh run ``` -This will exercise the available PRIF feature set of the compiler version +Alternatively without use of FPM: +```bash +make -C app prif +``` + +This test will exercise the available PRIF feature set of the compiler version detected at install time. Run tests --------- After installation, one can optionally issue the following command to run -Caffeine's correctness unit tests to exercise the PRIF subroutines: +Caffeine's correctness unit tests to exercise the PRIF subroutines (requires FPM): ``` ./run-fpm.sh test