CMake: set path to MPI headers and binaries manually
Asked Answered
I

5

7

I am developing an MPI application which requires to be run with a specific implementation of MPI (let's call it MPIvA). On my workstation, another implementation of MPI (let's call it MPIvB) is installed.

My application is built using CMake and the find_library(MPI) obviously points to MPIvB. It compiles and runs without hassle.

I compiled MPIvA on my workstation. How can I make CMake use these headers and binaries?

Input answered 18/3, 2016 at 18:16 Comment(0)
D
0

Well, this is not a new post but it may be useful to others in the future.

Even though the previous answers can also work, I think that the a better approach is to use the CMAKE_PREFIX_PATH option, ie sth like

CMAKE_PREFIX_PATH=~/my-libs-install-path ccmake ..

Now, some other comments:

  1. All MPI libraries should be interchangeable, ie code that uses the MPI specification should compile and run with any MPI implementation (eg MPIvA and MPIvB which I am assuming are intelmpi,openmpi or mpich).

  2. Regarding this answer (my reputation doesn't allow me to comment so I reply here):

find_package(MPI REQUIRED)
if (MPI_FOUND)
    include_directories(SYSTEM ${MPI_INCLUDE_PATH})
else (MPI_FOUND)
    message(SEND_ERROR "This application cannot compile without MPI")
endif (MPI_FOUND)

even though the functionality would be mostly as expected, the following is functionally equivalent:

find_package(MPI REQUIRED)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})

The REQUIRED part in the findpackage(MPI REQUIRED) command will cause the command to fail if MPI is not found, so the if(MPI_FOUND) part is useless and the else clause will actually never be executed.

  1. Finally, regarding the include_directories command, in my tests was not required if you are using targets, eg

    target_link_libraries(my_app PUBLIC MPI::C)

is enough.

Djokjakarta answered 24/1, 2020 at 11:23 Comment(1)
Good point about target usage. It is actually the currently recommended CMake pattern.Input
C
8

CMake comes with a FindMPI module, that does all the heavy lifting for you.

In your CMakeLists.txt, instead of calling find_library(MPI), use find_package like so:

#### MPI
find_package(MPI REQUIRED)
if (MPI_FOUND)
    include_directories(SYSTEM ${MPI_INCLUDE_PATH})
else (MPI_FOUND)
    message(SEND_ERROR "This application cannot compile without MPI")
endif (MPI_FOUND)

Then wherever you link your application, link against the ${MPI_LIBRARIES}:

target_link_libraries(example-app ${MPI_LIBRARIES})

Now cmake will automatically find a MPI implementation in your system. If you have multiple different MPI versions, and want to specify which one to compile with, you can set the MPI_C_COMPILER and MPI_CXX_COMPILER variables to the corresponding mpicc and mpicxx compiler wrappers. The CMake module will then use those to figure out all the required compiler and linker flags itself.

Example:

cmake -DMPI_C_COMPILER=/usr/share/mvapich/bin/mpicc your-project-dir

To make sure cmake is using the correct MPI, start in a new empty build directory.

More information on the FindMPI module here: https://cmake.org/cmake/help/v3.0/module/FindMPI.html

Cesya answered 18/3, 2016 at 20:48 Comment(5)
This is indeed a very convenient way to do it. CMake also requires the MPI_C_INCLUDE_PATH (path to the header directory) and MPI_C_LIBRARIES (path to the .so library file) (or their C++ counterparts) to be set to the appropriate values.Input
@Input not necessarily. The FindMPI module will figure those paths out directly from the compiler wrapper mpicc. If you click the link I posed above, it describes these two possibilities. 1) Via passing the path to the mpicc wrapper, or 2) manually via setting the library and link paths manually. Version 1 should usually work and is easier, since it will also deduct further required linker and compiler flags.Cesya
Indeed, I wasn't specific enough: I had to do this accordingly with point 2 because point 1 failed. The implementation of MPI I compiled is not installed in a system path, it is sitting somewhere in my home directory.Input
Ah ok, sorry for the misunderstanding. Cheers!Cesya
The non-LANG-specific variables of the FindMPI module are marked as deprecated, instead the MPI_<lang>_XXX should be used. In practice you can run into very hard to debug issues if you use the library for the wrong language.Ferdinana
C
1

In order to compile against MPIvA on your workstation, you'll need CMake to find those headers and binaries first. The following link describes how CMake's find_library's search order works: https://cmake.org/cmake/help/v3.0/command/find_library.html

I'd suggest adding MPIvA to the CMAKE_LIBRARY_PATH. See the top answer to the following question for an example: How do I instruct CMake to look for libraries installed by MacPorts?

Calebcaledonia answered 18/3, 2016 at 19:17 Comment(0)
O
0

the built in cmake will interfere with your desired library more often than not, especially if you are using different clusters as usually default compilers are not the latest version you might need, the work around this is to have your own FindMYMPI.cmake and take the control. Otherwise command line option or changing it with the ccmake GUI is also a possibility as provided in the above answers.

Odaodab answered 20/3, 2018 at 15:56 Comment(0)
K
0

In this specific case, I succeeded using the following environment variable:

export MPI_HOME=/your/path/to/prefix

Please set it before using cmake, or empty the build directory.

Kissinger answered 28/11, 2019 at 9:58 Comment(1)
This works for Windows. Adding the environment variable MPI_HOME pointing to the root directory of Windows MPI works.Sorrento
D
0

Well, this is not a new post but it may be useful to others in the future.

Even though the previous answers can also work, I think that the a better approach is to use the CMAKE_PREFIX_PATH option, ie sth like

CMAKE_PREFIX_PATH=~/my-libs-install-path ccmake ..

Now, some other comments:

  1. All MPI libraries should be interchangeable, ie code that uses the MPI specification should compile and run with any MPI implementation (eg MPIvA and MPIvB which I am assuming are intelmpi,openmpi or mpich).

  2. Regarding this answer (my reputation doesn't allow me to comment so I reply here):

find_package(MPI REQUIRED)
if (MPI_FOUND)
    include_directories(SYSTEM ${MPI_INCLUDE_PATH})
else (MPI_FOUND)
    message(SEND_ERROR "This application cannot compile without MPI")
endif (MPI_FOUND)

even though the functionality would be mostly as expected, the following is functionally equivalent:

find_package(MPI REQUIRED)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})

The REQUIRED part in the findpackage(MPI REQUIRED) command will cause the command to fail if MPI is not found, so the if(MPI_FOUND) part is useless and the else clause will actually never be executed.

  1. Finally, regarding the include_directories command, in my tests was not required if you are using targets, eg

    target_link_libraries(my_app PUBLIC MPI::C)

is enough.

Djokjakarta answered 24/1, 2020 at 11:23 Comment(1)
Good point about target usage. It is actually the currently recommended CMake pattern.Input

© 2022 - 2024 — McMap. All rights reserved.