为什么当源文件改变时 make 不重新编译这些目标文件?
Why does make not recompile these object files when the source files are changed?
我有两个源文件,library.f90
和 toolbox.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.f90
或 toolbox.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.o
和 toolbox.o
都依赖于 library.f90
和 toolbox.f90
,这意味着如果其中一个被更改,则两个都是重建的,如果一个丢失,则两个构建都将失败。
至于您的规则失败的原因:它正在您当前目录中寻找 library.f90
,但根据规则我推断源位于子目录 /home/ma/include
.
中
更好的解决方案是:
${OBJ} : %.o : ${INCLUDE}/%.f90
${FC} ${CFLAGS} -c $^ -o $@
(我还删除了前导 @
,因为我发现查看它尝试执行的实际命令非常有用 运行。)
我有两个源文件,library.f90
和 toolbox.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.f90
或 toolbox.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.o
和 toolbox.o
都依赖于 library.f90
和 toolbox.f90
,这意味着如果其中一个被更改,则两个都是重建的,如果一个丢失,则两个构建都将失败。
至于您的规则失败的原因:它正在您当前目录中寻找 library.f90
,但根据规则我推断源位于子目录 /home/ma/include
.
更好的解决方案是:
${OBJ} : %.o : ${INCLUDE}/%.f90
${FC} ${CFLAGS} -c $^ -o $@
(我还删除了前导 @
,因为我发现查看它尝试执行的实际命令非常有用 运行。)