【问题标题】:Writing CMake file for Fortran project with both gfortran and mpifort使用 gfortran 和 mpifort 为 Fortran 项目编写 CMake 文件
【发布时间】:2017-05-31 08:34:35
【问题描述】:

我有一个项目,其中一些 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.f90mpi_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 的项目结构。

【问题讨论】:

  • 为什么不能使用 MPI 包装器编译所有内容?这就是我在项目中所做的。
  • 这可能是可能的,但我认为这可能是不好的做法。例如,当调用 mpifort 而不是 gfortran 时,我不知道“幕后”到底发生了什么。
  • 没什么不好的。我不明白为什么不能通过 MPI 包装器编译所有内容。你甚至如何决定哪个是,哪个不是......?
  • @VladimirF,我想那些有 use mpi 声明的人
  • 没有理由这样划分。

标签: cmake fortran gfortran openmpi


【解决方案1】:

只需使用 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})

【讨论】:

  • 谢谢!你的解释很透彻,我会尽快尝试。希望我能用积极的消息回复你
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-15
  • 1970-01-01
  • 1970-01-01
  • 2014-08-26
  • 1970-01-01
  • 2021-06-24
相关资源
最近更新 更多