为什么当源文件改变时 make 不重新编译这些目标文件?

Why does make not recompile these object files when the source files are changed?

我有两个源文件,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.f90toolbox.f90 时,这不会重新编译 library.o(或 toolbox.o)。我认为这是因为缺少依赖项,所以我将 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 识别那里的依赖关系并按预期编译源文件。

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

你的第二个版本稍微好一点,但现在意味着 library.otoolbox.o 都依赖于 library.f90toolbox.f90,这意味着如果其中一个被更改,则两个都是重建的,如果一个丢失,则两个构建都将失败。

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

更好的解决方案是:

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

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