常见的模式是:
obj/%.o : src/%.c
mkdir -p $(dir $@)
$(CC) -c $< -o $@
我想知道我是否可以为每个文件分配mkdir
的呼叫。我遇到了这个解决方案:
CSRC=some/path/here/foo.c another/directory/random/here/bar.c
OBJDIR=obj/
objdirs = $(sort $(foreach path,$(CSRC),$(addprefix $(OBJDIR),$(dir $(path)))))
$(objdirs): %:
mkdir -p $@
obj/%.o : src/%.c | $(objdirs)
$(CC) -c $< -o $@
有更好的解决方案吗?
答案 0 :(得分:3)
一个简单的解决方案,但不是100%令人满意,与您的相似:
OBJDIR := obj
CSRC := some/path/here/foo.c another/directory/random/here/bar.c
CSRCDIRS := $(sort $(dir $(CSRC)))
objdirs := $(addprefix $(OBJDIR)/,$(CSRCDIRS))
OBJS := $(patsubst %.c,$(OBJDIR)/%.o,$(CSRC))
$(OBJS): $(OBJDIR)/%.o: %.c | $(objdirs)
$(CC) -c $< -o $@
$(objdirs):
mkdir -p $@
它应该可以工作,但它的缺点是每个目标文件都有所有对象目录作为仅订单的先决条件,这是过度的。即使只构建了一个目标文件,也会创建所有对象目录。它们只会被创建一次,因为它们只是订单,但它仍然不是100%令人满意。
为了每个目标文件只有一个只有订单的对象目录先决条件,我看到的唯一解决方案(但可能有更好的解决方案)是这样的:
OBJDIR := obj
CSRC := some/path/here/foo.c another/directory/random/here/bar.c
CSRCDIRS := $(sort $(dir $(CSRC)))
objdirs := $(addprefix $(OBJDIR)/,$(CSRCDIRS))
# $(1): source directory
define MY_rule
$(OBJDIR)/$(1)%.o: $(1)%.c | $(OBJDIR)/$(1)
$(CC) -c $$< -o $$@
endef
$(foreach c,$(CSRCDIRS),$(eval $(call MY_rule,$(c))))
$(objdirs):
mkdir -p $@
迭代器显式声明每个对象目录,作为它所包含的所有目标文件的唯一仅限订单的先决条件。但它更难理解(特别是$$
)。是否值得额外的复杂性?