这是一个示例,说明了我想要的输出:
LIST1 := hello.o world.o
LIST2 := hello.c world.c
# Make the first object
# hello.o: hello.c
$(word 1, $(LIST1)): $(word 1, $(LIST2))
cc -c $^ -o $@
# Make the second object
# world.o: world.c
$(word 2, $(LIST1)): $(word 2, $(LIST2))
cc -c $^ -o $@
是否有一种方法来总结目标:先决条件文本,使其循环遍历两个完整的列表?
我已经尝试使用foreach
函数与word
函数,但我没有得到输出。我得到word
和其他无效表达式的非数字参数。
您实际上可以这样做,但是真的很难看(并且很难维护),我给出了答案,但我绝对不建议使用它…如果你能像@MadScientist建议的那样使用模式规则,那就再好不过了。如果不是(如果名称不同,您可以这样做):
LIST1 := hello.o bob.o
hello.o : hello.c
bob.o : sally.c
$(LIST1):
cc -c $< -o $@
允许您为每个目标指定自定义先决条件。如果你真的需要两个列表,对你的问题的技术回答如下:
LIST1 := hello.o bob.o
LIST2 := hello.c sally.c
all:
define recursive_def
$(firstword $(1)) : $(firstword $(2))
cc -c $$^ -o $$@
$(if $(wordlist 2,3,$1),$(call recursive_def,$(wordlist 2,$(words $(1)),$1),$(wordlist 2,$(words $(2)),$(2))))
endef
$(info -v---v-)
$(info $(call recursive_def,$(LIST1),$(LIST2)))
$(info -^---^-)
$(eval $(call recursive_def,$(LIST1),$(LIST2)))
简短的回答是"不"。为什么不直接写一个模式规则呢?
all: $(LIST1)
%.o : %.c
cc -c $^ -o $@
?事实上,你根本不需要编写模式规则:make已经有了一个默认规则,可以从C源文件构建目标文件。
埃塔
如果源文件在不同的目录中,您有两个选择。最好的选择是使用一个模式规则,并在模仿源目录的子目录结构中创建所有对象。所以,像这样:
SRCS := foo.c bar/bar.c bar/biz/baz.c
OBJS := $(patsubst %.c,obj/%.o,$(SRCS))
all: $(OBJS)
obj/%.o : %.c
@mkdir -p $(@D)
$(COMPILE.c) -o $@ $<
如果你真的不想这样做,你想把所有的目标文件到同一个目录(一个坏主意,因为如果你有两个源文件具有相同的名称在不同的源目录,你的构建将失败),你可以使用VPATH
:
SRCS := foo.c bar/bar.c bar/biz/baz.c
OBJS := $(patsubst %.c,obj/%.o,$(notdir $(SRCS)))
VPATH := $(sort $(dir $(SRCS)))
all: $(OBJS)
obj/%.o : %.c
@mkdir -p $(@D)
$(COMPILE.c) -o $@ $<