具有通用中间规则的 Makefile
Makefile with generic intermediate rules
我有一个看起来像这样的 makefile:
TARGET:=prog
SOURCES:=a.c b.c
CFLAGS:=-Wall -g -O2
OBJECTS:=$(SOURCES:%.c=%.o)
$(TARGET): $(OBJECTS)
gcc -o $@ $^
%.o: %.c
gcc $(CFLAGS) -c -o $@ $<
clean:
rm -f $(TARGET) $(OBJECTS)
用户需要更改的唯一变量是目标名称和构建它所需的源。需要生成的对象是根据源自动确定的。我想扩展它以支持多个目标,每个目标都有自己的源列表。不过,我在正确使用语法时遇到了麻烦。这是总体思路:
TARGETS:=prog1 prog2
SOURCES_prog1:=a.c b.c
SOURCES_prog2:=a.c c.c
CFLAGS:=-Wall -g -O2
OBJECTS_$@=$(SOURCES_$@:%.c=%.o)
$(TARGETS): $(OBJECTS_$@)
gcc -o $@ $^
%.o: %.c
gcc $(CFLAGS) -c -o $@ $<
clean:
rm -f $(TARGET) $(OBJECTS)
但是我无法正确生成对象列表。我也不确定如何编写 clean
规则来清除所有对象。这可能吗?
我认为有两种主要方法可以做到这一点。
第一个涉及使用 $(eval)
function.
动态创建 target/prerequisite 映射
TARGETS:=prog1 prog2
SOURCES_prog1:=a.c b.c
SOURCES_prog2:=a.c c.c
CFLAGS:=-Wall -g -O2
$(TARGETS):
gcc -o $@ $^
$(foreach t,$(TARGETS),$(eval OBJECTS_$t := $(SOURCES_$t:.c=.o))$(eval $t: $(OBJECTS_$t)))
第二个涉及使用 Secondary Expansion。
TARGETS:=prog1 prog2
SOURCES_prog1:=a.c b.c
SOURCES_prog2:=a.c c.c
CFLAGS:=-Wall -g -O2
.SECONDEXPANSION:
$(TARGETS): $$(OBJECTS_$$@)
gcc -o $@ $^
$(foreach t,$(TARGETS),$(eval OBJECTS_$t := $(SOURCES_$t:.c=.o)))
在任一情况下,clean
目标变为:
clean:
rm -f $(TARGETS) $(foreach t,$(TARGETS),$(OBJECTS_$t))
我有一个看起来像这样的 makefile:
TARGET:=prog
SOURCES:=a.c b.c
CFLAGS:=-Wall -g -O2
OBJECTS:=$(SOURCES:%.c=%.o)
$(TARGET): $(OBJECTS)
gcc -o $@ $^
%.o: %.c
gcc $(CFLAGS) -c -o $@ $<
clean:
rm -f $(TARGET) $(OBJECTS)
用户需要更改的唯一变量是目标名称和构建它所需的源。需要生成的对象是根据源自动确定的。我想扩展它以支持多个目标,每个目标都有自己的源列表。不过,我在正确使用语法时遇到了麻烦。这是总体思路:
TARGETS:=prog1 prog2
SOURCES_prog1:=a.c b.c
SOURCES_prog2:=a.c c.c
CFLAGS:=-Wall -g -O2
OBJECTS_$@=$(SOURCES_$@:%.c=%.o)
$(TARGETS): $(OBJECTS_$@)
gcc -o $@ $^
%.o: %.c
gcc $(CFLAGS) -c -o $@ $<
clean:
rm -f $(TARGET) $(OBJECTS)
但是我无法正确生成对象列表。我也不确定如何编写 clean
规则来清除所有对象。这可能吗?
我认为有两种主要方法可以做到这一点。
第一个涉及使用 $(eval)
function.
TARGETS:=prog1 prog2
SOURCES_prog1:=a.c b.c
SOURCES_prog2:=a.c c.c
CFLAGS:=-Wall -g -O2
$(TARGETS):
gcc -o $@ $^
$(foreach t,$(TARGETS),$(eval OBJECTS_$t := $(SOURCES_$t:.c=.o))$(eval $t: $(OBJECTS_$t)))
第二个涉及使用 Secondary Expansion。
TARGETS:=prog1 prog2
SOURCES_prog1:=a.c b.c
SOURCES_prog2:=a.c c.c
CFLAGS:=-Wall -g -O2
.SECONDEXPANSION:
$(TARGETS): $$(OBJECTS_$$@)
gcc -o $@ $^
$(foreach t,$(TARGETS),$(eval OBJECTS_$t := $(SOURCES_$t:.c=.o)))
在任一情况下,clean
目标变为:
clean:
rm -f $(TARGETS) $(foreach t,$(TARGETS),$(OBJECTS_$t))