【问题标题】:Fortran module files not found by CMakeCMake 找不到 Fortran 模块文件
【发布时间】:2019-07-24 16:42:57
【问题描述】:

我在 Fortran 中有一个拆分项目,其中有一个子目录作为库:

# ./CMakeLists.txt
cmake_minimum_required (VERSION 2.8)
project (Simulation Fortran)
enable_language(Fortran)

add_subdirectory(lib)

add_executable(Simulation main.f90)
include_directories(lib)
add_dependencies(Simulation physicalConstants)
target_link_libraries(Simulation physicalConstants)

根目录只包含一个 Fortran 源代码文件:

! ./main.f90:

program simulation
use physicalConstants

implicit none

write(*,*) "Boltzmann constant:", k_b

end program simulation

我的子目录lib 包含另一个CMakeLists.txt 以及一个Fortran 模块源文件:

# ./lib/CMakeLists.txt:

cmake_minimum_required (VERSION 2.8)
enable_language(Fortran)

project(physicalConstants)
add_library( physicalConstants SHARED physicalConstants.f90)
! ./lib/physicalConstants.f90:

module physicalConstants
implicit none
save

real, parameter :: k_B = 1.38e-23

end module physicalConstants

我尝试使用 cmake 构建那些。 make在lib目录下生成physicalconstants.mod,但是在main.f90.o的构建过程中找不到这个文件:

Fatal Error: Can't open module file 'physicalconstants.mod' for reading at (1): No such file or directory

我在这里错过了什么?

【问题讨论】:

    标签: cmake fortran


    【解决方案1】:

    为了让目标A成功使用目标B中的模块,B存储模块文件的目录必须在A的包含目录中。

    变体 1

    实现此目的的一种方法是在目标 B 上设置属性 Fortran_MODULE_DIRECTORY,然后将该属性的内容添加到包含 A 的目录。

    您声称支持古老的 CMake 2.8.0,您需要在其中执行以下操作:

    add_executable(Simulation main.f90)
    include_directories(lib)
    # note that add_dependencies call is not necessary when you're actually linking
    target_link_libraries(Simulation physicalConstants)
    get_property(moduleDir TARGET physicalConstants PROPERTY Fortran_MODULE_DIRECTORY)
    include_directories(${moduleDir})
    

    在更现代的 CMake 中,您可以这样做:

    add_executable(Simulation main.f90)
    include_directories(lib)
    target_link_libraries(Simulation physicalConstants)
    target_include_directories(Simulation PUBLIC $<TARGET_PROPERTY:physicalConstants,Fortran_MODULE_DIRECTORY>)
    

    你甚至可以为它创建一个函数:

    function(LinkFortranLibraries Target)
      target_link_libraries(Target ${ARGN})
      foreach(Lib IN LISTS ARGN)
        target_include_directories(Simulation PUBLIC $<TARGET_PROPERTY:${Lib},Fortran_MODULE_DIRECTORY>)
      endforeach()
    endfunction()
    

    然后像这样使用它:

    add_executable(Simulation main.f90)
    include_directories(lib)
    LinkFortranLibraries(Simulation physicalConstants)
    

    变体 2

    如果不使用Fortran_MODULE_DIRECTORY 属性,模块文件将存储在与生成它们的目标的源目录对应的二进制目录中。这可以从目标的属性BINARY_DIR 中检索到,您可以完全按照变体 1 中的Fortran_MODULE_DIRECTORY 使用它。

    但是,CMake 2.8.0 不支持目标属性BINARY_DIR,因此您必须手动“重构”其值:

    add_executable(Simulation main.f90)
    include_directories(lib ${CMAKE_CURRENT_BINARY_DIR}/lib)
    target_link_libraries(Simulation physicalConstants)
    

    【讨论】:

    • “声称支持古老的 CMake 2.8.0”。嗯,它是一个 Centos7 :/.我已经尝试过您的第一个变体,但 Fortran_MODULE_DIRECTORY 为空/未设置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    • 1970-01-01
    • 2020-04-10
    • 1970-01-01
    相关资源
    最近更新 更多