清理目标文件后不重新编译

问题描述 投票:0回答:1

我有以下makefile:

compiler := g++
flags := -Wall -Wextra -Wpedantic -Werror -O2 -march=native
libs := sqlite3

build_dir := build
debug_dir := debug
source_dir := src
object_dir := obj
include_dir := include

objects := main.o politician.o data_base.o exceptions.o input.o
# Prepend object_dir/ to every object
objects := $(patsubst %, $(object_dir)/%, $(objects))

dependencies := data_base.hpp exceptions.hpp politician.hpp input.hpp CLI11.hpp
# Prepend include_dir/ to every dependency
dependencies := $(patsubst %, $(include_dir)/%, $(dependencies))

executable := politician

# Don't remove object files when finished
.SECONDARY: $(objects)

.PHONY: all
all: $(build_dir)/$(executable) | $(build_dir)

.PHONY: debug
debug: flags += -g
debug: $(debug_dir)/$(executable) | $(debug_dir)/

%/$(executable): $(objects)
    $(compiler) $(flags) -l $(libs) $^ -o $@

$(object_dir)/%.o: $(source_dir)/%.cpp $(dependencies) | $(object_dir)/
    $(compiler) $(flags) -I $(include_dir) -c $< -o $@

%/:
    mkdir -p $@

.PHONY: clean
clean:
    rm -f $(objects)

.PHONY: clean-all
clean-all:
    rm -f $(objects) $(build_dir)/$(executable) $(debug_dir)/$(executable)

预计在运行make clean之后,make all将重新编译所有内容(因为可执行文件取决于对象并且它们不再存在),但这不是正在发生的事情:相反,我得到了make: Nothing to be done for 'all'.

导致此行为的原因是什么?

makefile gnu-make
1个回答
0
投票

之所以会这样,是因为您使用的是模式规则链。

考虑一个简单的例子:

all: build/politician

build/politician: main.o
    whatever...

main.o: src/main.cpp
    whatever...

如果运行make,它将先构建main.o,然后构建build/politician。如果然后删除main.o并再次运行make,它将再次生成main.obuild/politician

现在将其中两个规则更改为模式规则:

all: build/politician

%/politician: main.o
    whatever...

%.o: src/%.cpp
    whatever...

现在第一次运行make时,它将再次构建main.o,然后再构建build/politician。但是,当您删除main.o并再次运行make时,它将报告“对于'all'无需执行任何操作”并且什么也不做。这是因为main.o现在是中间文件,并且根据the manual

如果普通文件b不存在,并且make考虑依赖于b的目标,则它总是创建b,然后从b更新目标。但是,如果b是一个中间文件,那么make可以单独放置。除非更新b的某些先决条件或有其他原因更新该目标,否则它不会麻烦更新b或最终目标。

© www.soinside.com 2019 - 2024. All rights reserved.