如何在Makefile中使用'build'和'clean'制作'rebuild'规则?

时间:2016-11-13 17:30:05

标签: makefile

我有一个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,该规则将按顺序执行cleanall 。我看不出如何正确地实现正确的排序。

我所看到的解决方案对我来说是错误的。

rebuild: clean all
.PHONY: rebuild

自然是错误的,因为无法保证依赖关系实际按其外观顺序执行。 all可以在clean之前执行。

我已经看到了建议仅订单依赖的答案,例如

rebuild: | clean all
.PHONY: rebuild

据我所知,这并不能解决问题。如果您说a: | b c,则表示a取决于bc,但如果采用bc,则不会执行a规则。它与排序依赖项无关。

我现在看到的唯一选择是通过

启动一个新的make实例
rebuild : clean
    make build

我真的想避免启动一个新的make实例来做一些简单的事情!

我做了一些关于SO的研究。我见过类似的问题,但没有正确的答案。对我来说,制作目标.PHONY或使用仅订单依赖项不是解决方案。

3 个答案:

答案 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时,您可以使用cleanallrebuild之间有条件地添加依赖关系。像这样:

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