Makefile 使用静态模式规则的多个目标的一个配方?

Makefile 使用静态模式规则的多个目标的一个配方?,makefile,gnu-make,Makefile,Gnu Make,使用make实现以下目标的最佳方法是什么: 输入文件 输出文件应为(使用GCC): 请注意,输入c文件不在同一文件夹中,我希望自动收集输入文件 这里的示例(使用静态模式规则)仅在c文件都在同一个文件夹中时有效,但在上述情况下如何工作 SOURCES = $(shell find $(PRJ)/app -type f -name *.c) OBJECTS = $(patsubst $(PRJ)/app/%, $(PRJ)/obj/%, $(SOURCES:.c=.o)) .PHONY: bu

使用make实现以下目标的最佳方法是什么:

输入文件 输出文件应为(使用GCC): 请注意,输入c文件不在同一文件夹中,我希望自动收集输入文件

这里的示例(使用静态模式规则)仅在c文件都在同一个文件夹中时有效,但在上述情况下如何工作

SOURCES  = $(shell find $(PRJ)/app -type f -name *.c)
OBJECTS  = $(patsubst $(PRJ)/app/%, $(PRJ)/obj/%, $(SOURCES:.c=.o))

.PHONY: build
build: $(OBJECTS)

$(OBJECTS): $(PRJ)/obj/%.o: $(PRJ)/app/%.c)
    $(CC) $(CFLAGS) -c -o $@ $<
SOURCES=$(shell find$(PRJ)/app-type f-name*.c)
OBJECTS=$(patsubst$(PRJ)/app/%,$(PRJ)/obj/%,$(源代码:.c=.o))
.伪造:建造
生成:$(对象)
$(对象):$(PRJ)/obj/%.o:$(PRJ)/app/%.c)
$(CC)$(CFLAGS)-c-o$@$<
使用:

SOURCES:=$(shell find$(PRJ)-type f-name“*.c”)
#$(PRJ)/lib/foo.c$(PRJ)/app/bar.c$(PRJ)/app/baz.c
SOURCE_DIRS:=$(sort$(dir$(SOURCES)))
#$(PRJ)/app/$(PRJ)/lib/
对象:=$(patsubst%.c,$(PRJ)/obj/%.o,$(notdir$(SOURCES)))
#$(PRJ)/obj/foo.o$(PRJ)/obj/bar.o$(PRJ)/obj/baz.o
.伪造:建造
生成:$(对象)
vpath%.c$(源目录)
$(对象):$(PRJ)/obj/%.o:%.c
$(CC)$(CFLAGS)-c-o$@$<
使用:

SOURCES:=$(shell find$(PRJ)-type f-name“*.c”)
#$(PRJ)/lib/foo.c$(PRJ)/app/bar.c$(PRJ)/app/baz.c
SOURCE_DIRS:=$(sort$(dir$(SOURCES)))
#$(PRJ)/app/$(PRJ)/lib/
对象:=$(patsubst%.c,$(PRJ)/obj/%.o,$(notdir$(SOURCES)))
#$(PRJ)/obj/foo.o$(PRJ)/obj/bar.o$(PRJ)/obj/baz.o
.伪造:建造
生成:$(对象)
vpath%.c$(源目录)
$(对象):$(PRJ)/obj/%.o:%.c
$(CC)$(CFLAGS)-c-o$@$<

如果不编写多个规则,就无法做到这一点。如果你真的有很多,你可以使用define/foreach/eval来生成它们,而不是手工写出来。但是,如果只有两个,就不值得增加复杂性(IMO)。另外,请记住,如果您将所有输出放在同一个目录中,您必须确保输入文件名都不相同(例如,您不能同时拥有
$PRJ/lib/foo.c
$PRJ/app/foo.c
)@madcascient,这是可以用一条规则实现的。您创建一个
.o
->
.c
映射(例如,通过超过
$(eval somemagic\u$1:=$2)
),然后使用二次扩展来获取先决条件(例如
$(somemagic\u$@)
)。现在,如果这样做对两个dir来说是值得的,那就另当别论了…@AndreaBiondo我认为使用我建议的define/eval方法更简单,也更易读:)@MadScientist绝对:)我只是喜欢想办法滥用make。我很尴尬,我没有想到vpath。如果不编写多个规则,就无法做到这一点。如果你真的有很多,你可以使用define/foreach/eval来生成它们,而不是手工写出来。但是,如果只有两个,就不值得增加复杂性(IMO)。另外,请记住,如果您将所有输出放在同一个目录中,您必须确保输入文件名都不相同(例如,您不能同时拥有
$PRJ/lib/foo.c
$PRJ/app/foo.c
)@madcascient,这是可以用一条规则实现的。您创建一个
.o
->
.c
映射(例如,通过超过
$(eval somemagic\u$1:=$2)
),然后使用二次扩展来获取先决条件(例如
$(somemagic\u$@)
)。现在,如果这样做对两个dir来说是值得的,那就另当别论了…@AndreaBiondo我认为使用我建议的define/eval方法更简单,也更易读:)@MadScientist绝对:)我只是喜欢想办法滥用make。“我很尴尬,我没有想到vpath。这很好。@疯狂科学家:如果我想到一个优雅的解决方案来解决一个你认为不可能解决的问题,那只能说明你患了食物中毒。太好了!谢谢,太好了!“这真是太好了!”疯狂科学家:如果我想到了一个优雅的解决方案来解决你认为不可能解决的问题,那只能说明你患了食物中毒。太好了!谢谢,太好了!
$PRJ/obj/foo.o
$PRJ/obj/bar.o
$PRJ/obj/baz.o
SOURCES  = $(shell find $(PRJ)/app -type f -name *.c)
OBJECTS  = $(patsubst $(PRJ)/app/%, $(PRJ)/obj/%, $(SOURCES:.c=.o))

.PHONY: build
build: $(OBJECTS)

$(OBJECTS): $(PRJ)/obj/%.o: $(PRJ)/app/%.c)
    $(CC) $(CFLAGS) -c -o $@ $<
SOURCES := $(shell find $(PRJ) -type f -name "*.c")
# $(PRJ)/lib/foo.c $(PRJ)/app/bar.c $(PRJ)/app/baz.c

SOURCE_DIRS := $(sort $(dir $(SOURCES)))
# $(PRJ)/app/ $(PRJ)/lib/

OBJECTS := $(patsubst %.c,$(PRJ)/obj/%.o, $(notdir $(SOURCES)))
# $(PRJ)/obj/foo.o $(PRJ)/obj/bar.o $(PRJ)/obj/baz.o

.PHONY: build
build: $(OBJECTS)

vpath %.c $(SOURCE_DIRS)

$(OBJECTS): $(PRJ)/obj/%.o: %.c
    $(CC) $(CFLAGS) -c -o $@ $<