首页 > 解决方案 > Autotools 和 Fortran 模块

问题描述

我在编写 Makefile.am 时遇到问题,它将使 autotools 以正确的顺序编译文件。

我的最小示例是一些test.f90使用模块中的例程的示例mod.f90。我手动执行以下操作。

gfortran -c mod.f90
gfortran -c test.f90
gfortran -o test test.o mod.o

这工作正常。现在,我已经读到 autotools 不处理 Fortran 模块依赖项,根据这篇文章(automake with fortran: order of file),应该手动将依赖项放入 Makefile.am 中。

我的看起来像下面这样。

AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = test
test_SOURCES = mod.f90 test.f90 
test: test.f90 mod.o
mod.o: mod.f90

虽然每次运行时都会生成模块的 .mod 文件./configure && make,但它显然不是在所有其他文件之前生成的,即我仍然收到错误消息Fatal Error: Cannot open module file ‘mod.mod’ for reading at (1): No such file or directory

连续运行./configure && make两次可以编译程序,但这当然不是一个真正令人满意的解决方案。有没有一些标准的方法来处理这个?我可以以某种方式强制mod.o之前编译test.o吗?

标签: fortranautotools

解决方案


鉴于第一行,这两行中的第二行是多余的:

test_SOURCES = mod.f90 test.f90 
test: test.f90 mod.o

这个是不需要的,因为 Automake (和 GNU make)已经知道它传达的信息:

mod.o: mod.f90

这实际上让你只剩下这个:

AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = test
test_SOURCES = mod.f90 test.f90

就目前而言,这没问题,但它没有表达任何与mod.mod文件相关的依赖信息,因此构建可能会失败。要解决这个问题,您需要添加一个或多个规则来表达额外的依赖关系以及如何满足它们。

真正的依赖是test.o依赖于mod.mod,你可以编写一个仅依赖的规则来表达:

# INSUFFICIENT
test.o: mod.mod

但这给你留下了一个问题:make不知道这mod.mod是编译的输出mod.f90。实际上,通过一次配方运行创建多个目标的情况很难描述make(和 Automake)。Automake 手册用其中一个较长的部分来讨论这个问题。最强大的构建系统将使用该部分描述的方法来表达如何构建mod.omod.mod,但这将使您的大小增加三倍Makefile.am,并且您需要为每个 Fortran 模块提供类似的额外代码。

您可以通过告诉 Automake 这test.o取决于mod.o

# Better
test.o: mod.o

这将产生从头开始的成功构建,并且在大多数正常的开发环境下,但它确实表达了不正确的依赖关系。因此,它很容易通过例如构建项目,然后删除mod.mod(留mod.o在原地)和更新来构建破坏test.f90。在随后的构建中,make将看到它mod.o是最新的,因此它不会重新生成缺失的mod.mod. 一个干净的构建可以解决这个问题,作为开发人员,为了简单起见,我可能准备接受这种情况Makefile.am

说到干净的构建,您还应该添加mod.modmake clean应该删除的文件列表中:

CLEANFILES = mod.mod

总的来说,那么,最终的结果是:

AUTOMAKE_OPTIONS = foreign

bin_PROGRAMS = test

test_SOURCES = mod.f90 test.f90

# A fib -- the real dependency is test.o: mod.mod
test.o: mod.o

CLEANFILES = mod.mod

推荐阅读