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?

5 Answers 5

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

Sign up to request clarification or add additional context in comments.

5 Comments

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.
@M4urice 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.
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.
Ah ok, sorry for the misunderstanding. Cheers!
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.
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?

Comments

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.

1 Comment

Good point about target usage. It is actually the currently recommended CMake pattern.
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.

Comments

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.

1 Comment

This works for Windows. Adding the environment variable MPI_HOME pointing to the root directory of Windows MPI works.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.