Building OpenCoarrays on macOS
– everything from the sources – gcc-9.2.0

——————

Most recent version of this post can be found here: gcc-13.2.0

——————

This article focuses on installation based on gcc-9.2.0.

There are quite a lot of perquisites for this article, but there are two, most important ones. You will need: huge cup of coffee/tea and something to do between various compilation steps (good book would be handy, maybe some movie on Netflix).

There are few steps you have to do, if you want to have everything built from the sources.

——————

1. GCC

This part of tutorial is heavily based on this article – in fact I have stolen the whole idea: https://solarianprogrammer.com/2019/10/12/compiling-gcc-macos/. However, I have changed it a little bit to make all the places local – I want things to be installed inside my $HOME/opt. If you prefer having gcc installed system wide, proceed with the steps above.

First of all, make sure to create place where all the sources and all the compiled codes will go. Note that in case of macOS I am strongly against installing stuff inside /usr. First of all, you have no idea when and what Apple decides to do with central locations – they can protect them, remove, change name, do whatever they want. Second thing is that I prefer to keep all the things close to my $HOME so I can easily move things around and pick arbitrary location for the stuff I build.

> mkdir -p $HOME/opt/usr/local
> mkdir -p $HOME/opt/src

Download gcc-9.2.0.

> cd $HOME/opt/src
> mkdir gcc
> cd gcc
> curl -L -O https://ftpmirror.gnu.org/gcc/gcc-9.2.0/gcc-9.2.0.tar.xz
> tar zxf gcc-9.2.0.tar.xz

Get all the dependencies.

> cd gcc-9.2.0
> contrib/download_prerequisites

Now, this is the step I have stolen from the page mentioned above. We have to create artificial system root. The reason here is that Apple removed /usr/include and moved it inside XCode based platforms. Note that I prefer to create everything inside my $HOME/opt.

> mkdir -p $HOME/opt/usr/local/gcc_system_root
> cd $HOME/opt/usr/local/gcc_system_root
> ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/Library .
> ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System .
> mkdir usr && cd usr
> ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/bin .
> ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib .
> ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/libexec .
> ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/share .
> cp -r /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include include

Now, we have to alter the file Availability.h. Apply this patch (save it inside your $HOME/Availability.h.patch) (you can download it here).

--- /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/Availability.h	2019-11-07 07:07:28.000000000 +0100
+++ Availability.h	2020-01-18 12:17:58.000000000 +0100
@@ -307,6 +307,12 @@
     #define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(_osxIntro, _osxDep, _iosIntro, _iosDep, _msg)
 #endif

+#ifndef __OSX_AVAILABLE_STARTING
+    #define __OSX_AVAILABLE_STARTING(_osx, _ios)
+    #define __OSX_AVAILABLE_BUT_DEPRECATED(_osxIntro, _osxDep, _iosIntro, _iosDep)
+    #define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(_osxIntro, _osxDep, _iosIntro, _iosDep, _msg)
+#endif
+

 #if defined(__has_feature)
   #if __has_feature(attribute_availability_with_message)

apply it following way

> patch -b $HOME/opt/usr/local/gcc_system_root/usr/include/Availability.h $HOME/Availability.h.patch

Now, we can configure the build of gcc.

> cd $HOME/opt/src/gcc/gcc-9.2.0
> mkdir build && cd build
> ../configure --prefix=$HOME/opt/usr/local/gcc/gcc-9.2.0 \
               --enable-checking=release \
               --enable-languages=c,c++,fortran \
               --disable-multilib \
               --with-sysroot=$HOME/opt/usr/local/gcc_system_root \
               --program-suffix=-9.2.0

And, once it’s finished, we can build it and install it

> make
> make install

Eventually, you can test it

> cd $HOME
> echo '#include <stdio.h> \nvoid main() { printf("Hello from gcc-9.2.0\\n"); }' \
$HOME/opt/usr/local/gcc/gcc-9.2.0/bin/g++-9.2.0 -x c -o hello -; ./hello

If you want, you can update your PATH variable such way it points to this location

export PATH=$HOME/opt/usr/local/gcc/gcc-9.2.0/bin:${PATH}

——————

2. MPICH

You need MPICH for OpenCoarrays. Note that MPICH serves as transport layer for OpenCoarrays project (it is said to work with OpenMPI as well).

> mkdir -p $HOME/opt/src/mpich
> cd $HOME/opt/src/mpich
> curl -L -O https://www.mpich.org/static/downloads/3.3.1/mpich-3.3.1.tar.gz
> tar zxf mpich-3.3.1.tar.gz
> cd mpich-3.3.1
> export CC=$HOME/opt/usr/local/gcc/gcc-9.2.0/bin/gcc-9.2.0
> export CXX=$HOME/opt/usr/local/gcc/gcc-9.2.0/bin/g++-9.2.0
> export FC=$HOME/opt/usr/local/gcc/gcc-9.2.0/bin/gfortran-9.2.0
> export FC77=$HOME/opt/usr/local/gcc/gcc-9.2.0/bin/gfortran-9.2.0
> ./configure --prefix=$HOME/opt/usr/local/mpich/mpich-3.3.1-gcc-9.2.0
> make
> make install

Once you have it installed, you can test it with simple code.

program main
  use mpi

  integer error, id, p

  call MPI_Init ( error )
  call MPI_Comm_size ( MPI_COMM_WORLD, p, error )
  call MPI_Comm_rank ( MPI_COMM_WORLD, id, error )
  write (*,*) 'Hello: ', id, '/', p
  call MPI_Finalize ( error )
end

Save it inside $HOME/tmp/hello.f90 and build it.

> cd $HOME/tmp
> $HOME/opt/usr/local/mpich/mpich-3.3.1-gcc-9.2.0/bin/mpif90 -o hello hello.f90
> $HOME/opt/usr/local/mpich/mpich-3.3.1-gcc-9.2.0/bin/mpirun -np 4 ./hello
 Hello:            0 /           4
 Hello:            1 /           4
 Hello:            3 /           4
 Hello:            2 /           4

You are done with MPICH. We can now move to OpenMPI.

——————

3. OpenMPI

OpenCoarrays can also be based on OpenMPI as transport layer. Let’s build OpenMPI

> mkdir -p $HOME/opt/src/openmpi
> cd $HOME/opt/src/openmpi
> curl -L -O https://download.open-mpi.org/release/open-mpi/v4.0/openmpi-4.0.2.tar.gz
> tar zxf openmpi-4.0.2.tar.gz
> cd openmpi-4.0.2
> export CC=$HOME/opt/usr/local/gcc/gcc-9.2.0/bin/gcc-9.2.0
> export CXX=$HOME/opt/usr/local/gcc/gcc-9.2.0/bin/g++-9.2.0
> export FC=$HOME/opt/usr/local/gcc/gcc-9.2.0/bin/gfortran-9.2.0
> export FC77=$HOME/opt/usr/local/gcc/gcc-9.2.0/bin/gfortran-9.2.0
> ./configure --prefix=$HOME/opt/usr/local/openmpi/openmpi-4.0.2-gcc-9.2.0
> make
> make install

Once you have OpenMPI installed, you can test it with simple code.

program main
  use mpi

  integer error, id, p

  call MPI_Init ( error )
  call MPI_Comm_size ( MPI_COMM_WORLD, p, error )
  call MPI_Comm_rank ( MPI_COMM_WORLD, id, error )
  write (*,*) 'Hello: ', id, '/', p
  call MPI_Finalize ( error )
end

Save it inside $HOME/tmp/hello.f90 and build it.

> cd $HOME/tmp
> $HOME/opt/usr/local/openmpi/openmpi-4.0.2-gcc-9.2.0/bin/mpif90 -o hello hello.f90
> $HOME/opt/usr/local/openmpi/openmpi-4.0.2-gcc-9.2.0/bin/mpirun -np 4 ./hello
 Hello:            0 /           4
 Hello:            1 /           4
 Hello:            3 /           4
 Hello:            2 /           4

You are done with OpenMPI. We can now move to CMake – it is needed by OpenCoarrays.

——————

4. CMake

You need CMake in order to build OpenCoarrays. And, again, I prefer to have it installed my way.

> mkdir -p $HOME/opt/src/cmake
> cd $HOME/opt/src/cmake
> curl -o https://github.com/Kitware/CMake/releases/download/v3.16.1/cmake-3.16.1.tar.gz
> tar zxf cmake-3.16.1.tar.gz
> cd cmake-3.16.1
> ./bootstrap --prefix=$HOME/opt/usr/local/cmake/cmake-3.16.1
> make
> make install

You can test whether it works following way

> $HOME/opt/usr/local/cmake/cmake-3.16.1/bin/cmake --version
cmake version 3.16.1

CMake suite maintained and supported by Kitware (kitware.com/cmake).

——————

5. OpenCoarrays – MPICH flavour

Now, let’s install OpenCoarrays witm MPICH as a transport layer.

> cd $HOME/opt/src/OpenCoarrays
> cd $HOME/opt/src/OpenCoarrays
> curl -L -O \
  https://github.com/sourceryinstitute/OpenCoarrays/releases/download/2.8.0/OpenCoarrays-2.8.0.tar.gz
> tar zxf OpenCoarrays-2.8.0.tar.gz
> cd OpenCoarrays-2.8.0
> mkdir opencoarrays-build-mpich
> cd opencoarrays-build-mpich
> $HOME/opt/usr/local/cmake/cmake-3.16.1/bin/cmake \
 $HOME/opt/src/OpenCoarrays/OpenCoarrays-2.8.0 \
-DMPI_Fortran_COMPILER=$HOME/opt/usr/local/mpich/mpich-3.3.1-gcc-9.2.0/bin/mpif90 \
-DMPI_C_COMPILER=$HOME/opt/usr/local/mpich/mpich-3.3.1-gcc-9.2.0/bin/mpicc \
-DMPIEXEC_EXECUTABLE=$HOME/opt/usr/local/mpich/mpich-3.3.1-gcc-9.2.0/bin/mpiexec \
-DCMAKE_INSTALL_PREFIX=$HOME/opt/usr/local/OpenCoarrays/OpenCoarrays-2.8.0-mpich-3.3.1-gcc-9.2.0
> make
> make test
> make install

——————

6. OpenCoarrays – OpenMPI flavour

Now, let’s install OpenCoarrays witm OpenMPI as a transport layer.

> cd $HOME/opt/src/OpenCoarrays/OpenCoarrays-2.8.0
> mkdir opencoarrays-build-openmpi
> cd opencoarrays-build-openmpi
> $HOME/opt/usr/local/cmake/cmake-3.16.1/bin/cmake \
 $HOME/opt/src/OpenCoarrays/OpenCoarrays-2.8.0 \
-DMPI_Fortran_COMPILER=$HOME/opt/usr/local/openmpi/openmpi-4.0.2-gcc-9.2.0/bin/mpif90 \
-DMPI_C_COMPILER=$HOME/opt/usr/local/openmpi/openmpi-4.0.2-gcc-9.2.0/bin/mpicc \
-DMPIEXEC_EXECUTABLE=$HOME/opt/usr/local/openmpi/openmpi-4.0.2-gcc-9.2.0/bin/mpiexec \
-DCMAKE_INSTALL_PREFIX=$HOME/opt/usr/local/OpenCoarrays/OpenCoarrays-2.8.0-openmpi-4.0.2-gcc-9.2.0
> make
> make test
> make install

——————

7. First coarray Fortran code

The time is now :) You can run your very first coarray based code.

program hello_world
implicit none
  write(*,*) 'Hello world from ', &
   this_image() , 'of', num_images()
end program hello_world

Save this file inside $HOME/tmp/hello_world.f90.

Let’s run it with MPICH based OpenCoarrays

> cd $HOME/tmp
> $HOME/opt/usr/local/OpenCoarrays/OpenCoarrays-2.8.0-mpich-3.3.1-gcc-9.2.0/bin/caf \
  -o hello_world hello_world.f90
> $HOME/opt/usr/local/OpenCoarrays/OpenCoarrays-2.8.0-mpich-3.3.1-gcc-9.2.0/bin/cafrun \
  -np 2 ./hello_world
 Hello world from            1 of           2
 Hello world from            2 of           2

Let’s run it with MPICH based OpenCoarrays

> cd $HOME/tmp
> $HOME/opt/usr/local/OpenCoarrays/OpenCoarrays-2.8.0-openmpi-4.0.2-gcc-9.2.0/bin/caf \
  -o hello_world hello_world.f90
> $HOME/opt/usr/local/OpenCoarrays/OpenCoarrays-2.8.0-openmpi-4.0.2-gcc-9.2.0/bin/cafrun \
  -np 2 ./hello_world
 Hello world from            1 of           2
 Hello world from            2 of           2

You did it!! You have macOS based environment for coarray based development in Fortran :)