Reputation: 94
I am building ScaLAPACK (commit 7e4e07070a489686287c36ab473d21cf29a54bdd
) using CMake (version 3.20.1). The find_package
utility is used in CMakeLists.txt
to define the libraries, inclusion directories, and flags required to compile with MPI. The ScaLAPACK library is linked with MPI using the alias MPI::MPI_C
:
target_link_libraries( scalapack ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES} MPI::MPI_C)
I am building a shared library, so according to CMake default behavior, the resulting DSO should not have any entries in its RPATH
. However, the installed library DSO maintains in its RUNPATH
the entries:
$ readelf -d ~/opt/scalapack/lib/libscalapack.so | grep RUNPATH
0x000000000000001d (RUNPATH) Library runpath: [/opt/apps/resif/aion/2020b/epyc/software/UCX/1.9.0-GCCcore-10.2.0/lib64:/usr/lib64:/opt/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/lib]
If the library is linked with using the libraries variable MPI_C_LIBRARIES
defined by the find_package
utility,
target_link_libraries( scalapack ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES} ${MPI_C_LIBRARIES})
then there is no RUNPATH
entry in the installed DSO.
Looking further into the Makefiles generated by CMake, I noticed the following differences:
MPI::MPI_C
:# File: <build directory>/CMakeFiles/scalapack.dir/DependInfo.cmake
...
set(CMAKE_Fortran_TARGET_INCLUDE_PATH
"/mnt/irisgpfs/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/include"
"/opt/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/include"
)
...
# File: <build directory>/CMakeFiles/scalapack.dir/Dflags.make
...
C_INCLUDES = -isystem /opt/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/include
C_FLAGS = -O3 -DNDEBUG -fPIC -fexceptions
Fortran_DEFINES = -DAdd_ -Dscalapack_EXPORTS
Fortran_INCLUDES = -I/mnt/irisgpfs/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/include -I/opt/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/include
Fortran_FLAGS = -fallow-argument-mismatch -O2 -DNDEBUG -O2 -fPIC -fexceptions
...
# File: <build directory>/CMakeFiles/scalapack.dir/link.txt
/opt/apps/resif/aion/2020b/epyc/software/GCCcore/10.2.0/bin/gfortran -fPIC -fallow-argument-mismatch -O2 -DNDEBUG -O2 -Wl,-rpath -Wl,/opt/apps/resif/aion/2020b/epyc/software/UCX/1.9.0-GCCcore-10.2.0/lib64 -Wl,-rpath -Wl,/usr/lib64 -Wl,-rpath -Wl,/opt/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/lib -Wl,--enable-new-dtags -L/mnt/irisgpfs/apps/resif/aion/2020b/epyc/software/UCX/1.9.0-GCCcore-10.2.0/lib -L/usr/lib64 -L/mnt/irisgpfs/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/lib -shared -Wl,-soname,libscalapack.so.2.2 -o lib/libscalapack.so.2.2.1 @CMakeFiles/scalapack.dir/objects1.rsp -Wl,-rpath,/home/users/gkafanas/opt/openblas/lib64: /home/users/gkafanas/opt/openblas/lib64/libopenblas.so -lpthread -lm -ldl /home/users/gkafanas/opt/openblas/lib64/libopenblas.so -lpthread -lm -ldl /opt/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/lib/libmpi.so
MPI_C_LIBRARIES
:# File: <build directory>/CMakeFiles/scalapack.dir/DependInfo.cmake
...
set(CMAKE_Fortran_TARGET_INCLUDE_PATH
)
...
# File: <build directory>/CMakeFiles/scalapack.dir/Dflags.make
...
C_INCLUDES =
C_FLAGS = -O3 -DNDEBUG -fPIC
Fortran_DEFINES = -DAdd_ -Dscalapack_EXPORTS
Fortran_INCLUDES =
Fortran_FLAGS = -fallow-argument-mismatch -O2 -DNDEBUG -O2 -fPIC
...
# File: <build directory>/CMakeFiles/scalapack.dir/link.txt
/opt/apps/resif/aion/2020b/epyc/software/GCCcore/10.2.0/bin/gfortran -fPIC -fallow-argument-mismatch -O2 -DNDEBUG -O2 -shared -Wl,-soname,libscalapack.so.2.2 -o lib/libscalapack.so.2.2.1 @CMakeFiles/scalapack.dir/objects1.rsp -Wl,-rpath,/home/users/gkafanas/opt/openblas/lib64: /home/users/gkafanas/opt/openblas/lib64/libopenblas.so -lpthread -lm -ldl /home/users/gkafanas/opt/openblas/lib64/libopenblas.so /opt/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/lib/libmpi.so -lpthread -lm -ldl /opt/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/lib/libmpi.so
So it seems that the alias sets some system options that are not necessary.
I have 2 questions:
MPI::MPI_C
and how it should be used.Upvotes: 0
Views: 234
Reputation: 94
I had to revisit this issue recently. It seems that the find_package
utility populates some variables with useless values:
$ cmake -LAH -S . -B build
...
// MPI C linker flags
MPI_C_LINK_FLAGS:STRING=-Wl,-rpath -Wl,/opt/apps/resif/aion/2020b/epyc/software/UCX/1.9.0-GCCcore-10.2.0/lib64 -Wl,-rpath -Wl,/usr/lib64 -Wl,-rpath -Wl,/opt/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/lib -Wl,--enable-new-dtags -L/mnt/irisgpfs/apps/resif/aion/2020b/epyc/software/UCX/1.9.0-GCCcore-10.2.0/lib -L/usr/lib64 -L/mnt/irisgpfs/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/lib
...
// MPI Fortran linker flags
MPI_Fortran_LINK_FLAGS:STRING=-Wl,-rpath -Wl,/opt/apps/resif/aion/2020b/epyc/software/UCX/1.9.0-GCCcore-10.2.0/lib64 -Wl,-rpath -Wl,/usr/lib64 -Wl,-rpath -Wl,/opt/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/lib -Wl,--enable-new-dtags -L/mnt/irisgpfs/apps/resif/aion/2020b/epyc/software/UCX/1.9.0-GCCcore-10.2.0/lib -L/usr/lib64 -L/mnt/irisgpfs/apps/resif/aion/2020b/epyc/software/OpenMPI/4.0.5-GCC-10.2.0/lib
...
These are variables contain linking options that add the spurious paths in the RUNPATH
of the resulting library. The link options are added to the target libraries by linking with alias targets.
The targets MPI::MPI_C
and MPI::MPI_Fortran
are alias libraries, a type of alias target. Alias targets refer to an actual target, in this case the external libraries for MPI, and can also define additional properties, such as link options. It seems that in this case the link flags are added in the target link options for MPI::MPI_C
and MPI::MPI_Fortran
, so linking with these alias libraries we inadvertently introduce the spurious link options.
The solution suggested by @VictorEijkhout uses directly the variables defined by the find_package
to setup the target properties, and thus avoids unnecessary side effects.
Upvotes: 0
Reputation: 5810
I'll answer your question indirectly. Since CMake is so little standardized, I have no idea what MPI::MPI_C
is or whether it can be made to work. Here is what I use:
find_package( MPI )
add_executable( ${PROJECT_NAME} ${PROJECT_NAME}.c )
target_include_directories(
${PROJECT_NAME} PUBLIC
${MPI_C_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} )
target_link_libraries(
${PROJECT_NAME} PUBLIC
${MPI_C_LIBRARIES} )
This is for a single source file, but it can be adapted to your own uses.
Upvotes: 1