使用 gfortran 和 mpifort 为 Fortran 项目编写 CMake 文件
Writing CMake file for Fortran project with both gfortran and mpifort
我有一个项目,其中一些 f90 文件需要使用常规 gfortran 编译器进行编译,一些需要使用 mpifort 包装器进行编译。我不知道如何正确编写 CMake 文件来适应这个问题。另外,我以前从未使用过 CMake,也不熟悉它,但我试图从文档和(基本上过时的)教程中理解。
我的项目目录如下所示:
├── CMakeLists.txt
├── README.md
├── bin
├── build
├── compile
├── src
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ │ ├── 3.8.1
│ │ │ ├── CMakeCCompiler.cmake
│ │ │ ├── CMakeCXXCompiler.cmake
│ │ │ ├── CMakeDetermineCompilerABI_C.bin
│ │ │ ├── CMakeDetermineCompilerABI_CXX.bin
│ │ │ ├── CMakeDetermineCompilerABI_Fortran.bin
│ │ │ ├── CMakeFortranCompiler.cmake
│ │ │ ├── CMakeSystem.cmake
│ │ │ ├── CompilerIdC
│ │ │ │ ├── CMakeCCompilerId.c
│ │ │ │ ├── a.out
│ │ │ │ └── tmp
│ │ │ ├── CompilerIdCXX
│ │ │ │ ├── CMakeCXXCompilerId.cpp
│ │ │ │ ├── a.out
│ │ │ │ └── tmp
│ │ │ └── CompilerIdFortran
│ │ │ ├── CMakeFortranCompilerId.F
│ │ │ ├── a.out
│ │ │ └── tmp
│ │ ├── CMakeDirectoryInformation.cmake
│ │ ├── CMakeOutput.log
│ │ ├── CMakeTmp
│ │ ├── Makefile.cmake
│ │ ├── Makefile2
│ │ ├── TargetDirectories.txt
│ │ ├── cmake.check_cache
│ │ ├── feature_tests.bin
│ │ ├── feature_tests.c
│ │ ├── feature_tests.cxx
│ │ ├── progress.marks
│ │ └── streetcanyon.dir
│ │ ├── DependInfo.cmake
│ │ ├── INC_BBB.f90.o
│ │ ├── INC_BBB.f90.o.provides.build
│ │ ├── INC_BC.f90.o
│ │ ├── INC_BC.f90.o.provides.build
│ │ ├── INC_BOUNDC.f90.o
│ │ ├── INC_BOUNDC.f90.o.provides.build
│ │ ├── INC_BUOY.f90.o
│ │ ├── INC_BUOY.f90.o.provides.build
│ │ ├── INC_COEF.f90.o
│ │ ├── INC_COEF.f90.o.provides.build
│ │ ├── INC_COEFB.f90.o
│ │ ├── INC_COEFB.f90.o.provides.build
│ │ ├── INC_GEO.f90.o
│ │ ├── INC_GEO.f90.o.provides.build
│ │ ├── INC_INDEX.f90.o
│ │ ├── INC_INDEX.f90.o.provides.build
│ │ ├── INC_OBSTACLE.f90.o
│ │ ├── INC_OBSTACLE.f90.o.provides.build
│ │ ├── INC_PAR.f90.o
│ │ ├── INC_PAR.f90.o.provides.build
│ │ ├── INC_PRINT.f90.o
│ │ ├── INC_PRINT.f90.o.provides.build
│ │ ├── INC_SOURCE.f90.o
│ │ ├── INC_SOURCE.f90.o.provides.build
│ │ ├── INC_STAT.f90.o
│ │ ├── INC_STAT.f90.o.provides.build
│ │ ├── INC_TIME.f90.o
│ │ ├── INC_TIME.f90.o.provides.build
│ │ ├── INC_TITLE.f90.o
│ │ ├── INC_TITLE.f90.o.provides.build
│ │ ├── INC_TREES.f90.o
│ │ ├── INC_TREES.f90.o.provides.build
│ │ ├── INC_UVW.f90.o
│ │ ├── INC_UVW.f90.o.provides.build
│ │ ├── INC_VEC.f90.o
│ │ ├── INC_VEC.f90.o.provides.build
│ │ ├── INC_WALL.f90.o
│ │ ├── INC_WALL.f90.o.provides.build
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── cmake_clean_Fortran.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── fortran.internal
│ │ ├── inc_bbb.mod.stamp
│ │ ├── inc_bc.mod.stamp
│ │ ├── inc_boundc.mod.stamp
│ │ ├── inc_buoy.mod.stamp
│ │ ├── inc_coef.mod.stamp
│ │ ├── inc_coefb.mod.stamp
│ │ ├── inc_geo.mod.stamp
│ │ ├── inc_index.mod.stamp
│ │ ├── inc_obstacle.mod.stamp
│ │ ├── inc_par.mod.stamp
│ │ ├── inc_print.mod.stamp
│ │ ├── inc_source.mod.stamp
│ │ ├── inc_stat.mod.stamp
│ │ ├── inc_time.mod.stamp
│ │ ├── inc_title.mod.stamp
│ │ ├── inc_trees.mod.stamp
│ │ ├── inc_uvw.mod.stamp
│ │ ├── inc_vec.mod.stamp
│ │ ├── inc_wall.mod.stamp
│ │ ├── link.txt
│ │ └── progress.make
│ ├── INC_BBB.f90
│ ├── INC_BC.f90
│ ├── INC_BOUNDC.f90
│ ├── INC_BUOY.f90
│ ├── INC_COEF.f90
│ ├── INC_COEFB.f90
│ ├── INC_GEO.f90
│ ├── INC_INDEX.f90
│ ├── INC_OBSTACLE.f90
│ ├── INC_PAR.f90
│ ├── INC_PAR.f90_8ob
│ ├── INC_PRINT.f90
│ ├── INC_SOURCE.f90
│ ├── INC_STAT.f90
│ ├── INC_TIME.f90
│ ├── INC_TITLE.f90
│ ├── INC_TREES.f90
│ ├── INC_UVW.f90
│ ├── INC_VEC.f90
│ ├── INC_WALL.f90
│ ├── Makefile
│ ├── cmake_install.cmake
│ ├── grid_binary
│ ├── grid_binary(8\ obsttacles)
│ ├── inc_bbb.mod
│ ├── inc_bc.mod
│ ├── inc_boundc.mod
│ ├── inc_buoy.mod
│ ├── inc_coef.mod
│ ├── inc_coefb.mod
│ ├── inc_geo.mod
│ ├── inc_index.mod
│ ├── inc_obstacle.mod
│ ├── inc_par.mod
│ ├── inc_print.mod
│ ├── inc_source.mod
│ ├── inc_stat.mod
│ ├── inc_time.mod
│ ├── inc_title.mod
│ ├── inc_trees.mod
│ ├── inc_uvw.mod
│ ├── inc_vec.mod
│ ├── inc_wall.mod
│ ├── mpi_par.f90
│ ├── source
│ ├── streetcanyon.f90
│ └── streetcanyon.f90~
在./src/
目录中streetcanyon.f90
和mpi_par.f90
需要使用mpifort
编译,其余的可以通过gfortran
完成。 streetcanyon.f90
需要编译成最终的可执行文件。我尝试使用项目根目录中包含的以下 CMakeList.txt
:
#./CMakeList.txt
cmake_minimum_required (VERSION 3.8.0)
project(mpi)
enable_language (Fortran)
file(GLOB SOURCES src/*.f90)
add_executable(streetcanyon ${SOURCES})
我也不知道我是否遵循了适合 Fortran 的项目结构。
只需使用 CMake 的 FindMPI 模块。它将从 mpifort
中提取编译标志和库,并将它们作为常规 CMake 变量提供。您所要做的就是将这些标志应用到您的库中。唯一困难的部分是必须应用几个不同的东西。这是您如何使用它的示例:
cmake_minimum_required (VERSION 3.8.0)
project(mpi)
enable_language (Fortran)
find_package(MPI)
if(NOT MPI_Fortran_FOUND)
message(FATAL_ERROR "Could not find Fortran MPI. Please set MPI_Fortran_COMPILER to point to the mpifort wrapper.")
endif()
include_directories(${MPI_Fortran_INCLUDE_PATH})
add_compile_options(${MPI_Fortran_COMPILE_FLAGS})
file(GLOB SOURCES src/*.f90)
add_executable(streetcanyon ${SOURCES})
target_link_libraries(streetcanyon ${MPI_Fortran_LIBRARIES})
set_property(TARGET streetcanyon APPEND_STRING PROPERTY LINK_FLAGS "${MPI_Fortran_LINK_FLAGS}")
这将按照 mpifort 编译它们的方式编译所有 streetcanyon 源代码,这在 99% 的用例中应该没问题。如果你真的只想编译一些像 mpifort 那样的文件,就像你说的那样,那么而不是
add_compile_options(${MPI_Fortran_COMPILE_FLAGS})
您可以将 MPI 编译选项仅传递给特定的源文件,需要一些小改动:
set(MPI_SOURCES foo.f90 bar.f90...)
set(NO_MPI_SOURCES baz.f90...)
# convert CMake list to string for PROPERTY COMPILE_FLAGS
set(MPI_Fortran_COMPILE_FLAGS_STR "")
foreach(ELEMENT ${MPI_Fortran_COMPILE_FLAGS})
set(MPI_Fortran_COMPILE_FLAGS_STR "${MPI_Fortran_COMPILE_FLAGS_STR } ${ELEMENT}")
endforeach()
set_property(SOURCE ${MPI_SOURCES} PROPERTY COMPILE_FLAGS ${MPI_Fortran_COMPILE_FLAGS_STR})
...later...
add_executable(streetcanyon ${MPI_SOURCES} ${NO_MPI_SOURCES})
我有一个项目,其中一些 f90 文件需要使用常规 gfortran 编译器进行编译,一些需要使用 mpifort 包装器进行编译。我不知道如何正确编写 CMake 文件来适应这个问题。另外,我以前从未使用过 CMake,也不熟悉它,但我试图从文档和(基本上过时的)教程中理解。
我的项目目录如下所示:
├── CMakeLists.txt
├── README.md
├── bin
├── build
├── compile
├── src
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ │ ├── 3.8.1
│ │ │ ├── CMakeCCompiler.cmake
│ │ │ ├── CMakeCXXCompiler.cmake
│ │ │ ├── CMakeDetermineCompilerABI_C.bin
│ │ │ ├── CMakeDetermineCompilerABI_CXX.bin
│ │ │ ├── CMakeDetermineCompilerABI_Fortran.bin
│ │ │ ├── CMakeFortranCompiler.cmake
│ │ │ ├── CMakeSystem.cmake
│ │ │ ├── CompilerIdC
│ │ │ │ ├── CMakeCCompilerId.c
│ │ │ │ ├── a.out
│ │ │ │ └── tmp
│ │ │ ├── CompilerIdCXX
│ │ │ │ ├── CMakeCXXCompilerId.cpp
│ │ │ │ ├── a.out
│ │ │ │ └── tmp
│ │ │ └── CompilerIdFortran
│ │ │ ├── CMakeFortranCompilerId.F
│ │ │ ├── a.out
│ │ │ └── tmp
│ │ ├── CMakeDirectoryInformation.cmake
│ │ ├── CMakeOutput.log
│ │ ├── CMakeTmp
│ │ ├── Makefile.cmake
│ │ ├── Makefile2
│ │ ├── TargetDirectories.txt
│ │ ├── cmake.check_cache
│ │ ├── feature_tests.bin
│ │ ├── feature_tests.c
│ │ ├── feature_tests.cxx
│ │ ├── progress.marks
│ │ └── streetcanyon.dir
│ │ ├── DependInfo.cmake
│ │ ├── INC_BBB.f90.o
│ │ ├── INC_BBB.f90.o.provides.build
│ │ ├── INC_BC.f90.o
│ │ ├── INC_BC.f90.o.provides.build
│ │ ├── INC_BOUNDC.f90.o
│ │ ├── INC_BOUNDC.f90.o.provides.build
│ │ ├── INC_BUOY.f90.o
│ │ ├── INC_BUOY.f90.o.provides.build
│ │ ├── INC_COEF.f90.o
│ │ ├── INC_COEF.f90.o.provides.build
│ │ ├── INC_COEFB.f90.o
│ │ ├── INC_COEFB.f90.o.provides.build
│ │ ├── INC_GEO.f90.o
│ │ ├── INC_GEO.f90.o.provides.build
│ │ ├── INC_INDEX.f90.o
│ │ ├── INC_INDEX.f90.o.provides.build
│ │ ├── INC_OBSTACLE.f90.o
│ │ ├── INC_OBSTACLE.f90.o.provides.build
│ │ ├── INC_PAR.f90.o
│ │ ├── INC_PAR.f90.o.provides.build
│ │ ├── INC_PRINT.f90.o
│ │ ├── INC_PRINT.f90.o.provides.build
│ │ ├── INC_SOURCE.f90.o
│ │ ├── INC_SOURCE.f90.o.provides.build
│ │ ├── INC_STAT.f90.o
│ │ ├── INC_STAT.f90.o.provides.build
│ │ ├── INC_TIME.f90.o
│ │ ├── INC_TIME.f90.o.provides.build
│ │ ├── INC_TITLE.f90.o
│ │ ├── INC_TITLE.f90.o.provides.build
│ │ ├── INC_TREES.f90.o
│ │ ├── INC_TREES.f90.o.provides.build
│ │ ├── INC_UVW.f90.o
│ │ ├── INC_UVW.f90.o.provides.build
│ │ ├── INC_VEC.f90.o
│ │ ├── INC_VEC.f90.o.provides.build
│ │ ├── INC_WALL.f90.o
│ │ ├── INC_WALL.f90.o.provides.build
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── cmake_clean_Fortran.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── fortran.internal
│ │ ├── inc_bbb.mod.stamp
│ │ ├── inc_bc.mod.stamp
│ │ ├── inc_boundc.mod.stamp
│ │ ├── inc_buoy.mod.stamp
│ │ ├── inc_coef.mod.stamp
│ │ ├── inc_coefb.mod.stamp
│ │ ├── inc_geo.mod.stamp
│ │ ├── inc_index.mod.stamp
│ │ ├── inc_obstacle.mod.stamp
│ │ ├── inc_par.mod.stamp
│ │ ├── inc_print.mod.stamp
│ │ ├── inc_source.mod.stamp
│ │ ├── inc_stat.mod.stamp
│ │ ├── inc_time.mod.stamp
│ │ ├── inc_title.mod.stamp
│ │ ├── inc_trees.mod.stamp
│ │ ├── inc_uvw.mod.stamp
│ │ ├── inc_vec.mod.stamp
│ │ ├── inc_wall.mod.stamp
│ │ ├── link.txt
│ │ └── progress.make
│ ├── INC_BBB.f90
│ ├── INC_BC.f90
│ ├── INC_BOUNDC.f90
│ ├── INC_BUOY.f90
│ ├── INC_COEF.f90
│ ├── INC_COEFB.f90
│ ├── INC_GEO.f90
│ ├── INC_INDEX.f90
│ ├── INC_OBSTACLE.f90
│ ├── INC_PAR.f90
│ ├── INC_PAR.f90_8ob
│ ├── INC_PRINT.f90
│ ├── INC_SOURCE.f90
│ ├── INC_STAT.f90
│ ├── INC_TIME.f90
│ ├── INC_TITLE.f90
│ ├── INC_TREES.f90
│ ├── INC_UVW.f90
│ ├── INC_VEC.f90
│ ├── INC_WALL.f90
│ ├── Makefile
│ ├── cmake_install.cmake
│ ├── grid_binary
│ ├── grid_binary(8\ obsttacles)
│ ├── inc_bbb.mod
│ ├── inc_bc.mod
│ ├── inc_boundc.mod
│ ├── inc_buoy.mod
│ ├── inc_coef.mod
│ ├── inc_coefb.mod
│ ├── inc_geo.mod
│ ├── inc_index.mod
│ ├── inc_obstacle.mod
│ ├── inc_par.mod
│ ├── inc_print.mod
│ ├── inc_source.mod
│ ├── inc_stat.mod
│ ├── inc_time.mod
│ ├── inc_title.mod
│ ├── inc_trees.mod
│ ├── inc_uvw.mod
│ ├── inc_vec.mod
│ ├── inc_wall.mod
│ ├── mpi_par.f90
│ ├── source
│ ├── streetcanyon.f90
│ └── streetcanyon.f90~
在./src/
目录中streetcanyon.f90
和mpi_par.f90
需要使用mpifort
编译,其余的可以通过gfortran
完成。 streetcanyon.f90
需要编译成最终的可执行文件。我尝试使用项目根目录中包含的以下 CMakeList.txt
:
#./CMakeList.txt
cmake_minimum_required (VERSION 3.8.0)
project(mpi)
enable_language (Fortran)
file(GLOB SOURCES src/*.f90)
add_executable(streetcanyon ${SOURCES})
我也不知道我是否遵循了适合 Fortran 的项目结构。
只需使用 CMake 的 FindMPI 模块。它将从 mpifort
中提取编译标志和库,并将它们作为常规 CMake 变量提供。您所要做的就是将这些标志应用到您的库中。唯一困难的部分是必须应用几个不同的东西。这是您如何使用它的示例:
cmake_minimum_required (VERSION 3.8.0)
project(mpi)
enable_language (Fortran)
find_package(MPI)
if(NOT MPI_Fortran_FOUND)
message(FATAL_ERROR "Could not find Fortran MPI. Please set MPI_Fortran_COMPILER to point to the mpifort wrapper.")
endif()
include_directories(${MPI_Fortran_INCLUDE_PATH})
add_compile_options(${MPI_Fortran_COMPILE_FLAGS})
file(GLOB SOURCES src/*.f90)
add_executable(streetcanyon ${SOURCES})
target_link_libraries(streetcanyon ${MPI_Fortran_LIBRARIES})
set_property(TARGET streetcanyon APPEND_STRING PROPERTY LINK_FLAGS "${MPI_Fortran_LINK_FLAGS}")
这将按照 mpifort 编译它们的方式编译所有 streetcanyon 源代码,这在 99% 的用例中应该没问题。如果你真的只想编译一些像 mpifort 那样的文件,就像你说的那样,那么而不是
add_compile_options(${MPI_Fortran_COMPILE_FLAGS})
您可以将 MPI 编译选项仅传递给特定的源文件,需要一些小改动:
set(MPI_SOURCES foo.f90 bar.f90...)
set(NO_MPI_SOURCES baz.f90...)
# convert CMake list to string for PROPERTY COMPILE_FLAGS
set(MPI_Fortran_COMPILE_FLAGS_STR "")
foreach(ELEMENT ${MPI_Fortran_COMPILE_FLAGS})
set(MPI_Fortran_COMPILE_FLAGS_STR "${MPI_Fortran_COMPILE_FLAGS_STR } ${ELEMENT}")
endforeach()
set_property(SOURCE ${MPI_SOURCES} PROPERTY COMPILE_FLAGS ${MPI_Fortran_COMPILE_FLAGS_STR})
...later...
add_executable(streetcanyon ${MPI_SOURCES} ${NO_MPI_SOURCES})