Answers:
在UNIX上,只需使用以下命令:
mkdir -p $(OBJDIR)
如果目录存在,则mkdir的-p选项可防止出现错误消息。
-p
在Windows上不起作用,这大概是问题所在。不知道这是怎么被接受的。
make -p
Unix还是Linux?
查看正式的make文档,这是一个很好的方法:
OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
all: $(OBJS)
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir -p $(OBJDIR)
您应该在这里看到|的用法。管道操作员,仅定义订单是先决条件。意味着$(OBJDIR)
目标应该存在(而不是最近的),以便建立当前目标。
请注意,我用过mkdir -p
。-p
与文档示例相比,添加了该标志。参见其他答案。
$(OBJDIR)
目标应该存在 ”。检查文件的存在(和时间戳),以决定是否需要构建目标。因此在这里,如果$(OBJDIR)
不存在,它将构建它,以便存在以构建当前目标$(OBJS)
,该目标将在内部创建。
您可以使用测试命令:
test -d $(OBJDIR) || mkdir $(OBJDIR)
make -j
由于在测试目录是否存在以及创建目录之间存在竞争状况,因此在并行构建()时此解决方案可能会中断。一个作业可以测试它是否不存在,但是在创建它之前,另一个作业可以创建目录。然后,当第一个尝试创建它时,它将失败,因为该目录已经存在。在这种情况下,最好的解决方案是仅使用@TeKa答案中提到的先决条件(应该是公认的答案)。
这是我与GNU make一起使用来创建编译器输出目录的一个技巧。首先定义此规则:
%/.d:
mkdir -p $(@D)
touch $@
然后,使进入该目录的所有文件都依赖于该目录中的.d文件:
obj/%.o: %.c obj/.d
$(CC) $(CFLAGS) -c -o $@ $<
注意使用$ <代替$ ^。
最后,防止.d文件自动删除:
.PRECIOUS: %/.d
跳过.d文件并直接取决于目录是不起作用的,因为每次在该目录中写入文件时都会更新目录修改时间,这将在每次调用make时强制进行重建。
如果目录已经存在对您来说不是问题,那么您可以重定向该命令的stderr,摆脱错误消息:
-mkdir $(OBJDIR) 2>/dev/null
在Windows上
if not exist "$(OBJDIR)" mkdir $(OBJDIR)
在Unix上| 的Linux
if [ ! -d "$(OBJDIR)" ]; then mkdir $(OBJDIR); fi
/bin/sh: 1: Syntax error: end of file unexpected (expecting "then")
$(OBJDIR):
mkdir $@
这也适用于多个目录,例如。
OBJDIRS := $(sort $(dir $(OBJECTS)))
$(OBJDIRS):
mkdir $@
添加$(OBJDIR)
为第一个目标效果很好。
比Lars的答案简单一点:
something_needs_directory_xxx : xxx/..
和通用规则:
%/.. : ;@mkdir -p $(@D)
没有触摸文件可以清理或制作.PRECIOUS :-)
如果您想了解另一个通用的gmake技巧,或者对使用最少脚手架的非递归make感兴趣,则可以在该博客中查看另外两个便宜的gmake技巧和其他与make相关的文章。