我有一个Makefile,其中包含构建小项目和清理它的规则。例如:
CC:=gcc
LD:=gcc
SOURCES:=$(wildcard src/*.c)
OBJS:=$(SOURCES:src/%.c=build/%.o)
TARGET:=bin/program
all: $(TARGET)
$(TARGET): $(OBJS)
@mkdir -p bin
$(LD) $+ -o $@
build/%.o: src/%.c
@mkdir -p build
$(CC) $+ -c -o $@
clean:
rm -rf $(OBJS)
rm -rf $(TARGET)
rmdir bin
rmdir build
.PHONY: clean all
我现在有兴趣创建一个规则rebuild
,该规则将按顺序执行clean
和all
。我看不出如何正确地实现正确的排序。
我所看到的解决方案对我来说是错误的。
rebuild: clean all
.PHONY: rebuild
自然是错误的,因为无法保证依赖关系实际按其外观顺序执行。 all
可以在clean
之前执行。
我已经看到了建议仅订单依赖的答案,例如
rebuild: | clean all
.PHONY: rebuild
据我所知,这并不能解决问题。如果您说a: | b c
,则表示a
取决于b
和c
,但如果采用b
或c
,则不会执行a
规则。它与排序依赖项无关。
我现在看到的唯一选择是通过
启动一个新的make实例rebuild : clean
make build
我真的想避免启动一个新的make实例来做一些简单的事情!
我做了一些关于SO的研究。我见过类似的问题,但没有正确的答案。对我来说,制作目标.PHONY
或使用仅订单依赖项不是解决方案。
答案 0 :(得分:6)
首先,在规则中并非如此:
rebuild: clean all
all
之前可以在clean
之前构建-j
(即没有并行.PHONY: rebuild
rebuild:
$(MAKE) clean
$(MAKE) all
启用)。 Make总是按照它们在makefile中列出的顺序构建先决条件(包含配方的规则有一个特例,但这里没有相关性)。当使用并行构建时,make仍然以相同的顺序遍历依赖树,但由于规则是并行构建的,因此它们可能不会以相同的顺序启动。
但是,你是对的,因为其他原因(目录缓存等),这个规则不是一个好主意。
我建议您使用递归make调用来执行此操作:
#!/usr/bin/env python
import json
i = 0
for record in json.load(open('raw.json', 'r'))['json_records']:
open('record_{}.json'.format(i), 'w').write(json.dumps(record))
i += 1
答案 1 :(得分:2)
当目标为MAKECMDGOALS
时,您可以使用clean
在all
和rebuild
之间有条件地添加依赖关系。像这样:
ifeq (rebuild,$(findstring rebuild,${MAKECMDGOALS}))
all: clean
rebuild: all
endif
现在,我还没有看到在makefile中执行此操作的好处,当有其他简单而安全的方法(仅“make clean && make all
”可能是更好的选择时)
答案 2 :(得分:1)
有一种方法可以在没有递归的情况下完成;价格是少量的冗余:
.PHONY: rebuild
$(TARGET) rebuild: $(OBJS)
@mkdir -p bin
$(LD) $+ -o $(TARGET) # note that I have replaced $@ with $(TARGET)
rebuild: | clean