我在Make中看到了一些制作输出目录的方法。 这些包括提前将所有目录放在任何规则之外,以及 将对象的目标目录作为对象规则的一部分。 这两种方法都涉及制作可能已经存在的目录。
我是否遗漏了解释为什么我没有看到以下方法的任何缺点或缺点?
.SECONDEXPANSION:
$(OBJDIR)%.o: %.c | $$(@D)/
# Compile command
.PRECIOUS: %/
%/:
# mkdir Command
答案 0 :(得分:1)
make
非常擅长处理文件。 make
在处理目录方面不是很擅长。
因此,将目录视为目标规则内部的实现细节是有道理的,因为make
永远不必考虑目录:
MKDIR_P = mkdir -p
$(objdir)%.o: %.c
@$(MKDIR_P) $(@D)
$(COMPILE.c) -o $@ -c $<
请注意,mkdir -p
所需的处理和IO可以在编译所需的处理和IO旁边忽略。
答案 1 :(得分:0)
目录的问题是(与任何其他目标相反)你不关心他们的时间戳,你只需要他们存在。许多Makefile导致目录错误,并且一遍又一遍地创建它们就是你所观察到的,所以make
永远不会检测到“没有什么可以做...... ”。
事实上,你只需要来正确处理GNU make目录就是“ order only dependency ”,如你的例子中所示。通常不需要尾部斜杠(您似乎使用它以获得模式规则,我不确定这是否有效),并且您也不需要.PRECIOUS
。 .SECONDEXPANSION
的诀窍看起来很整洁,我猜测这会起作用,因为模式规则确实有效(没试过)。
作为替代方案,大多数正确处理目录的Makefile通过在单个变量中连接规则的所有所需输出目录并使用此变量作为另一规则的目标(例如,就像在这个简化的例子中一样:
MODULES:=src/main
OBJDIR?=obj
OBJS:=$(addprefix $(OBJDIR)/,$(addsuffix .c,$(MODULES)))
DIRS:=$(sort $(addprefix $(OBJDIR)/,$(dir $(OBJS))))
TARGET:= myprogram
all: $(TARGET)
myprogram: $(OBJS)
$(CC) -o$@ $^
$(DIRS):
mkdir -p $(DIRS)
$(OBJDIR)/%.o: %.c Makefile | $(DIRS)
$(CC) -c -o$@ $<
clean:
rm -fr $(OBJDIR)
.PHONY: all clean