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_COMPILER
和 MPI_CXX_COMPILER
变量设置为相应的 mpicc
和 mpicxx
编译器包装器.然后 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 ..
现在,一些其他评论:
所有 MPI 库应该是可互换的,即使用 MPI 规范的代码应该编译并且 运行 任何 MPI 实现(例如我假设的 MPIvA 和 MPIvB 是 intelmpi、openmpi 或米奇)。
关于这个回答(我的名誉不允许我发表评论所以我在这里回复):
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 子句实际上永远不会执行。
最后,关于 include_directories 命令,如果您使用的是目标,在我的测试中不需要,例如
target_link_libraries(my_app PUBLIC MPI::C)
够了。
我正在开发一个 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_COMPILER
和 MPI_CXX_COMPILER
变量设置为相应的 mpicc
和 mpicxx
编译器包装器.然后 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 ..
现在,一些其他评论:
所有 MPI 库应该是可互换的,即使用 MPI 规范的代码应该编译并且 运行 任何 MPI 实现(例如我假设的 MPIvA 和 MPIvB 是 intelmpi、openmpi 或米奇)。
关于这个回答(我的名誉不允许我发表评论所以我在这里回复):
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 子句实际上永远不会执行。
最后,关于 include_directories 命令,如果您使用的是目标,在我的测试中不需要,例如
target_link_libraries(my_app PUBLIC MPI::C)
够了。