Tianyu Liu

The correct way of building MPI program using Cmake

Advertisements

Many posts on this topic appear outdated. Modern cmake stresses target-specific configuration, for each individual executable, library, etc. So a correct way of building MPI program with cmake (version 3.9.2 for instance) is:

find_package(MPI REQUIRED)
add_executable(my_mpi_bin src1.cpp src2.cpp)
target_include_directories(my_mpi_bin PRIVATE ${MPI_CXX_INCLUDE_PATH} hd1.h)
target_compile_options(my_mpi_bin PRIVATE ${MPI_CXX_COMPILE_FLAGS} my_compile_flags)
target_link_libraries(my_mpi_bin ${MPI_CXX_LIBRARIES} ${MPI_CXX_LINK_FLAGS} my_link_flags)

If the MPI implementation (MPICH-3.2 for instance) is installed at a certain location that cmake cannot find by itself, we may explicitly specify the path:

cmake \
-DMPI_CXX_COMPILER=/usr/local/mpich-install/bin/mpicxx \
-DMPI_C_COMPILER=/usr/local/mpich-install/bin/mpicc \
-DMPIEXEC=/usr/local/mpich-install/bin/mpiexec.hydra

Note that MPI_CXX_COMPILER and MPI_C_COMPILER are set here just for completeness, cmake actually does NOT need them to build the program. We do NOT need to change CMAKE_CXX_COMPILER and CMAKE_CXX_COMPILER via command line. After all, mpi compilers are simply wrappers aimed to provide correct compile/link flags that cmake has automatically derived. Moreover, we MUST NOT specify CMAKE_CXX_COMPILER and CMAKE_CXX_COMPILER inside the cmake script. This is unfortunately a very common anti-pattern.

If we want to add the mpi program to the test:

add_test(NAME my_mpi_test
         COMMAND ${MPIEXEC}
         ${MPIEXEC_NUMPROC_FLAG}
         ${MPIEXEC_MAX_NUMPROCS}
         ${MPIEXEC_PREFLAGS}
         ${CMAKE_CURRENT_BINARY_DIR}/my_mpi_bin
         ${MPIEXEC_POSTFLAGS}
         my_arg_1 my_arg_2 ...)

What phrase is considered toxic but may apply now? — GG EZ

Reference:
https://cmake.org/cmake/help/v3.9/module/FindMPI.html
http://www.urbandictionary.com/define.php?term=ggez

Advertisements