Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,27 @@ jobs:
version: 22
network: smp
native_multi_image: 1
brew_via_install: 1
FFLAGS: -fcoarray
- os: macos-15
compiler: flang
version: 22
network: smp
brew_via_install: 1
native_multi_image: 1
FFLAGS: -fcoarray
- os: macos-15-intel
compiler: flang
version: 22
network: smp
brew_via_install: 1
native_multi_image: 1
FFLAGS: -fcoarray
- os: macos-26
compiler: flang
version: 22
network: smp
brew_via_install: 1
native_multi_image: 1
FFLAGS: -fcoarray

Expand Down Expand Up @@ -177,7 +181,7 @@ jobs:
echo "CXX=g++-${COMPILER_VERSION}" >> "$GITHUB_ENV"

- name: Set flang variables
if: matrix.compiler == 'flang'
if: ${{ matrix.compiler == 'flang' && !matrix.brew_via_install }}
run: |
set -x
echo "FC=flang-new" >> "$GITHUB_ENV"
Expand Down Expand Up @@ -239,15 +243,15 @@ jobs:
apt install -y build-essential pkg-config make git curl

- name: Install macOS Dependencies
if: contains(matrix.os, 'macos')
if: ${{ contains(matrix.os, 'macos') && !matrix.brew_via_install }}
run: |
set -x
brew update
# fpm binary distribution for macOS requires gfortran shared libraries from gcc@12
brew install gcc@12

- name: Install LLVM flang on macOS
if: contains(matrix.os, 'macos') && matrix.compiler == 'flang'
if: ${{ contains(matrix.os, 'macos') && matrix.compiler == 'flang' && !matrix.brew_via_install }}
run: |
set -x
brew install llvm@${COMPILER_VERSION} flang
Expand All @@ -258,6 +262,7 @@ jobs:
echo "PATH=$(brew --prefix)/opt/llvm/bin:${PATH}" >> "$GITHUB_ENV"

- name: Setup FPM
if: ${{ !matrix.brew_via_install }}
uses: fortran-lang/setup-fpm@main
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -283,7 +288,9 @@ jobs:
echo
echo PATH="$PATH"
for tool in ${FC} ${CC} ${CXX} fpm ; do
( echo ; set -x ; w=$(which $tool) ; ls -al $w ; ls -alhL $w ; $tool --version )
if command -v $tool > /dev/null 2>&1 ; then
( echo ; set -x ; w=$(which $tool) ; ls -al $w ; ls -alhL $w ; $tool --version )
fi
done

- name: Build Caffeine (install.sh)
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ Prerequisites & Dependencies
### Build prerequisites
The `install.sh` script uses the following packages:
* Fortran and C compilers
* We regularly test with: GNU Fortran versions 13, 14, 15 and LLVM Flang versions 19, 20, 21
* On macOS the Homebrew-installed `llvm` and `flang` packages may require some
additional settings, see [issue #228](https://github.com/BerkeleyLab/caffeine/issues/228) for the latest information.
* We regularly test with: LLVM Flang versions 19:22 and GNU Fortran versions 13:15
* [Fortran package manager] `fpm`
* [pkg-config]
* [realpath]
Expand Down Expand Up @@ -98,7 +96,10 @@ env FC=<Fortran-compiler> CC=<C-compiler> CXX=<C++-compiler> ./install.sh <optio
env CAF_IMAGES=8 ./run-fpm.sh run --example hello
```

The provided compilers MUST be "compatible": for the best experience you are
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.

The selected compilers MUST be "compatible": for the best experience you are
HIGHLY recommended to specify the language frontends provided by a single version
of a given compiler suite installation. The C++ compiler is optional for
single-node deployments (and can be disabled using command-line option `--without-cxx`),
Expand All @@ -107,10 +108,9 @@ but C++ is required for some network backends.
*Note for macOS/Homebrew users*: Homebrew may be used to install
[LLVM flang](https://formulae.brew.sh/formula/flang) for use with Caffeine, however
by default Homebrew will not replace the incompatible Apple-provided `clang` in your `PATH`.
Such users are recommended to use Homebrew's version-suffixed compiler variants,
for example setting `FC=flang-21 CC=clang-21 CXX=clang++-21` in the command above,
Such users are recommended to use Homebrew's matching LLVM C/C++ compilers
(usually installed in `/opt/homebrew/opt/llvm/bin`)
to ensure that a matching set of LLVM compilers are used.
See also [issue #228](https://github.com/BerkeleyLab/caffeine/issues/228).

The `install.sh` recognizes a number of command-line options and environment variables to
customize behavior for your system. See the output of `./install.sh --help` for full documentation,
Expand Down
134 changes: 94 additions & 40 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ Report bugs to fortran@lbl.gov or at https://go.lbl.gov/caffeine
EOF
}

GCC_VERSION=${GCC_VERSION:=14}
GASNET_VERSION="stable"
VERBOSE=""
GASNET_CONDUIT="${GASNET_CONDUIT:-smp}"
YES=false
APPEND_CFLAGS=""

list_prerequisites()
{
Expand All @@ -58,7 +58,7 @@ Caffeine and this installer were developed with the following prerequisites.
If any are missing and if permission is granted, the installer will install
the latest versions using Homebrew:

GCC $GCC_VERSION
LLVM flang
GASNet-EX $GASNET_VERSION
fpm
git (used by fpm to clone dependencies)
Expand Down Expand Up @@ -115,23 +115,57 @@ while [ "$1" != "" ]; do
shift
done

set -u # error on use of undefined variable
# Early check for pre-installed Homebrew
BREW="${BREW:-brew}"
if command -v "$BREW" > /dev/null 2>&1; then
BREW_PREFIX=`$BREW --prefix || exit 0`
if [ -z ${BREW_PREFIX:+x} ] || [ ! -d "$BREW_PREFIX" ] ; then
echo Warning: Failed to detect Homebrew prefix
BREW_PREFIX=
fi
fi

if [ -z ${FC+x} ] || [ -z ${CC+x} ] || [ -z ${CXX+x} ]; then
if command -v gfortran-$GCC_VERSION > /dev/null 2>&1; then
FC=`which gfortran-$GCC_VERSION`
if [ -z ${FC:+x} ] || [ -z ${CC:+x} ]; then
if command -v flang > /dev/null 2>&1; then
FC=`which flang`
echo "Setting FC=$FC"
if [ -n "$BREW_PREFIX" ] && [[ $FC =~ $BREW_PREFIX ]] ; then
# We are using Homebrew flang, so prefer Homebrew clang/clang++
export PATH="$BREW_PREFIX/opt/llvm/bin:$PATH"
fi
fi
if command -v gcc-$GCC_VERSION > /dev/null 2>&1; then
CC=`which gcc-$GCC_VERSION`
if command -v clang > /dev/null 2>&1; then
CC=`which clang`
echo "Setting CC=$CC"
fi
if command -v g++-$GCC_VERSION > /dev/null 2>&1; then
CXX=`which g++-$GCC_VERSION`
fi
if [ -n "$CC" ] && ! command -v "$CC" > /dev/null 2>&1; then
echo "CC=$CC not found. If you don't yet have a C compiler, please leave environment variable CC unset."
exit 1
fi
if [ -n "$FC" ] && ! command -v "$FC" > /dev/null 2>&1; then
echo "FC=$FC not found. If you don't yet have a Fortran compiler, please leave environment variable FC unset."
exit 1
fi
if [ -z ${CXX:+x} ] && [ -n "$CC" ] ; then
# C++ is an optional dependency
# try to auto-detect from CC
if [[ $(basename $CC) =~ clang ]] ; then
CXX_guess=clang++
else
CXX_guess=g++
fi
if [[ $CC =~ (-[0-9]+)$ ]] ; then
CXX_guess=${CXX_guess}${BASH_REMATCH[0]}
fi
if command -v $CXX_guess > /dev/null 2>&1; then
CXX=`which $CXX_guess`
echo "Setting CXX=$CXX"
fi
fi

set -u # error on use of undefined variable

if command -v pkg-config > /dev/null 2>&1; then
PKG_CONFIG=`which pkg-config`
fi
Expand Down Expand Up @@ -163,7 +197,7 @@ ask_permission_to_use_homebrew()
{
cat << EOF

Either one or more of the environment variables FC, CC, and CXX are unset or
Either one or more of the environment variables FC and CC are unset or
one or more of the following packages are not in the PATH: pkg-config, realpath, make, fpm.
If you grant permission to install prerequisites, you will be prompted before each installation.

Expand Down Expand Up @@ -212,9 +246,9 @@ exit_if_user_declines()
case ${1:-} in
*GASNet*)
echo "Please ensure the $pkg.pc file is in $PKG_CONFIG_PATH and then rerun './install.sh'." ;;
*GCC*)
echo "To use compilers other than Homebrew-installed gcc-$GCC_VERSION, g++-$GCC_VERSION, and gfortran-$GCC_VERSION,"
echo "please set the FC, CC, and CXX environment variables and rerun './install.sh'." ;;
*FC*)
echo "To use compilers other than Homebrew-installed LLVM flang and clang,"
echo "please set the FC and CC environment variables and rerun './install.sh'." ;;
*)
echo "Please ensure that $1 is installed and in your PATH and then rerun './install.sh'." ;;
esac
Expand All @@ -228,13 +262,11 @@ if [ ! -d $DEPENDENCIES_DIR ]; then
mkdir -p $DEPENDENCIES_DIR
fi

if [ -z ${FC+x} ] || [ -z ${CC+x} ] || [ -z ${CXX+x} ] || [ -z ${PKG_CONFIG+x} ] || [ -z ${REALPATH+x} ] || [ -z ${MAKE+x} ] || [ -z ${FPM+x} ] ; then
if [ -z ${FC:+x} ] || [ -z ${CC:+x} ] || [ -z ${PKG_CONFIG:+x} ] || [ -z ${REALPATH:+x} ] || [ -z ${MAKE:+x} ] || [ -z ${FPM:+x} ] ; then

ask_permission_to_use_homebrew
exit_if_user_declines "brew"

BREW="brew"

if ! command -v $BREW > /dev/null 2>&1; then

ask_permission_to_install_homebrew
Expand Down Expand Up @@ -264,47 +296,62 @@ EOF
fi
fi

if [ -z ${FC+x} ] || [ -z ${CC+x} ] || [ -z ${CXX+x} ]; then
ask_permission_to_install_homebrew_package "gfortran, gcc, and g++" "gcc@$GCC_VERSION"
exit_if_user_declines "GCC"
"$BREW" install gcc@$GCC_VERSION
if [ uname == "Linux" ]; then
brew link --force glibc
fi
BREW_PREFIX=`$BREW --prefix || exit 0`
if [ -z ${BREW_PREFIX:+x} ] || [ ! -d "$BREW_PREFIX" ] ; then
echo Failed to detect Homebrew prefix
echo 1
fi
CC=`which gcc-$GCC_VERSION`
CXX=`which g++-$GCC_VERSION`
FC=`which gfortran-$GCC_VERSION`

if [ -z ${REALPATH+x} ] || [ -z ${MAKE+x} ] ; then
# fetch the latest package definitions:
$BREW update

if [ -z ${FC:+x} ] || [ -z ${CC:+x} ] ; then
ask_permission_to_install_homebrew_package "'llvm' and 'flang'"
exit_if_user_declines "FC"
$BREW install llvm flang

# Homebrew does not inject clang/clang++ into PATH on macOS
export PATH="$BREW_PREFIX/opt/llvm/bin:$PATH"
CC=`which clang`
CXX=`which clang++`
FC=`which flang-new`
for tool in $CC $CXX $FC ; do
if ! command -v $tool > /dev/null 2>&1 ; then
echo Failed to detect Homebrew compiler install at $tool
exit 1
fi
done
fi

if [ -z ${REALPATH:+x} ] || [ -z ${MAKE:+x} ] ; then
ask_permission_to_install_homebrew_package "'realpath' and 'make'" "coreutils"
exit_if_user_declines "realpath"
"$BREW" install coreutils
exit_if_user_declines "realpath and make"
$BREW install coreutils
REALPATH=`which realpath`
MAKE=`which make`
fi
REALPATH=`which realpath`

if [ -z ${PKG_CONFIG+x} ]; then
if [ -z ${PKG_CONFIG:+x} ]; then
ask_permission_to_install_homebrew_package "'pkg-config'"
exit_if_user_declines "pkg-config"
"$BREW" install pkg-config
$BREW install pkg-config
PKG_CONFIG=`which pkg-config`
fi
PKG_CONFIG=`which pkg-config`

if [ -z ${FPM+x} ] ; then
if [ -z ${FPM:+x} ] ; then
ask_permission_to_install_homebrew_package "'fpm'"
exit_if_user_declines "fpm"
"$BREW" tap fortran-lang/hombrew-fortran
"$BREW" install fpm
$BREW install fpm
FPM=`which fpm`
fi
FPM=`which fpm`
fi

PREFIX=${PREFIX:-"${HOME}/.local"}
mkdir -p "$PREFIX"
PREFIX=`$REALPATH "$PREFIX"`
echo "PREFIX=$PREFIX"

if [ -z ${PKG_CONFIG_PATH+x} ]; then
if [ -z ${PKG_CONFIG_PATH:+x} ]; then
PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig"
else
PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH"
Expand All @@ -317,6 +364,13 @@ if [[ $FPM_FC == *flang* ]]; then
fi
FPM_CC="$($REALPATH $(command -v $CC))"

# workaround issue #228: clang cannot find Homebrew flang's C header
if [ "${BREW_PREFIX:-unset}" != unset ] ; then
if [[ $FPM_FC =~ flang ]] && [[ $FPM_FC =~ $BREW_PREFIX ]] ; then
APPEND_CFLAGS="-I$(dirname $(find "$BREW_PREFIX/Cellar/flang" -name ISO_Fortran_binding.h | head -1))"
fi
fi

ask_package_permission()
{
cat << EOF
Expand Down Expand Up @@ -436,7 +490,7 @@ cat << EOF > $CAFFEINE_PC
CAFFEINE_FPM_LDFLAGS=$GASNET_LDFLAGS $GASNET_LIB_LOCATIONS
CAFFEINE_FPM_FC=$FPM_FC
CAFFEINE_FPM_CC=$GASNET_CC
CAFFEINE_FPM_CFLAGS=$GASNET_CFLAGS $GASNET_CPPFLAGS
CAFFEINE_FPM_CFLAGS=$GASNET_CFLAGS $GASNET_CPPFLAGS $APPEND_CFLAGS
Name: caffeine
Description: Coarray Fortran parallel runtime library
URL: https://gitlab.lbl.gov/berkeleylab/caffeine
Expand Down