CMake:手动设置 MPI headers 和二进制文件的路径

CMake: set path to MPI headers and binaries manually

我正在开发一个 MPI 应用程序,它需要 运行 具有特定的 MPI 实现(我们称之为 MPIvA)。在我的工作站上,安装了另一个 MPI 实现(我们称之为 MPIvB)。

我的应用程序是使用 CMake 构建的,find_library(MPI) 显然指向 MPIvB。它可以毫不费力地编译和 运行s。

我在我的工作站上编译了 MPIvA。如何让 CMake 使用这些 headers 和二进制文件?

为了在您的工作站上针对 MPIvA 进行编译,您需要先使用 CMake 找到那些 headers 和二进制文件。以下 link 描述了 CMake 的 find_library 搜索顺序的工作原理:https://cmake.org/cmake/help/v3.0/command/find_library.html

我建议将 MPIvA 添加到 CMAKE_LIBRARY_PATH。有关示例,请参见以下问题的最佳答案: How do I instruct CMake to look for libraries installed by MacPorts?

CMake 带有一个 FindMPI 模块,它可以为您完成所有繁重的工作。

在您的 CMakeLists.txt 中,不要调用 find_library(MPI),而是像这样使用 find_package

#### 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)

然后无论你link你的申请,link反对${MPI_LIBRARIES}:

target_link_libraries(example-app ${MPI_LIBRARIES})

现在 cmake 会自动在您的系统中找到 a MPI 实现。如果你有多个不同的 MPI 版本,并且想指定用哪个版本编译,你可以将 MPI_C_COMPILERMPI_CXX_COMPILER 变量设置为相应的 mpiccmpicxx 编译器包装器.然后 CMake 模块将使用这些来找出所有必需的编译器和 linker 标志本身。

示例:

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

为确保 cmake 使用正确的 MPI,请从一个新的空构建目录开始。

在此处了解有关 FindMPI 模块的更多信息:https://cmake.org/cmake/help/v3.0/module/FindMPI.html

内置的 cmake 通常会干扰您想要的库,特别是如果您使用不同的集群,因为通常默认编译器不是您可能需要的最新版本,解决这个问题的方法是拥有自己的 FindMYMPI.cmake 并取得控制权。 否则命令行选项或使用 ccmake GUI 更改它也是一种可能性,如上述答案中提供的那样。

在这个具体案例中,我成功地使用了以下环境变量:

export MPI_HOME=/your/path/to/prefix

请在之前使用cmake设置它,或者清空构建目录。

好吧,这不是新的 post 但它可能对将来的其他人有用。

尽管前面的答案也可以,但我认为更好的方法是使用 CMAKE_PREFIX_PATH 选项,即

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

现在,一些其他评论:

  1. 所有 MPI 库应该是可互换的,即使用 MPI 规范的代码应该编译并且 运行 任何 MPI 实现(例如我假设的 MPIvA 和 MPIvB 是 intelmpi、openmpi 或米奇)。

  2. 关于这个回答(我的名誉不允许我发表评论所以我在这里回复):

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)

尽管功能大部分都符合预期,但以下功能在功能上是等效的:

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

findpackage(MPI REQUIRED)命令中的REQUIRED部分如果找不到MPI会导致命令失败,所以if(MPI_FOUND) 部分没用,else 子句实际上永远不会执行。

  1. 最后,关于 include_directories 命令,如果您使用的是目标,在我的测试中不需要,例如

    target_link_libraries(my_app PUBLIC MPI::C)

够了。