我制作了一个makefile来编译一系列fortran模块。我的想法是编写,以便检查文件夹../obj中是否存在.o文件,以及文件夹../mod中是否存在.mod文件,如果缺少任何一个文件,则重新编译模块,文件存储在那些相应的文件夹中。代码如下:
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
# SOURCES AND PATHS
#--------------------------------------------------------------------#
MODPATH = ../mod
OBJPATH = ../obj
SRCS = $(wildcard *.f)
OBJS = $(SRCS:%.f=%.o)
MODS = $(SRCS:%.f=%.mod)
#
#
# COMPILING ORDERS
#--------------------------------------------------------------------#
FC = ifort
FFLAGS = -g -O3 -c -cpp -Dpack -fPIC -module $(MODPATH)
all : objects modules
objects : $(OBJS:%.o=$(OBJPATH)/%.o)
modules : $(MODS:%.mod=$(MODPATH)/%.mod)
$(OBJPATH)/%.o : %.f ../obj
$(FC) $(FFLAGS) -c $< -o $@
../obj:
mkdir ../obj
$(MODPATH)/%.mod : %.f ../mod
$(FC) $(FFLAGS) -c $< -o $(@:$(MODPATH)/%.mod=$(OBJPATH)/%.o)
../mod:
mkdir ../mod
#
#
# CLEAN
#--------------------------------------------------------------------#
.PHONY: clean
clean :
rm -f $(OBJS:%.o=$(OBJPATH)/%.o) $(MODS:%.mod=$(MODPATH)/%.mod)
#
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
显然它起到了我所描述的作用;但是,它有一种我不完全理解的行为。因为当我在make clean之后制作它时,它会将一些模块编译两次,然后编译一次:
ifort -g -O3 -c -cpp -Dpack -fPIC -module ../mod -c garcha_mod.f -o ../obj/garcha_mod.o
ifort -g -O3 -c -cpp -Dpack -fPIC -module ../mod -c liokeys.f -o ../obj/liokeys.o
ifort -g -O3 -c -cpp -Dpack -fPIC -module ../mod -c sysdata.f -o ../obj/sysdata.o
ifort -g -O3 -c -cpp -Dpack -fPIC -module ../mod -c garcha_mod.f -o ../obj/garcha_mod.o
ifort -g -O3 -c -cpp -Dpack -fPIC -module ../mod -c liokeys.f -o ../obj/liokeys.o
(1)为什么有些模块会编译两次?当它因为缺少.o或.mod而编译时,该命令会创建两个文件,因此当它检查另一个文件时,它应该注意到它已经完成。 (2)为什么它会编译一些模块两次但是其他一些只编译一次?我没有注意到makefile对这些模块的影响有什么不同。
答案 0 :(得分:2)
原谅我,但你的makefile有点乱。所以我用好的做法重写了它,所有的问题都消失了。 objects
和modules
都是严格意义上的,不需要,但如果你扩展你的makefile,也许你在其他地方需要它们,所以我把它们包括在内。
Wildcarding来源是个坏主意。请参阅上面的评论。明确列出文件 - 它对您来说很健康! :)
MODPATH := ../mod
OBJPATH := ../obj
SRCS := \
garcha_mod.f \
liokeys.f \
sysdata.f \
.PHONY: all objects modules
all : objects modules
objects : $(SRCS:%.f=$(OBJPATH)/%.o)
modules : $(SRCS:%.f=$(MODPATH)/%.mod)
$(OBJPATH)/%.o : $(MODPATH)/%.mod ;
.SECONDARY: %/.
%/.: Makefile
mkdir -p $*
.SECONDEXPANSION:
$(MODPATH)/%.mod : %.f Makefile | $$(@D)/. $(OBJPATH)/.
ifort -g -O3 -c -cpp -Dpack -fPIC -module $(@D) -o $(OBJPATH)/$*.o
clean:
rm -rf $(MODPATH)
rm -rf $(OBJPATH)
这里有一个微妙的问题。
如果用户仅删除了.o
文件,则会出现问题。一个人通过告诉用户解决这个问题,在不知道他们在做什么的情况下不要无偿地删除文件。他们必须使用make clean
,或者更好的是,不要随时删除任何内容,因为使用正确构造的makefile,没有必要。
还需要注意的是,通过仔细阅读有关中断的GNU Make规则,杀死正在进行的食谱,不会导致.mod
文件存在,但.o
不存在。
事实上,这就是我订购&#34;清洁&#34;这样的食谱。首先删除$(MODPATH)
然后$(OBJPATH)
。