为什么我的 makefile 在构建后调用 rm 依赖项?

Why does my makefile call rm on dependencies after building?

当我 运行 make -j tests 时,它使测试正常但随后删除了依赖项。为什么要这样做,我该如何解决?对于复杂的 makefile,我深表歉意。 makefile 的相关部分是测试部分。

生成文件:

# Build tools
CC = clang++ -g --std=gnu++11 -O3
LEX = flex
YACC = bison -d

# Includes
CC_HEADERS   = `llvm-config-3.5 --cppflags`
CC_LIBRARIES = -lboost_program_options `llvm-config-3.5 --libs all --ldflags` -ltinfo -lpthread -lffi -ldl -lm -lz

# Created files
GENERATED_SOURCES = parser.cpp tokens.cpp
GENERATED_FILES   = $(GENERATED_SOURCES)
EXEC = brainfuck.out

# Test cases
TESTS            = $(wildcard ./tests/*.bf)
TESTS_IN         = $(TESTS:.bf=.in)
TESTS_BUILD      = $(TESTS:.bf=.build)
TESTS_EXPECTED   = $(TESTS:.bf=.expected)
TESTS_ACTUAL     = $(TESTS:.bf=.actual)
TESTS_DIFF       = $(TESTS:.bf=.diff)
GENERATED_FILES += $(TESTS_BUILD) $(TESTS_EXPECTED) $(TESTS_ACTUAL) $(TESTS_DIFF)

# Generic config
SOURCES  = $(filter-out $(GENERATED_SOURCES), $(wildcard *.cpp))
SOURCES += $(GENERATED_SOURCES)
OBJECTS  = $(SOURCES:.cpp=.o)

# Main targets
target: $(EXEC)

all: target tests

# Generated source targets
tokens.cpp: tokens.l parser.hpp
    $(LEX) -o $@ $<

parser.hpp: parser.cpp

parser.cpp: parser.y
    $(YACC) -o $@ $<

# Test targets
tests: $(TESTS_DIFF)
    @echo ""
    @echo "#####################"
    @echo "# Begin test output #"
    @echo "#####################"
    @$(foreach f,$^, echo "Test:" $(f:.diff=.bf); cat $(f); echo "";)
    @echo "#####################"
    @echo "#  End test output  #"
    @echo "#####################"
    @echo ""

tests/%.build: tests/%.bf $(EXEC)
    ./brainfuck.out $< -p | llc-3.5 - -o - | gcc -O0 -x assembler - -o $@

tests/%.expected: tests/%.bf tests/%.in
    -bf -c65535 $< < $(word 2,$^) > $@

tests/%.actual: tests/%.build tests/%.in
    -$< < $(word 2,$^) > $@

tests/%.diff: tests/%.expected tests/%.actual
    -diff $< $(word 2,$^) > $@

# Generic targets
clean:
    rm -rf $(EXEC) $(OBJECTS) $(GENERATED_FILES) $(GENERATED_SOURCES:.cpp=.hpp)

$(EXEC): $(OBJECTS)
    $(CC) -o $@ ${OBJECTS} $(CC_LIBRARIES)

%.o: %.cpp parser.hpp
    $(CC) $(CC_HEADERS) -c $< -o $@

输出:

bf -c65535 tests/awib-0.4.bf < tests/awib-0.4.in > tests/awib-0.4.expected
./brainfuck.out tests/awib-0.4.bf -p | llc-3.5 - -o - | gcc -O0 -x assembler - -o tests/awib-0.4.build
bf -c65535 tests/dbfi.bf < tests/dbfi.in > tests/dbfi.expected
./brainfuck.out tests/dbfi.bf -p | llc-3.5 - -o - | gcc -O0 -x assembler - -o tests/dbfi.build
bf -c65535 tests/factor.bf < tests/factor.in > tests/factor.expected
./brainfuck.out tests/factor.bf -p | llc-3.5 - -o - | gcc -O0 -x assembler - -o tests/factor.build
bf -c65535 tests/hanoi.bf < tests/hanoi.in > tests/hanoi.expected
./brainfuck.out tests/hanoi.bf -p | llc-3.5 - -o - | gcc -O0 -x assembler - -o tests/hanoi.build
bf -c65535 tests/long.bf < tests/long.in > tests/long.expected
./brainfuck.out tests/long.bf -p | llc-3.5 - -o - | gcc -O0 -x assembler - -o tests/long.build
bf -c65535 tests/mandelbrot.bf < tests/mandelbrot.in > tests/mandelbrot.expected
./brainfuck.out tests/mandelbrot.bf -p | llc-3.5 - -o - | gcc -O0 -x assembler - -o tests/mandelbrot.build
bf -c65535 tests/prime.bf < tests/prime.in > tests/prime.expected
./brainfuck.out tests/prime.bf -p | llc-3.5 - -o - | gcc -O0 -x assembler - -o tests/prime.build
tests/dbfi.build < tests/dbfi.in > tests/dbfi.actual
tests/long.build < tests/long.in > tests/long.actual
tests/factor.build < tests/factor.in > tests/factor.actual
tests/prime.build < tests/prime.in > tests/prime.actual
tests/mandelbrot.build < tests/mandelbrot.in > tests/mandelbrot.actual
tests/hanoi.build < tests/hanoi.in > tests/hanoi.actual
tests/awib-0.4.build < tests/awib-0.4.in > tests/awib-0.4.actual
diff tests/factor.expected tests/factor.actual > tests/factor.diff
diff tests/awib-0.4.expected tests/awib-0.4.actual > tests/awib-0.4.diff
diff tests/mandelbrot.expected tests/mandelbrot.actual > tests/mandelbrot.diff
diff tests/hanoi.expected tests/hanoi.actual > tests/hanoi.diff
diff tests/long.expected tests/long.actual > tests/long.diff
diff tests/prime.expected tests/prime.actual > tests/prime.diff
diff tests/dbfi.expected tests/dbfi.actual > tests/dbfi.diff

#####################
# Begin test output #
#####################
Test: tests/awib-0.4.bf

Test: tests/dbfi.bf

Test: tests/factor.bf

Test: tests/hanoi.bf

Test: tests/long.bf

Test: tests/mandelbrot.bf

Test: tests/prime.bf

#####################
#  End test output  #
#####################

rm tests/mandelbrot.actual tests/hanoi.build tests/long.actual tests/mandelbrot.build tests/factor.actual tests/awib-0.4.actual tests/long.build tests/prime.actual tests/hanoi.expected tests/factor.build tests/awib-0.4.build tests/dbfi.expected tests/prime.build tests/mandelbrot.expected tests/dbfi.actual tests/long.expected tests/dbfi.build tests/hanoi.actual tests/factor.expected tests/prime.expected tests/awib-0.4.expected

注意最后一行 rm ...。这是从哪里来的?

解决办法是把.SECONDARY:放在makefile的顶部。更多信息在这里:http://www.thinkplexx.com/learn/howto/build-chain/make-based/prevent-gnu-make-from-always-removing-files-it-says-things-like-rm-or-removing-intermediate-files

摘录:

GNU make does track some files, which are created during the build, and it will remove such files after the build. The files are called "intermediate files". They are supposed to be created by make’s "chain of Implicit Rules". Because they were created to facilitate something else, make considers them useless after the build and removes them.

...

.SECONDARY with no prerequisites causes all targets to be treated as secondary (i.e., no target is removed because it is considered intermediate