how to prevent "directory already exists error" in a makefile when using mkdir

我需要在 makefile 中生成一个目录,并且我不希望一遍又一遍地出现“目录已经存在错误”,即使我可以很容易地忽略它。

I mainly use mingw/msys but would like something that works across other shells/systems too.

我试过了,但没用,有什么办法吗?

ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR) )))
-mkdir $(OBJDIR)
endif
125215 次浏览

如果目录已经存在对您来说不是问题,您可以为该命令重定向 stderr,消除错误消息:

-mkdir $(OBJDIR) 2>/dev/null

在 UNIX 上使用下面的代码:

mkdir -p $(OBJDIR)

Mkdir 的-p 选项可以防止在目录存在时出现错误消息。

在你的 makefile 中:

target:
if test -d dir; then echo "hello world!"; else mkdir dir; fi

您可以使用 test 命令:

test -d $(OBJDIR) || mkdir $(OBJDIR)
ifeq "$(wildcard $(MY_DIRNAME) )" ""
-mkdir $(MY_DIRNAME)
endif
$(OBJDIR):
mkdir $@

它也适用于多个目录,例如。

OBJDIRS := $(sort $(dir $(OBJECTS)))


$(OBJDIRS):
mkdir $@

添加 $(OBJDIR)作为第一个目标工作得很好。

On Windows

if not exist "$(OBJDIR)" mkdir $(OBJDIR)

On Unix | Linux

if [ ! -d "$(OBJDIR)" ]; then mkdir $(OBJDIR); fi

下面是我在使用 GNU 创建编译器输出目录时使用的一个技巧:

  %/.d:
mkdir -p $(@D)
touch $@

然后使所有进入该目录的文件依赖于该目录中的. d 文件:

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

注意使用 $< 代替 $^ 。

最后防止.d 文件被自动删除:

 .PRECIOUS: %/.d

跳过。D 文件,并且直接取决于目录,将无法工作,因为每次在该目录中写入文件时,目录修改时间都会更新,这将强制在每次调用 make 时重新构建。

Looking at 官方制作文件, here is a good way to do it:

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)

You should see here the usage of the | pipe operator, defining an order only prerequisite. 这意味着为了构建当前目标,应该存在 $(OBJDIR)目标(而不是 more recent)。

注意,我使用了 mkdir -p。与文档的示例相比,添加了 -p标志。 查看其他答案,寻找另一种选择。

It works under mingw32/msys/cygwin/linux

ifeq "$(wildcard .dep)" ""
-include $(shell mkdir .dep) $(wildcard .dep/*)
endif

比佬司的回答要简单一点:

something_needs_directory_xxx : xxx/..

和一般规则:

%/.. : ;@mkdir -p $(@D)

没有触摸文件清理或制作。珍贵: -)

如果您希望看到另一个通用的 gmake 技巧,或者如果您对使用最小脚手架的非递归 make 感兴趣,那么可以查看该博客中的 还有两个小把戏和其他与 make 相关的文章。

如果显式忽略返回代码并转储错误流,那么如果发生错误,make 将忽略该错误:

mkdir 2>/dev/null || true

这应该不会在并行制作中引起竞争危险-但我还没有测试它来确定。