为带有模块的Fortran项目寻找最佳的多线程生成文件



我的所有代码都在模块中,每个源文件都有一个模块(除了文件中 tests.f90 中模块之后的最小程序)。源文件和模块的名称相等,给出等效的名称,例如:src/computes.f90build/computes.obuild/computes.mod。有use语句将模块相互链接。以下是我为这个项目提供一个好的makefile的最佳尝试,但是有一个主要问题,即文件被无限期地重新考虑。

想法:只能用-fsyntax-only快速编译.mod文件。当所有 .mod 文件都存在时,.o 文件没有内部依赖关系,可以按任何顺序编译,从而简化了多线程编译。

编译源时,使用 our withoutgfortran -fsyntax-only,模块文件仅在更改时更新,无论相应的目标文件是否更新。因此,可以拥有比对应于同一 .f90 文件的.o文件更早的.mod文件。

如果 file.f90 被更新,相应的 file.o 应该更新,也许是 file.mod。如果 file.mod 已更新,则依赖于 file.mod 的 file2.mod 应与gfortran -fsyntax-only file2.f90进行检查。只有当 file2.mod 被更新时,才应该编译 file2.o(这是一个耗时的步骤,否则应该避免。(这甚至正确吗?

实现和问题:我在下面的制作文件中实现了这些原则。但是问题出现在(预期)情况下,当 file.mod 更新但不更新 file2.mod。然后 make 每次都会继续运行gfortran -fsyntax-only file2.f90,因为先决条件比没有(和没有)更新的目标早。

我能做什么?我可以仅在替换 file.mod 时触发依赖项 file2.mod(即创建时的时间),但仅由make根据其最新touch(最新修改时间)来判断 file.mod 本身?我也欢迎关于采取不同做法的建议。

B = build
S = src
F = gfortran
f = -J$B -I$B 
P = program 
modfile_names = constypes computes systems tests
obj = $(addprefix $B/, $(modfile_names:=.o))   
vpath %.f90 $S
all:
make -j4 $P
$P:$(obj)
$F $f $^ -o $@
$B/%.o:%.f90 $B/%.mod
$F $f -c $< -o $@
$B/%.mod:
$F $f -fsyntax-only $S/$(notdir ${@:.mod=.f90}) 
$B/tests.mod: $B/constypes.mod $B/computes.mod $B/systems.mod
$B/computes.mod $B/systems.mod: $B/constypes.mod
.phony:clear
clear: 
rm $B/* $P

我的代码结构完全相同。此外,仅当修改了源文件时,才会更新.o文件,但.mod文件可以较旧。 这是生成文件:

# Compiler options
FC  := $(F90) -cpp
FFLAGS  := -fdefault-real-8 -fdefault-integer-8 -Wall -Wtabs -Ofast -fcheck=all -ffree-line-length-none -pthread
# Define directories
OOP_DIR :=  ../oop
MOD_DIR :=  ../build
vortZ2D_DIR := ..
# Define file extensions
.SUFFIXES: .f90 .o .mod
# Targets (objects)
OBJ  = $(MOD_DIR)/fft.o $(MOD_DIR)/grid.o $(MOD_DIR)/geom.o $(MOD_DIR)/body.o $(MOD_DIR)/fluid.o
OBJ1 = $(MOD_DIR)/vortZ2D.o
TAR1 = vortZ2D
# Build rules
all: runner | $(MOD_DIR)
$(MOD_DIR):
mkdir -p $(MOD_DIR)
$(MOD_DIR)/%.o: $(OOP_DIR)/%.f90 | $(MOD_DIR)
$(FC) $(FFLAGS) -c $^ -o $@ -J$(MOD_DIR)
$(MOD_DIR)/%.o: $(vortZ2D_DIR)/%.f90 | $(MOD_DIR)
$(FC) $(FFLAGS) $(OBJ) -o $(TAR1) ../vortZ2D.f90 -J$(MOD_DIR)
runner: $(OBJ) $(OBJ1)
clean:
@if [ -d $(MOD_DIR) ]; then 
rm -rf $(MOD_DIR) && echo "build/ cleaned"; 
else 
echo "nothing to clean"; 
fi
run:
@"make; ./vortZ2D; cd ../bin"

我在/bin文件夹中有这个生成文件。在/oop中更新源文件时,不会触发级联。如果需要,您可以包含-fsyntax-only标志以加快速度。希望这有帮助。

最新更新