使用 mkdir 时如何防止 makefile 中出现“目录已存在错误”
题
我需要在我的 makefile 中生成一个目录,并且我不想一遍又一遍地收到“目录已存在错误”,即使我可以轻松忽略它。
我主要使用 mingw/msys,但也希望能在其他 shell/系统上工作。
我尝试了这个,但没有成功,有什么想法吗?
ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR) )))
-mkdir $(OBJDIR)
endif
解决方案
在 UNIX 上只需使用这个:
mkdir -p $(OBJDIR)
如果目录存在,mkdir 的 -p 选项可防止出现错误消息。
其他提示
看着 官方制作文档, ,这是一个好方法:
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
与文档的示例相比,添加了标志。请参阅其他答案以了解另一种选择。
您可以使用测试命令:
test -d $(OBJDIR) || mkdir $(OBJDIR)
这是我在 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
在你的 makefile 中:
target:
if test -d dir; then echo "hello world!"; else mkdir dir; fi
在 Windows 上
if not exist "$(OBJDIR)" mkdir $(OBJDIR)
在unix | Linux
if [ ! -d "$(OBJDIR)" ]; then mkdir $(OBJDIR); fi
ifeq "$(wildcard $(MY_DIRNAME) )" ""
-mkdir $(MY_DIRNAME)
endif
$(OBJDIR):
mkdir $@
这也适用于多个目录,例如...
OBJDIRS := $(sort $(dir $(OBJECTS)))
$(OBJDIRS):
mkdir $@
添加 $(OBJDIR)
因为第一个目标效果很好。
它运行在 mingw32/msys/cygwin/linux 下
ifeq "$(wildcard .dep)" ""
-include $(shell mkdir .dep) $(wildcard .dep/*)
endif
如果您明确忽略返回代码并转储错误流,那么您的 make 将忽略发生的错误:
mkdir 2>/dev/null || true
这不应该导致并行制造中的竞争危险 - 但我还没有测试它来确定。
比拉尔斯的回答简单一点:
something_needs_directory_xxx : xxx/..
和通用规则:
%/.. : ;@mkdir -p $(@D)
无需清理或制作触摸文件。珍贵:-)
如果您想了解另一个通用的 gmake 技巧,或者您对具有最少脚手架的非递归 make 感兴趣,您可能需要查看一下 另外两个便宜的 gmake 技巧 以及该博客中其他与 make 相关的帖子。