Difference between revisions of "XIOS on an Apple Silicon Mac"
(→Compiling XIOS on macOS (Apple Silicon) with Open MPI and Clang) |
(→Compiling XIOS on macOS (Apple Silicon) with openmpi and clang) |
||
| Line 1: | Line 1: | ||
= Compiling XIOS on macOS (Apple Silicon) with openmpi and clang = | = Compiling XIOS on macOS (Apple Silicon) with openmpi and clang = | ||
| − | This page | + | This page makes the assumption that you have built and installed the parallel version of NetCDF similarly to that described on the page [[NetCDF-Parallel on an Apple Silicon Mac]]. Below, one finds the three XIOS arch files needed to build XIOS on macOS (using Homebrew gfortran and Homebrew Open MPI). The customizations here with respect to the stock <code>arch-gfortran</code> files are driven by the Open MPI C++ wrapper calling Apple '''clang''', not GCC (e.g., [[#Background: Open MPI uses Clang, not GCC|the background section]]). |
== Tested environment == | == Tested environment == | ||
Latest revision as of 12:37, 16 October 2026
Contents
Compiling XIOS on macOS (Apple Silicon) with openmpi and clang
This page makes the assumption that you have built and installed the parallel version of NetCDF similarly to that described on the page NetCDF-Parallel on an Apple Silicon Mac. Below, one finds the three XIOS arch files needed to build XIOS on macOS (using Homebrew gfortran and Homebrew Open MPI). The customizations here with respect to the stock arch-gfortran files are driven by the Open MPI C++ wrapper calling Apple clang, not GCC (e.g., the background section).
Tested environment
- macOS 26 (Darwin 25.6.0), Apple Silicon (arm64)
- GNU Fortran 16.2.0 (Homebrew), installed as
gfortran - Apple clang 21, which provides
/usr/bin/cppand is called bympiCC - Open MPI 5.0.11 (Homebrew)
- netCDF-C 4.10.1 and netCDF-Fortran 4.6.4, compiled from source against Open MPI(which is where the CLANG dependence originates) and installed in
/opt/parallel-netcdf
Arch files
Create these three files in the arch/ directory of your XIOS source tree.
arch/arch-CLANG_MACOSX.env
Change NETCDF_DIR to match your netCDF installation.
# Environment to compile XIOS on Mac OS X with NETCDF compiled with CLANG (through openmpi)
#
# Tested successfully with :
# Mac OS X 25.6.0
# Prerequisite softwares installed with Homebrew
# gfortran : 16.2.0
# openmpi : 5.0.11
#
# Compiled from source with open-mpi
# netcdf : netCDF 4.10.1 netCDF-Fortran 4.6.4
#
#
export NETCDF_DIR=/opt/parallel-netcdf
export NETCDF_INC_DIR=${NETCDF_DIR}/include
export NETCDF_LIB_DIR=${NETCDF_DIR}/lib
arch/arch-CLANG_MACOSX.fcm
################################################################################ ################### Projet XIOS ################### ################################################################################ #Build environment (2026-10-13): # #- macOS 26 (Darwin 25.6.0), arm64 #- GNU Fortran 16.2.0 (Homebrew), installed as `gfortran` #- Apple clang 21, which provides `/usr/bin/cpp` and is wrapped by `mpiCC` #- Open MPI 5.0.11 (Homebrew) ## Summary %CCOMPILER mpiCC %FCOMPILER mpif90 %LINKER mpif90 %BASE_CFLAGS -w -std=gnu++11 %PROD_CFLAGS -O3 -D BOOST_DISABLE_ASSERTS %DEV_CFLAGS -g %DEBUG_CFLAGS -g -O2 %BASE_FFLAGS -D__NONE__ -ffree-line-length-none %PROD_FFLAGS -O3 %DEV_FFLAGS -g -O2 %DEBUG_FFLAGS -g %BASE_INC -D__NONE__ %BASE_LD -lc++ %CPP cpp -P -undef %FPP cpp-16 -P %MAKE make
arch/arch-CLANG_MACOSX.path
This file gets the netCDF flags from nc-config and nf-config, so both must be on your PATH.
NETCDF_INCDIR="$(nc-config --cflags) $(nf-config --fflags)" NETCDF_LIBDIR="$(nc-config --libs) $(nf-config --flibs)" NETCDF_LIB=""
Building
From the top of the XIOS source tree:
./make_xios --arch CLANG_MACOSX --job 8 --full > make_xios.out 2>&1
Use --full to rebuild from scratch.
A successful build produces:
-
lib/libxios.a
Background: Open MPI uses Clang, not GCC
On Linux, mpif90, mpicc and mpicxx usually all call the GNU compilers. With Homebrew on macOS, Open MPI is built with Apple's toolchain. Only the Fortran wrapper calls GCC:
| Component | Wrapper | Underlying compiler | C++ standard library |
|---|---|---|---|
| XIOS (C++ core) | mpiCC |
Apple clang | libc++ (LLVM), linked with -lc++
|
| XIOS Fortran interface, and the model (e.g. LMDZ / PCM) | mpif90 |
Homebrew gfortran | none (GCC Fortran runtime) |
This mix causes two problems: one with the preprocessor and one at link time.
Why mpiCC is really clang
macOS filesystems are case-insensitive by default, so the files mpiCC and mpicc cannot both exist. Homebrew's Open MPI makes /opt/homebrew/bin/mpiCC a symlink to the C wrapper mpicc, which calls Apple clang:
$ mpiCC --showme clang -I/opt/homebrew/Cellar/open-mpi/5.0.11/include -L/opt/homebrew/Cellar/open-mpi/5.0.11/lib -lmpi
clang still compiles the XIOS .cpp files as C++, because it picks the language from the file extension. But it compiles them against libc++, LLVM's C++ standard library, not GCC's libstdc++.
A side effect: OMPI_CXX has no effect on mpiCC, because mpiCC is really mpicc, and mpicc reads OMPI_CC.
1. Link library: -lc++ instead of -lstdc++
The stock arch-gfortran.fcm sets %BASE_LD -lstdc++. With clang-compiled C++ objects, the link of xios_server.exe fails with errors like:
Undefined symbols for architecture arm64: "std::__1::basic_string<...>::copy(...) const", referenced from: ... "std::__1::regex_error::regex_error(...)", referenced from: ... ld: symbol(s) not found for architecture arm64
The std::__1:: prefix is libc++'s inline namespace. libstdc++ uses different names, such as std::__cxx11::. The two libraries are not interchangeable at link time: an object compiled against libc++ can only be linked with libc++.
The final link is done by mpif90 (gfortran), and gfortran does not add any C++ library on its own. The arch file must name the right one, so %BASE_LD is set to -lc++.
This also applies to every program that links against this libxios.a. For example, the LMDZ / PCM arch .path file must use:
XIOS_LIB="-lxios -lc++"
and not -lstdc++. Otherwise the model build compiles all its sources and then fails at the final link with hundreds of undefined std::__1:: symbols coming from libxios.a.
To check which C++ library an existing libxios.a needs:
nm -C lib/libxios.a | grep -m1 'std::__1::' # match -> libc++ (-lc++) nm -C lib/libxios.a | grep -m1 'std::__cxx11::' # match -> libstdc++ (-lstdc++)
The rule: the C++ library named at link time must be the same one that compiled XIOS. If you rebuild XIOS with GCC's g++ instead (for example %CCOMPILER mpicxx with export OMPI_CXX=g++-16), switch back to -lstdc++ in both the XIOS and the model arch files.
2. Fortran preprocessor: cpp-16 instead of cpp
The XIOS Fortran interface builds its names with a token-pasting macro, defined in src/interface/fortran/xios_fortran_prefix.hpp:
#define xios(arg) xios_##arg #define txios(arg) xios_##arg
On macOS, /usr/bin/cpp is Apple clang. It does not expand ## in these files, so txios(duration) comes out as xios_##duration instead of xios_duration. Compilation then fails, for example in duration_interface.f90:
IMPORT :: xios_##duration Error: Syntax error in IMPORT statement at (1) TYPE(xios_##duration), VALUE :: dur Error: Malformed type-spec at (1)
The fix is to use the GNU C preprocessor that comes with Homebrew GCC for Fortran files: %FPP cpp-16 -P. The -16 suffix follows the major version of Homebrew GCC. If GCC is upgraded, update this line to match. Check the installed version with:
ls /opt/homebrew/bin/cpp-*
gfortran -E -P -cpp may also work as the Fortran preprocessor, but it has not been tested.
Harmless warning
The XIOS build and the model builds may print:
ld: warning: ignoring duplicate libraries: '-lnetcdf'
It appears because nc-config --libs and nf-config --flibs both list -lnetcdf. You can ignore it.