All,
I’m hoping to get some help using Intel MPI with CMake, but with GNU Fortran as the compiler, not Intel Fortran (which works fine). For example, I have a code called mpiversion.F90
that isn’t very special:
program main
use mpi
implicit none
integer :: ierror, n
character(MPI_MAX_LIBRARY_VERSION_STRING) :: version_string
call MPI_Get_library_version(version_string, n, ierror)
write(*,*) trim(version_string)
end program main
And I have loaded GCC 8.3.0 and Intel MPI 2019 Update 5:
(1039) $ gfortran --version
GNU Fortran (GCC) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
(1040) $ mpirun --version
Intel(R) MPI Library for Linux* OS, Version 2019 Update 5 Build 20190806 (id: 7e5a4f84c)
Copyright 2003-2019, Intel Corporation.
And I can build and run the program just fine by hand using the mpifc
wrapper:
(1043) $ mpifc -o mpiversion.exe mpiversion.F90
(1044) $ ./mpiversion.exe
Intel(R) MPI Library 2019 Update 5 for Linux* OS
Now I try to make a simple CMakeLists.txt file:
cmake_minimum_required(VERSION 3.15.5)
project(mpiversion VERSION 1.0.0 LANGUAGES Fortran)
find_package(MPI REQUIRED)
message(STATUS "MPI_Fortran_COMPILER: ${MPI_Fortran_COMPILER}")
add_executable(mpiversion.exe mpiversion.F90)
target_link_libraries(mpiversion.exe PRIVATE MPI::MPI_Fortran)
This CMake file works just happily with Intel Fortran and Intel MPI. But when I try with gfortran and Intel MPI:
(1069) $ cmake ..
-- The Fortran compiler identification is GNU 8.3.0
-- Check for working Fortran compiler: /usr/local/other/gcc/8.3.0/bin/gfortran
-- Check for working Fortran compiler: /usr/local/other/gcc/8.3.0/bin/gfortran -- works
-- Detecting Fortran compiler ABI info
-- Detecting Fortran compiler ABI info - done
-- Checking whether /usr/local/other/gcc/8.3.0/bin/gfortran supports Fortran 90
-- Checking whether /usr/local/other/gcc/8.3.0/bin/gfortran supports Fortran 90 -- yes
-- Found MPI_Fortran: /gpfsm/dulocal/sles12/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/lib/libmpifort.so (found version "3.1")
-- Found MPI: TRUE (found version "3.1")
-- MPI_Fortran_COMPILER: /usr/local/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/bin/mpif90
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI
(1070) $ make
Scanning dependencies of target mpiversion.exe
[ 50%] Building Fortran object CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o
f951: Fatal Error: Reading module ‘mpi’ at line 1 column 2: Unexpected EOF
compilation terminated.
CMakeFiles/mpiversion.exe.dir/build.make:62: recipe for target 'CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o' failed
make[2]: *** [CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o] Error 1
CMakeFiles/Makefile2:75: recipe for target 'CMakeFiles/mpiversion.exe.dir/all' failed
make[1]: *** [CMakeFiles/mpiversion.exe.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
So, first it picked the wrong MPI_Fortran_COMPILER
wrapper, mpif90
instead of mpifc
, but if I do a verbose make:
[ 50%] Building Fortran object CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o
/usr/local/other/gcc/8.3.0/bin/gfortran -I/gpfsm/dulocal/sles12/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/include -I/gpfsm/dulocal/sles12/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/include/gfortran/8.2.0 -c /home/mathomp4/MPIVersionCMake/Fortran/mpiversion.F90 -o CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o
f951: Fatal Error: Reading module ‘mpi’ at line 1 column 2: Unexpected EOF
compilation terminated.
CMakeFiles/mpiversion.exe.dir/build.make:62: recipe for target 'CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o' failed
and compare to from mpifc -show
:
(1072) $ mpifc -show
gfortran -I/usr/local/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/include/gfortran/8.2.0 -I/usr/local/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/include -L/usr/local/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/lib/release -L/usr/local/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/lib -Xlinker --enable-new-dtags -Xlinker -rpath -Xlinker /usr/local/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/lib/release -Xlinker -rpath -Xlinker /usr/local/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/lib -lmpifort -lmpi -lrt -lpthread -Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Xlinker --enable-new-dtags -ldl
it does seem like Cmake knows gfortran-specific files can be found in the include/gfortran/8.2.0
directory…but it put it second so it’s actually picking up the Intel Fortran compiled modules.
I thought (reading the FindMPI help) that I could pass in the right wrapper with -DMPI_Fortran_COMPILER
, but it doesn’t seem to change anything:
(1101) $ cmake .. -DMPI_Fortran_COMPILER=mpifc
-- The Fortran compiler identification is GNU 8.3.0
-- Check for working Fortran compiler: /usr/local/other/gcc/8.3.0/bin/gfortran
-- Check for working Fortran compiler: /usr/local/other/gcc/8.3.0/bin/gfortran -- works
-- Detecting Fortran compiler ABI info
-- Detecting Fortran compiler ABI info - done
-- Checking whether /usr/local/other/gcc/8.3.0/bin/gfortran supports Fortran 90
-- Checking whether /usr/local/other/gcc/8.3.0/bin/gfortran supports Fortran 90 -- yes
-- Found MPI_Fortran: /gpfsm/dulocal/sles12/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/lib/libmpifort.so (found version "3.1")
-- Found MPI: TRUE (found version "3.1")
-- MPI_Fortran_COMPILER: /usr/local/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/bin/mpifc
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI
(1102) $ make
Scanning dependencies of target mpiversion.exe
[ 50%] Building Fortran object CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o
f951: Fatal Error: Reading module ‘mpi’ at line 1 column 2: Unexpected EOF
compilation terminated.
CMakeFiles/mpiversion.exe.dir/build.make:62: recipe for target 'CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o' failed
make[2]: *** [CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o] Error 1
CMakeFiles/Makefile2:75: recipe for target 'CMakeFiles/mpiversion.exe.dir/all' failed
make[1]: *** [CMakeFiles/mpiversion.exe.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
(1103) $ make VERBOSE=1
/gpfsm/dswdev/gmao_SIteam/other/SLES12.3/cmake/3.15.5/bin/cmake -S/home/mathomp4/MPIVersionCMake/Fortran -B/home/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI --check-build-system CMakeFiles/Makefile.cmake 0
/gpfsm/dswdev/gmao_SIteam/other/SLES12.3/cmake/3.15.5/bin/cmake -E cmake_progress_start /home/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI/CMakeFiles /home/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/gpfsm/dhome/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI'
make -f CMakeFiles/mpiversion.exe.dir/build.make CMakeFiles/mpiversion.exe.dir/depend
make[2]: Entering directory '/gpfsm/dhome/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI'
cd /home/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI && /gpfsm/dswdev/gmao_SIteam/other/SLES12.3/cmake/3.15.5/bin/cmake -E cmake_depends "Unix Makefiles" /home/mathomp4/MPIVersionCMake/Fortran /home/mathomp4/MPIVersionCMake/Fortran /home/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI /home/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI /home/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI/CMakeFiles/mpiversion.exe.dir/DependInfo.cmake --color=
make[2]: Leaving directory '/gpfsm/dhome/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI'
make -f CMakeFiles/mpiversion.exe.dir/build.make CMakeFiles/mpiversion.exe.dir/build
make[2]: Entering directory '/gpfsm/dhome/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI'
[ 50%] Building Fortran object CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o
/usr/local/other/gcc/8.3.0/bin/gfortran -I/gpfsm/dulocal/sles12/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/include -I/gpfsm/dulocal/sles12/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/include/gfortran/8.2.0 -c /home/mathomp4/MPIVersionCMake/Fortran/mpiversion.F90 -o CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o
f951: Fatal Error: Reading module ‘mpi’ at line 1 column 2: Unexpected EOF
compilation terminated.
CMakeFiles/mpiversion.exe.dir/build.make:62: recipe for target 'CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o' failed
make[2]: *** [CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o] Error 1
make[2]: Leaving directory '/gpfsm/dhome/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI'
CMakeFiles/Makefile2:75: recipe for target 'CMakeFiles/mpiversion.exe.dir/all' failed
make[1]: *** [CMakeFiles/mpiversion.exe.dir/all] Error 2
make[1]: Leaving directory '/gpfsm/dhome/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI'
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
The message()
seems to say it’s going to use mpifc
but it doesn’t seem to?
Now, I can sort of “force” a working compile by doing:
cmake .. -DMPI_Fortran_MODULE_DIR=/usr/local/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/include/gfortran/8.2.0
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mathomp4/MPIVersionCMake/Fortran/build-GNUIMPI
(1074) $ make
Scanning dependencies of target mpiversion.exe
[ 50%] Building Fortran object CMakeFiles/mpiversion.exe.dir/mpiversion.F90.o
[100%] Linking Fortran executable mpiversion.exe
[100%] Built target mpiversion.exe
(1075) $ ./mpiversion.exe
Intel(R) MPI Library 2019 Update 5 for Linux* OS
but as I often compile code with various versions of GNU (on this cluster I have 6.5.0, 7.4.0, 8.3.0, and 9.2.0), I’d really like to have CMake actually do this automatically.
So, is there an easy way to use CMake with Intel MPI+gfortran? Does anyone have a recipe/macro/hint? I’m not the best at CMake, but I’m trying to figure out how to make CMake code that checks if mpifc
is in MPI_Fortran_COMPILER
and if so it runs execute_process()
on mpifc
and tries to extract the second (space-delimited) field, strips the -I
and then tries to stuff that into MPI_Fortran_MODULE_DIR
but I’m not having much luck yet. It’s a bit fragile as it assumes that the second field of mpifc
will be the module include path, but I don’t see a good reason Intel would change that in the future as it works now. Of course, I’d really not like to even have to pass in MPI_Fortran_COMPILER
but I guess that’s not too bad. It’s the passing in MPI_Fortran_MODULE_DIR
that I’d like to avoid.
A couple of notes. First, I only have CMake 3.15.5 available on this cluster. I’ll try and ask the sysadmins to install 3.16.1 as maybe it’s fixed there, but the history on GitHub makes me think the only possible change will be an error message update (from Nov 20).
Second, CMake does seem to handle the Intel MPI + gcc case okay:
(1128) $ cat mpiversion.c
# include <stdlib.h>
# include <stdio.h>
# include "mpi.h"
int main(int argc, char *argv[])
{
char mpi_lib_ver[MPI_MAX_LIBRARY_VERSION_STRING];
int len;
MPI_Get_library_version(mpi_lib_ver, &len);
printf("%s\n",mpi_lib_ver);
}
(1129) $ cat CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(mpiversion VERSION 1.0.0 LANGUAGES C)
find_package(MPI REQUIRED)
message(STATUS "MPI_C_COMPILER: ${MPI_C_COMPILER}")
add_executable(mpiversion.exe mpiversion.c)
target_link_libraries(mpiversion.exe PRIVATE MPI::MPI_C)
...
(1132) $ cmake ..
-- The C compiler identification is GNU 8.3.0
-- Check for working C compiler: /usr/local/other/gcc/8.3.0/bin/gcc
-- Check for working C compiler: /usr/local/other/gcc/8.3.0/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Found MPI_C: /gpfsm/dulocal/sles12/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/lib/release/libmpi.so (found version "3.1")
-- Found MPI: TRUE (found version "3.1")
-- MPI_C_COMPILER: /usr/local/intel/2019/compilers_and_libraries_2019.5.281/linux/mpi/intel64/bin/mpigcc
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mathomp4/MPIVersionCMake/C/build
(1133) $ make
Scanning dependencies of target mpiversion.exe
[ 50%] Building C object CMakeFiles/mpiversion.exe.dir/mpiversion.c.o
[100%] Linking C executable mpiversion.exe
[100%] Built target mpiversion.exe
(1134) $ ./mpiversion.exe
Intel(R) MPI Library 2019 Update 5 for Linux* OS
it even correctly used mpigcc
. But as about 95% of my coding is in Fortran and using Fortran libraries, I’d like to get the gfortran working.