Fortran:包含已编译模块的 makefile

Fortran: makefile with already compiled modules

我有这样的项目结构

-Project

 --Common

  ---types.f90

  ---global.f90

  ---common_routines.f90

 --Program 1

  ---program1.f90

  ---module1.f90

  ---module2.f90

  ---etc...

 --Program 2

 --etc...

其中,Common 是包含一些在所有程序之间共享的模块的文件夹。我如何在我的 makefile 中包含这些模块?

我试过这个:

FC = gfortran
FCFLAGS = -fbounds-check -O3
FCFLAGS += -I ../Common

all: program1

program1: module1.o module2.o module3.o

program1.o: module1.o module2.o module3.o

module2.o: module1.o

module3.o: module2.o module1.o

%: %.o
    $(FC) $(FCFLAGS) -o $@ $^ 

%.o: %.f90
    $(FC) $(FCFLAGS) -c $<

clean:
    rm -rf *.o *.mod

但是我收到一个未定义的通用模块变量引用错误。

GNU syntax to define additional include directory-Idir 而不是 -I dir(额外的 space)

还要确保公共模块已经 compiled 并且包括搜索路径指向您编译模块的目录,而不是源文件:

This path is also used to search for .mod files when previously compiled modules are required by a USE statement.

I tried FCFLAGS += -I../Common types.o global.o common_routines.o

这将不起作用,因为 -I 是 GNU Fortran 预处理器的一个选项 指定预处理器搜索要包含的文件的路径 编译 之前。您不能使用它来指定 object 文件 (*.o) 的路径 会在编译后被linker搜索。没有任何意义 linker 并没有传递给 linker。

为简单起见,我们假设您需要 link 的目标文件 program1 只是 program1/program1.o 加上预先存在的 common/types.ocommon/global.ocommon/common_routines.o

然后下面的 Makefile,放在目录 program1 中,将构建它:

OBJS = program1.o ../common/types.o ../common/global.o ../common/common_routines.o

.phony: all

all: program1

program1: program1.o
    $(FC) -o $@ $(FCFLAGS) $(OBJS) 

clean:
    rm -f *.o program1

只需将所有需要的目标文件列出给 linker,在本例中是通过 $(OBJS)

您可能希望采取预防措施确保公共模块 在您构建 program1 之前是最新的,您现在可能认为您可以做到这一点 只需更换:

program1: program1.o

与:

program1: $(OBJS)

因此提示 make 重新编译 任何 四个目标文件 相对于相应源文件的日期,作为先决条件 建筑物 program1

make 肯定会努力做到这一点,但要小心。那样的话,就会 从 ../common/types.f90 重新编译,比如说 ../common/types.o.f90 生成 .o 的隐式默认配方,因为此 makefile 是 没有告诉它做任何不同的事情。但这可能不是 ../common/types.f90是用来编译的,如果你在common中也有一个makefile 规定了如何以某种非默认方式执行此操作。

在那种情况下,应该始终按照 common 中的生成文件。最好保留 program1 的先决条件,但将配方更改为:

program1: program1.o
    $(MAKE) -C ../common
    $(FC) -o $@ $(FCFLAGS) $(OBJS)

现在,任何时候 program1 需要重建,配方将抢先 运行 make../common 在它之前 link 是四个目标文件。 (这个 $(MAKE) -C ../common 有点不雅 即使它无事可做也会被调用:这可以通过更高级的 make 用法来避免)。

最后你可能还会发现需要(如果不是在这种情况下,那么在另一种情况下)来区分 传递给 预处理的标志之间 and/or 传递给 编译的标志 and/or 传递给 [=84 的标志=]年龄。 按照惯例,这些被分配给不同的 make 变量,例如FPPFLAGS(预处理器), FCFLAGS(编译器),LDFLAGS(linker)。