当我使用由所有可执行文件共享的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)文件放在特定于目标的目录中,这样它们就不会被其他目标覆盖或删除。这将解决我的问题,即使它仍然需要更多的编译而不是必要的。我不知道如何完成任何一个选项,因此欢迎使用任何提示或替代解决方案。
答案 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())。