makefile - 为带有模块的 Fortran 项目寻找最佳多线程 makefile

标签 makefile module fortran gfortran

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

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

当源代码被编译时,如果没有 gfortran -fsyntax-only,模块文件只会在它发生变化时更新,而不管相应的目标文件是否更新。因此,与对应于同一 .f90 文件的 .o 文件相比,.mod 文件可能更旧。

如果 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(即创建时间),但让 file.mod 本身仅由 make 根据其最新的 touch 判断 (最新修改时间)例如?我也欢迎提出不同方法的建议。

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

关于makefile - 为带有模块的 Fortran 项目寻找最佳多线程 makefile,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41025462/

相关文章:

oop - 使用延迟和不可重写过程和 gcc 编译器面向对象的 Fortran 中的不确定行为

memory - 使用整数变量在 FORTRAN 上计算阶乘。内存溢出

testing - make test后如何强制cmake写入测试输出

makefile - 使用 CMake 将 *.gcno 和 *.gcda 文件添加到 make clean 规则

makefile - 可以在 gnu makefile 中对共享库进行静态库链接吗?

c++ - 发生 PIE 链接错误时不能使用针对 `.bss' 的重定位 R_X86_64_32S

python - simpleCV 和树莓派 : no module named simplecv

Makefile 什么是 "SHELL = bash"

javascript - 如何在Vue+webpack+vue-loader项目中导入不同js文件的函数

azure - 使用 PowerShell 隐式导入较旧的模块版本