使用模块为Fortran项目寻求Optimal多线程makefile

时间:2016-12-07 19:11:40

标签: makefile module fortran gfortran

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

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

编译源时,如果没有gfortran -fsyntax-only,则模块文件只有在更改时才会更新,无论相应的目标文件是否更新。因此,可以使用比同一.f90文件对应的.mod个文件更旧的.o个文件。

如果更新了file.f90,则应更新相应的file.o,并且可能是file.mod。如果更新了file.mod,则应使用gfortran -fsyntax-only file2.f90检查依赖于file.mod的file2.mod。只有当file2.mod得到更新时,file2.o才会被编译(这是一个耗时的步骤,否则应该避免。(这是否正确?))。

实施和问题:我在下面的make文件中实现了这些原则。但问题出现在(预期)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

1 个答案:

答案 0 :(得分:0)

我的代码结构完全相同。此外,仅在修改源文件时,.o文件才会更新,但.mod文件可能更旧。 这是makefile:

# 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文件夹中有这个makefile。在/oop中更新源文件时,没有触发级联。如果需要,您可以加入-fsyntax-only标记以加快速度。希望这会有所帮助。