【问题标题】:CMake: Fortran modules and compilation orderCMake:Fortran 模块和编译顺序
【发布时间】:2019-06-17 15:46:33
【问题描述】:

我有一个包含许多目录的大型 Fortran 程序。每个目录都在一个伪库中单独编译,但仍然存在相互依赖的混乱,因此最后所有伪库都组合在一个可用的库中。我想使用 Fortran 模块,但它非常脆弱,因为我不能依赖自动依赖检查,并且根据顺序编译可能会失败。

例如,考虑以下CMakeLists.txt 文件:

project (test Fortran)
add_library (lib1 dir1/lib1.f90)
add_library (lib2 dir2/lib2.f90 dir2/mod.f90)
add_executable (exe dir3/exe.f90)
target_link_libraries (exe lib1 lib2)

来源:

dir1/lib1.f90:

subroutine bar
use foo, only: foofoo
implicit none
write(6,*) foofoo
end subroutine bar

dir2/lib2.f90:

subroutine bar2
use foo, only: foofoo
implicit none
write(6,*) foofoo,' again'
end subroutine bar2

dir2/mod.f90:

module foo
implicit none
integer :: foofoo=3
end module foo

dir3/exe.f90:

program meh
implicit none
call bar()
call bar2()
end program meh

从头开始编译失败:

$ make
[ 25%] Building Fortran object CMakeFiles/lib1.dir/dir1/lib1.f90.o
/home/user/cmake/dir1/lib1.f90:2.4:

use foo, only: foofoo
    1
Fatal Error: Can't open module file 'foo.mod' for reading at (1): No such file or directory
make[2]: *** [CMakeFiles/lib1.dir/dir1/lib1.f90.o] Error 1
make[1]: *** [CMakeFiles/lib1.dir/all] Error 2
make: *** [all] Error 2

但以正确的顺序进行操作:

$ make lib2
Scanning dependencies of target lib2
[ 50%] Building Fortran object CMakeFiles/lib2.dir/dir2/mod.f90.o
[100%] Building Fortran object CMakeFiles/lib2.dir/dir2/lib2.f90.o
Linking Fortran static library liblib2.a
[100%] Built target lib2
$ make
[ 25%] Building Fortran object CMakeFiles/lib1.dir/dir1/lib1.f90.o
Linking Fortran static library liblib1.a
[ 25%] Built target lib1
[ 75%] Built target lib2
Scanning dependencies of target exe
[100%] Building Fortran object CMakeFiles/exe.dir/dir3/exe.f90.o
Linking Fortran executable exe
[100%] Built target exe

CMake 有什么方法可以找出依赖关系并在lib1 之前编译lib2(或至少mod.f90)?

ETA:无论在CMakeLists.txt 文件中定义lib1lib2 的顺序如何,以及在编译程序后运行rm foo.mod ; touch ../dir1/lib1.f90 之后,一个健壮的解决方案都应该工作。

【问题讨论】:

  • 你的cmake版本是什么? cmake --version
  • 对于信息,“cmake 版本 3.13.4”正确地解决了依赖关系。
  • @PierredeBuyl 我试过 2.8.12.2 和 3.8.1。
  • 你们更新可行吗?如果您的系统包管理器上没有最新的包,从源代码安装非常轻松 :-) cmake.org/download
  • @PierredeBuyl 这应该是可行的,因为这就是我获得 3.8.1 的方式。与此同时,我在另一台我有 3.13.2 的机器上尝试过,得到了同样的错误。从 3.13.2 到 3.13.4 有什么相关的变化吗?你有没有先编译mod.f90?或者这是一种随机/系统相关的行为?

标签: cmake fortran


【解决方案1】:

upcoming ninja build system version (1.10.0) 支持动态依赖,可以正确解析模块的编译顺序。

要将它与 CMake 一起使用,您必须指定 Ninja 生成器:

cmake .. -DCMAKE_GENERATOR=Ninja # generate project
ninja # build the project

【讨论】:

    【解决方案2】:

    这里的问题是lib1 的目标是mod.f90 所需的目标文件。但是CMakeLists.txt 中没有提到在创建liblib1.a 时创建mod.f90.o 的规则。为lib2 创建目标mod.f90.o

    可能有以下两种可能的解决方案。

    解决方案 1

    mod.f90 添加到两个库中。

    project (test Fortran)
    add_library (lib1 dir1/lib1.f90 dir2/mod.f90)
    add_library (lib2 dir2/lib2.f90 dir2/mod.f90)
    add_executable (exe dir3/exe.f90)
    target_link_libraries (exe lib1 lib2)
    

    解决方案 2

    将带有mod.f90.o 的库链接到另一个库。

    project (test Fortran)
    add_library (lib1 dir1/lib1.f90)
    add_library (lib2 dir2/lib2.f90 dir2/mod.f90)
    add_dependencies(lib1 lib2)
    add_executable (exe dir3/exe.f90)
    target_link_libraries (exe lib1 lib2)
    

    【讨论】:

    • 没错,我需要一种方法让 CMake 检测到 lib1 需要 foo.mod,因此依赖于 mod.f90。我需要手动指定此依赖项(在文件级别或库级别)的任何解决方案都只会导致维护地狱。它适用于这个简单的示例,但对于具有许多可能相互关联的目录/库的大型项目而言,它不值得。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-23
    • 1970-01-01
    • 1970-01-01
    • 2013-05-03
    相关资源
    最近更新 更多