【问题标题】:CMake Fortran Module Directory to be used with add_library与 add_library 一起使用的 CMake Fortran 模块目录
【发布时间】:2018-10-09 02:15:28
【问题描述】:

我有一个 CMake 3.5.2 项目,它创建了一个库:libtest.a,然后由可执行文件链接到该库。

源代码为Fortran,libtest.a生成模块文件:“main.mod”

可执行文件还需要包含此 main.mod 文件,因此为了使 main.mod 可访问,在构建项目时我将变量 CMAKE_Fortran_MODULE_DIRECTORY 设置为已知位置,并将其添加到相关的包含路径中。

这在构建整个项目时非常有用,main.mod 构建在已知位置,它可以用于任何代码需要它。然而,我的用法使得只需要自己构建 libtest.a,而有时将可执行文件留给下游用户构建。

我遇到的问题是,当我进入 libtest 源并将其视为自己的 CMake 项目时,该库将构建和安装,但 main.mod 文件始终留在 BINARY_DIR 中并且不是内置的CMAKE_Fortran_MODULE_DIRECTORY,尽管在 libtest 中的 CMakeList.txt 中设置。

仅在调用 add_executable() 时才使用 Fortran_MODULE_DIRECTORY 吗?并且仅仅因为库构建而被忽略?还是我错过了什么。

感谢您的帮助。

编辑:这将重现我的问题。

test_mod.f90:

module main
 implicit none
 real, parameter :: pi=3.2
end module main

tt.f90:

program test
  use main
  implicit none
  real :: a, area
  a =10
  area = a * 100
end program test

CMakeList.txt:

CMAKE_minimum_required( VERSION 3.5 )
enable_language( Fortran )
project( tt )
file( GLOB test_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.f90 )
add_library( tt STATIC ${test_SOURCES} )
set( CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Mod )
install( TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/Lib/ )

如果我构建并安装上述代码,我将在 Lib 目录中安装一个 libtt.a 库,但是我的 main.mod 将保留在我的构建目录中,而不是在 Mod 文件夹中构建。

【问题讨论】:

    标签: module cmake fortran


    【解决方案1】:

    这里我假设“用户”使用 cmake 来构建项目,同时可以访问项目的源代码。

    工作构建的步骤。

    1. libtest 有一个CMakeLists.txt 文件,它指定CMAKE_Fortran_MODULE_DIRECTORY。这应该足以让main.mod 出现在那里。
    2. 有一个CMakeLists.txt 文件用于构建“客户端”程序。此文件应包含带有 add_subdirectory 的 libtest 项目。
    3. 添加target_link_libraries(NAME_OF_PROGRAM NAME_OF_LIBRARY)。这仅负责库的链接,对于客户端程序知道模块是不够的(无论如何对于下面的解决方案 B)。

    现在,开始你自己的冒险吧:

    解决方案 A:在 libtest CMakeLists.txt 中,将模块放置在“所有模块将去”的位置,例如 set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/modules)(您也需要为“客户端”CMakeLists.txt 这样做)。变量${CMAKE_BINARY_DIR} 由“客户端”cmake 调用设置,并且对于所有包含的cmake 项目都是相同的。该目录将列在 Fortran 程序的构建命令中。

    方案B:在libtestCMakeLists.txt中,把这个库的模块放在一个专门的目录下。例如,您可以使用set(CMAKE_Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/modules) 实现此目的。然后您需要在客户端CMakeLists.txt 中使用include_directories(PATH_THAT_DEPENDS_ON_THE_NAME_OF_THE_SUBPROJECT) 手动指定此位置。

    如果您希望库可安装,您需要指定安装库的路径和模块文件。对于 Fortran,您应该考虑到目标操作系统、编译器和架构。

    CMake 文档的链接:

    添加示例代码后,应进行以下修改:

    CMAKE_minimum_required( VERSION 3.5 )
    enable_language( Fortran )
    project( tt )
    
    set( CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Mod )
    
    file( GLOB test_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.f90 )
    
    add_library( tt STATIC ${test_SOURCES} )
    
    install( TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/Lib/ )
    
    install(DIRECTORY ${CMAKE_Fortran_MODULE_DIRECTORY} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR})
    
    1. 确保set( CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Mod ) 出现在任何add_library 行之前。
    2. 添加install(DIRECTORY ${CMAKE_Fortran_MODULE_DIRECTORY} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}) 以实际安装.mod 文件。除了库文件之外,还必须安装模块文件(作为 C 中的头文件)。

    您创建的设置有点不寻常,因为您在源构建中找到所有内容,而“通常”安装位置是相对于 CMAKE_INSTALL_PREFIX

    【讨论】:

    • 感谢您的回复皮埃尔。我的设置类似于您的解决方案 B。我的问题是 CMAKE_Fortran_MODULE_DIRECTORY 在我自己构建库时实际上并没有将输出 main.mod 放在正确的位置。 **如果我在主可执行文件下将库构建为子目录/依赖项,那么一切正常。
    • 它起作用的情况可能是因为巧合,main.mod 是编译器看到的某个地方(例如${CMAKE_BINARY_DIR}),而不是因为事情设置正确。我会检查您发布的示例。
    • 这可能是可能的,但不太可能,因为在这种情况下“有效”意味着在我期望的目录中显示一个名为 main.mod 的文件。我没有构建错误或包含错误,当它工作时,我最终在我的 CMAKE_Fortran_MODULE_DIRECTORY 中有一个 main.mod 文件,当它不起作用时,我的 CMAKE_F_M_D 是空的并且 main.mod 仍然位于我的 CMAKE_BINARY_DIR 中。再次感谢您查看此内容。
    • 我确实测试了我在网上发布的配置文件。你测试了我的提议吗?
    • 哦,我没有看到添加内容。我已经对其进行了测试,唯一需要修改的是将 set(CMAKE_Fortran_MODULE_DIRECTORY) before add_library 命令。现在它按预期工作。非常感谢您的帮助!!
    猜你喜欢
    • 1970-01-01
    • 2013-09-08
    • 1970-01-01
    • 2019-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多