使用模块对Fortran-90 +进行CMake并行构建

时间:2015-04-19 10:54:04

标签: cmake makefile fortran parallel-builds

当我使用由所有可执行文件共享的Fortran模块并使用make -j并行构建时,使用CMake构建多个Fortran-90 +可执行目标时遇到问题。问题似乎是编译的目标文件放在每个目标CMakeFiles/targetName.dir/src/file.f90.o的不同子目录中,而模块文件放在每个目标的同一目录中(我可以通过设置{{1}来更改此目录,但它仍然是所有模块文件的相同目录)。问题是所有目标都开始并行编写这些模块文件,我得到了一个 Fortran_MODULE_DIRECTORY 当使用gfortran(显然创建.mod0文件,然后将其重命名为.mod)时。当我在没有-j选项(串行构建)的情况下发出make时,不会出现这个问题。

我可以看到两个解决方案,但我不知道如何实现它们。首先,将所有目标的目标文件放在同一目录而不是目标特定目录中。这可能是首选选项,因为我不必为N个目标编译共享源文件N次。 make进程将识别目标文件存在,而不是再次编译相应的源文件,因此不再触及.mod(0)文件(我可能需要使所有后续目标依赖于第一个)。

第二种解决方案是将.mod(0)文件放在特定于目标的目录中,这样它们就不会被其他目标覆盖或删除。这将解决我的问题,即使它仍然需要更多的编译而不是必要的。我不知道如何完成任何一个选项,因此欢迎使用任何提示或替代解决方案。

1 个答案:

答案 0 :(得分:1)

我正在寻找的答案在@RaulLaasner对问题的评论中提供:

  

我会以相关源文件的核心库的形式创建一个额外的目标,然后可以链接到所有可执行文件。这应该并行工作。 mod文件仍然可以放在一个目录中。

我使用add_library()target_link_libraries()来实现这一目标。

请注意,例如Gentoo ebuild脚本将--as-needed添加到链接器,当您链接它和外部库以形成可执行文件时,可能会在您的核心库中导致undefined references。为防止这种情况,请确保首先将外部库链接到核心库。为此,我的CMakeListst.txt包含:

add_library( "Core" STATIC src/functions.f90 src/routines.f90 )  # creates libCore.a
target_link_libraries( Core ${EXTERNAL_LIBRARIES} )              # link external libraries to libCore.a
...
add_executable( myProgram1 src/myProgram1.f90 )                  # creates the first executable
target_link_libraries( myProgram1 Core )                         # links libCore.a to myProgram1 

可以重复最后两行来构建其他可执行文件(例如,使用foreach())。