我在Makefile中有以下规则来分三个阶段构建可执行文件:
all: build/myexe
build/myexe: output/main_dats.o output/foo_dats.o | build/
gcc $^ -o $@
output/%.o: output/%.c
patscc -c $< -o $@
output/%_dats.c: src/%.dats | output/
patsopt -cc -o $@ -d $<
build/:
mkdir -p build/
output/:
mkdir -p output/
src/%.dats
源文件用于生成output/%_dats.c
源文件,该文件被编译为output/%.o
目标文件,最后它们被链接到可执行文件build/myexe
。< / p>
第一次运行make
只会成功构建两个.o
文件的第一个:
$ make
mkdir -p output/
patsopt -cc -o output/main_dats.c -d src/main.dats
patscc -c output/main_dats.c -o output/main_dats.o
make: *** No rule to make target `output/foo_dats.o', needed by `build/myexe'. Stop.
rm output/main_dats.c
但是再次运行将构建第二个.o
文件并成功链接可执行文件:
$ make
patsopt -cc -o output/foo_dats.c -d src/foo.dats
patscc -c output/foo_dats.c -o output/foo_dats.o
mkdir -p build/
gcc output/main_dats.o output/foo_dats.o -o build/myexe
rm output/foo_dats.c
并注意在每次调用结束时,命令rm output/..._dats.c
正在删除生成的.c
源文件。
这是一个没有模式匹配的Makefile:
all: build/myexe
build/myexe: output/main_dats.o output/foo_dats.o | build/
gcc $^ -o $@
output/foo_dats.o: output/foo_dats.c
patscc -c $< -o $@
output/main_dats.o: output/main_dats.c
patscc -c $< -o $@
output/foo_dats.c: src/foo.dats | output/
patsopt -cc -o $@ -d $<
output/main_dats.c: src/main.dats | output/
patsopt -cc -o $@ -d $<
build/:
mkdir -p build/
output/:
mkdir -p output/
更可预测的是:
$ make
mkdir -p output/
patsopt -cc -o output/main_dats.c -d src/main.dats
patscc -c output/main_dats.c -o output/main_dats.o
patsopt -cc -o output/foo_dats.c -d src/foo.dats
patscc -c output/foo_dats.c -o output/foo_dats.o
mkdir -p build/
gcc output/main_dats.o output/foo_dats.o -o build/myexe
并注意,生成的.c
文件不再被删除。
显然我在滥用模式匹配机制。我知道有一些通配符功能,但我相信它适用于文件通配。
答案 0 :(得分:2)
为避免删除中间文件,您只需将它们列为某处的实际目标。例如,您可以编写单独的规则:
.jumbotron.tight {
margin-bottom: 0;
}
您不必将此目标make_srcs: output/main_dats.c output/foo_dats.c
列为先决条件,也不必提供配方等。只需将make_srcs
文件列为makefile中的实际目标或先决条件即可它们被删除了。
至于你的“只构建一些输出”的行为,我不知道:它对我来说很好用:
_dats.c
因此,您的设置中有一些内容尚未在您的问题中明确说明。正如评论所示,您需要运行$ make --version | head -n1
GNU Make 4.2.1
$ cat Makefile
all: build/myexe
build/myexe: output/main_dats.o output/foo_dats.o | build/
touch $@
output/%.o: output/%.c
touch $@
output/%_dats.c: src/%.dats | output/
touch $@
build/:
mkdir -p build/
output/:
mkdir -p output/
make_srcs: output/main_dats.c output/foo_dats.c
$ rm -rf output build && make
mkdir -p output/
touch output/main_dats.c
touch output/main_dats.o
touch output/foo_dats.c
touch output/foo_dats.o
mkdir -p build/
touch build/myexe
(我会忽略make -d
选项,我不知道您为什么要添加它)并弄清楚为什么会抛出错误。
答案 1 :(得分:0)
理想情况下,不应该弃用模式规则。他们容易过度匹配(因为,模式),他们可能很难开始工作,他们带来了整个&#34;中间目标&#34;问题(删除您正在观察的output/*.c
个文件),他们需要另一个可疑功能(&#34;二次扩展&#34;)以使其可用于一些更多涉及的场景等。
简而言之:不建议使用模式规则,并且使用多级模式规则肯定不建议。比它的价值更麻烦。无论如何,恕我直言。
(结束咆哮)
所以我建议你写一个简单的宏,所以你的makefile最终看起来像这样:
all: build/myexe
# $(call dats,basename)
define dats
output/$1_dats.o: output/$1_dats.c
patscc -c $$< -o $$@
output/$1_dats.c: src/$1.c | output
patcc -cc -o $$@ -d $$<
endif
build/myexe: output/main_dats.o output/foo_dats.o | build
gcc $^ -o $@
$(eval $(call dats,foo))
$(eval $(call dats,main))
build:
mkdir -p build
output:
mkdir -p output