Makefile - 依赖性检查/命令运行顺序

时间:2014-12-12 19:17:27

标签: makefile

我制作了一个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对这些模块的影响有什么不同。

1 个答案:

答案 0 :(得分:2)

原谅我,但你的makefile有点乱。所以我用好的做法重写了它,所有的问题都消失了。 objectsmodules都是严格意义上的,不需要,但如果你扩展你的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)

非常重要