我正在使用 MinGW 编译 Fortran 源代码并在 Windows 上制作。
源文件扩展名是
.f
和 .for
- .for
是模块(某些 .for
文件甚至包含多个模块)。
我有一个通用的 makefile ;基本上是
# Source directories
dirs := . srkf
# Executable to create
Executable = D:\Executables\a.exe
# -------------------------------------------------------
# Obj dir
Objets_dir = ../obj
VPATH = $(dirs) $(Objets_dir)
# Creation of .for list
Sourmod := $(foreach dir,$(dirs),$(wildcard $(dir)/*.for))
# Creation of .f list
Sources := $(foreach dir,$(dirs),$(wildcard $(dir)/*.f))
# Obj list
Objmod = $(patsubst %.for,%.o,$(Sourmod))
Objets = $(patsubst %.f,%.o,$(Sources))
# Full path to .o
TempObjets = $(addprefix $(Objets_dir)/, $(notdir $(Objmod) $(Objets)))
# Comp options
cpl = gfortran
cpl_opt = -ffpe-trap=invalid,zero,overflow -O3 -Wall
lnk = gfortran
lnk_opt =
# Compilation
$(Objets_dir)/%.o:%.for
$(cpl) -J$(Objets_dir) $(cpl_opt) -c $< -o $(Objets_dir)\$(notdir $@)
$(Objets_dir)/%.o:%.f
$(cpl) -I$(Objets_dir) $(cpl_opt) -c $< -o $(Objets_dir)\$(notdir $@)
# Link
$(Executable): $(TempObjets)
$(lnk) -o $@ $^ $(lnk_opt)
clean:
@-rm -rf $(Objets_dir) $(Executable)
首先编译模块,但是:
include
语句(而不是模块,尽管我仍然会在其他地方使用模块),以及相同类型的依赖关系问题出现了。如果我有一个 foo.f
文件,其中某个地方有 include 'bar.inc'
,那么修改 bar.inc
文件并编译代码不会导致 foo.f
被重新编译。这显然是有问题的。
为了解决这个问题,有人建议我以这种方式修改makefile(自动创建依赖文件)
# Source directories
dirs := . srkf
# Executable to create
Executable = D:\Executables\a.exe
# -------------------------------------------------------
# Obj dir
Objets_dir ?= ../obj
VPATH = $(dirs) $(Objets_dir)
# Creation of .for list
Sourmod := $(foreach dir,$(dirs),$(wildcard $(dir)/*.for))
# Creation of .f list
Sources := $(foreach dir,$(dirs),$(wildcard $(dir)/*.f))
# Obj list
Objmod = $(patsubst %.for,%.o,$(Sourmod))
Objets = $(patsubst %.f,%.o,$(Sources))
# Full path to .o
TempObjets = $(addprefix $(Objets_dir)/, $(notdir $(Objmod) $(Objets)))
DEPENDS = $(patsubst %.o,%.d,$(TempObjets))
# Comp options
cpl = gfortran
FFLAGS = -ffpe-trap=invalid,zero,overflow -O3 -Wall
lnk = gfortran
lnk_opt =
all: $(Executable)
# Compilation
$(Objets_dir)/%.o:%.for
$(cpl) -J$(Objets_dir) $(FFLAGS) -c $< -o $@
$(Objets_dir)/%.o:%.f
$(cpl) -I$(Objets_dir) $(FFLAGS) -c $< -o $@
$(Objets_dir)/%.d: %.for
@-(echo -n $(Objets_dir)/;$(cpl) -cpp -MM -J$(Objets_dir) -fsyntax-only $(FFLAGS) -c $<) > $@
$(Objets_dir)/%.d: %.f
@-(echo -n $(Objets_dir)/;$(cpl) -cpp -MM -I$(Objets_dir) -fsyntax-only $(FFLAGS) -c $<) > $@
-include $(DEPENDS)
# Link
$(Executable): $(TempObjets)
$(lnk) $(lnk_opt) -o $@ $^
# Clean
clean:
@-rm -rf $(Objets_dir)/* $(Executable)
#all:
# @echo $(value Sources)
# @echo $(value Objets)
# @echo $(value TempObjets)
这确实适用于包含:修改
bar.inc
文件并编译代码现在确实会导致 foo.f
被重新编译 - 太棒了。
但是修改模块(
.for
文件)仍然不会导致使用该模块(或.for
文件中存在的模块)重新编译文件。
您将如何编写此 makefile,以便考虑两种行为/依赖关系?
如果您希望在重建任何模块 (
.f
) 文件时重建所有 Fortran (.for
) 文件,只需对 makefile 进行以下更改即可:
# Obj target lists
Objmod = $(patsubst %.for,$(Objets_dir)/%.o,$(notdir $(Sourmod)))
Objets = $(patsubst %.f,$(Objets_dir)/%.o,$(notdir $(Sources)))
# All objects
TempObjets = $(Objmod) $(Objets)
# Make sure all .f objects are rebuilt after any .for objects are built
$(Objets) : $(Objmod)