为什么在更改源文件时不重新编译这些目标文件?

时间:2017-03-26 22:20:26

标签: makefile fortran gnu-make gfortran

我在一个单独的目录中有两个源文件library.f90toolbox.f90。这些编译成目标文件,在编译主文件时链接,恰当地称为main。最初,我有这个Makefile:

TARGET  = main
SRC     = ${TARGET}.f95

FC      = /usr/bin/gfortran
CFLAGS  = -O2 -std=gnu -Wfatal-errors -I${INCLUDE}

INCLUDE = /home/ma/include
OBJ     = library.o toolbox.o
OBJ_SRC = $(subst .o,.f90,${OBJ})


all: ${TARGET}

${TARGET}: ${SRC} ${OBJ}
    @${FC} ${CFLAGS} -pedantic -Wall ${OBJ} ${SRC} -o ${TARGET}

${OBJ}:
    @echo "Compiling $(subst .o,,$@)"
    @${FC} ${CFLAGS} -c ${INCLUDE}/$(subst .o,.f90,$@) -o $@

clean:
    @rm -vf ${TARGET} ${OBJ}

但在编辑源文件library.otoolbox.o时,这不会重新编译library.f90(或toolbox.f90)。我认为这是因为缺少依赖关系,所以我将Makefile调整为如下所示:

TARGET  = main
SRC     = ${TARGET}.f95

FC      = /usr/bin/gfortran
CFLAGS  = -O2 -std=gnu -Wfatal-errors -I${INCLUDE}

INCLUDE = /home/ma/include
OBJ     = library.o toolbox.o

all: ${TARGET}

${TARGET}: ${SRC} ${OBJ}
    @${FC} ${CFLAGS} -pedantic -Wall ${OBJ} ${SRC} -o ${TARGET}

${OBJ}: ${OBJ_SRC}
    @echo "Compiling $(subst .o,,$@)"
    @${FC} ${CFLAGS} -c ${INCLUDE}/$(subst .o,.f90,$@) -o $@

clean:
    @rm -vf ${TARGET} ${OBJ}

然而,这会抛出错误

make: *** No rule to make target 'library.f90', needed by 'library.o'.  Stop.

我不明白这一点,因为没有规则来构建${SRC},但是make会识别那里的依赖项并按预期编译源文件。

1 个答案:

答案 0 :(得分:2)

在您的第一个版本中,目标文件'规则没有指定任何先决条件。这就是为什么make没有检查library.f90是否已经改变,因此没有重新创建它。

您的第二个版本略胜一筹,但现在意味着library.otoolbox.o都取决于 library.f90toolbox.f90,意思是如果其中任何一个被更改,则两个都重建,如果其中任何一个丢失,则两个构建都将失败。

至于你的规则失败的原因:它在当前目录中寻找library.f90,但是根据规则我推断出这些来源位于子目录/home/ma/include中。

更好的解决方案是:

${OBJ} : %.o : ${INCLUDE}/%.f90
        ${FC} ${CFLAGS} -c $^ -o $@

(我还删除了前导@,因为我觉得查看它尝试运行的实际命令非常有用。)