使用mkdir时如何防止makefile中的"目录已存在错误"

KPe*_*xEA 107 directory makefile exists

我需要在我的makefile中生成一个目录,我想不要一遍又一遍地得到"目录已存在错误",即使我可以轻易忽略它.

我主要使用mingw/msys但是想要能够在其他shell /系统中运行的东西.

我试过这个,但它没有用,有什么想法?

ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR) )))
-mkdir $(OBJDIR)
endif
Run Code Online (Sandbox Code Playgroud)

ofa*_*vre 120

查看官方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)
Run Code Online (Sandbox Code Playgroud)

你应该在这里看到|的用法 管道运算符,仅定义订单先决条件.意味着$(OBJDIR)目标应该存在(而不是更新)以构建当前目标.

请注意,我用过mkdir -p.-p与文档示例相比,添加了该标志.另见其他选择.

  • 这绝对是解决这个问题的官方方式. (4认同)

tch*_*hen 105

在UNIX上只需使用:

mkdir -p $(OBJDIR)
Run Code Online (Sandbox Code Playgroud)

如果目录存在,mkdir的-p选项可防止出现错误消息.

  • "通常,坚持使用这些程序广泛支持的(通常是posix指定的)选项和功能.例如,不要使用'mkdir -p',因为它可能很方便,因为有些系统不支持它在所有人和其他人之间,并行执行是不安全的."http://www.gnu.org/s/hello/manual/make/Utilities-in-Makefiles.html (39认同)
  • `-p`在Windows上不起作用,这可能是问题所在.不确定这是如何被接受的. (6认同)
  • 对于Windows,请投票:https://connect.microsoft.com/PowerShell/feedback/details/1074131/mkdir-and-rm-needs-unix-like-most-pertinent-switches (2认同)

sky*_*ymt 66

您可以使用test命令:

test -d $(OBJDIR) || mkdir $(OBJDIR)
Run Code Online (Sandbox Code Playgroud)

  • 如果您需要makefile在Windows(使用gnuwin32和PowerShell)和POSIX兼容的操作系统中工作,这是首选方法. (7认同)
  • 提供了gnuwin32 CoreUtils包以提供'test'实用程序. (6认同)
  • 在这里很晚,但是我想指出这个解决方案在并行构建时会崩溃(`make -j`),因为在测试目录存在和创建目录之间存在竞争条件.一个作业可以测试它不在那里,但在创建它之前,另一个作业创建目录.然后,当第一个尝试创建它时,它将失败,因为该目录已存在.在这种情况下,最好的解决方案是使用@ TeKa的答案(应该是接受的答案)中提到的仅有订单的先决条件. (2认同)

Lar*_*rén 18

这是我用GNU make创建编译器输出目录的技巧.首先定义此规则:

  %/.d:
          mkdir -p $(@D)
          touch $@
Run Code Online (Sandbox Code Playgroud)

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

 obj/%.o: %.c obj/.d
    $(CC) $(CFLAGS) -c -o $@ $<
Run Code Online (Sandbox Code Playgroud)

注意使用$ <而不是$ ^.

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

 .PRECIOUS: %/.d
Run Code Online (Sandbox Code Playgroud)

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


and*_*ich 13

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

-mkdir $(OBJDIR) 2>/dev/null
Run Code Online (Sandbox Code Playgroud)


Lee*_*e H 11

在makefile中:

target:
    if test -d dir; then echo "hello world!"; else mkdir dir; fi
Run Code Online (Sandbox Code Playgroud)


小智 9

在Windows上

if not exist "$(OBJDIR)" mkdir $(OBJDIR)
Run Code Online (Sandbox Code Playgroud)

在Unix上| Linux的

if [ ! -d "$(OBJDIR)" ]; then mkdir $(OBJDIR); fi
Run Code Online (Sandbox Code Playgroud)


Mic*_*rty 7

ifeq "$(wildcard $(MY_DIRNAME) )" ""
  -mkdir $(MY_DIRNAME)
endif
Run Code Online (Sandbox Code Playgroud)


Mar*_*ido 6

$(OBJDIR):
    mkdir $@
Run Code Online (Sandbox Code Playgroud)

这也适用于多个目录,例如.

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

$(OBJDIRS):
    mkdir $@
Run Code Online (Sandbox Code Playgroud)

添加$(OBJDIR)作为第一个目标效果很好.