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

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

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

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

我主要使用mingw/msys,但也希望在其他shell/系统中工作。

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

1
2
3
ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR) )))
-mkdir $(OBJDIR)
endif

查看官方制作文档,以下是一个很好的方法:

1
2
3
4
5
6
7
8
9
10
11
12
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标志。另一种选择见其他答案。


在Unix上,只需使用:

1
mkdir -p $(OBJDIR)

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


您可以使用test命令:

1
test -d $(OBJDIR) || mkdir $(OBJDIR)

下面是我使用GNU make创建编译器输出目录的一个技巧。首先定义此规则:

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

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

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

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

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

1
 .PRECIOUS: %/.d

跳过.d文件(直接取决于目录)将不起作用,因为每次在该目录中写入文件时都会更新目录修改时间,这将在每次调用make时强制重新生成。


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

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

在makefile中:

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


在Windows上

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

关于UNIX Linux

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

1
2
3
ifeq"$(wildcard $(MY_DIRNAME) )"""
  -mkdir $(MY_DIRNAME)
endif

1
2
$(OBJDIR):
    mkdir $@

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

1
2
3
4
OBJDIRS := $(sort $(dir $(OBJECTS)))

$(OBJDIRS):
    mkdir $@

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


它在mingw32/msys/cygwin/linux下工作

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

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

1
mkdir 2>/dev/null || true

这不应该造成一个平行的种族危险-但我还没有测试它确定。


比拉尔斯的回答简单一点:

1
something_needs_directory_xxx : xxx/..

和一般规则:

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

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

如果你想看到另一个通用的gmake小技巧,或者如果你对使用最小脚手架的非递归make感兴趣,你可能会想在那个博客中找到两个更便宜的gmake技巧和另一个相关的make文章。


推荐阅读

    linux下一层目录命令?

    linux下一层目录命令?,系统,数据,命令,目录,信息,传播,时间,基础,一致,文件,L

    linux命令进入根目录?

    linux命令进入根目录?,工作,系统,位置,设备,一致,财务,公司,地址,目录,命令,l

    linux命令去上一目录?

    linux命令去上一目录?,系统,电脑,一致,目录,上级,名称,命令,空格,读法,终端,l

    目录管理linux命令?

    目录管理linux命令?,管理,系统,工作,信息,目录,命令,文件,工具,电脑,档案,玩

    linux命令生成序列?

    linux命令生成序列?,系统,工具,信息,灵活,名称,管理,工作,状态,网络,命令,lin

    linux可生成文件命令?

    linux可生成文件命令?,名字,命令,名称,文件,文件夹,位置,数据,密码,时间,电

    linux跳至子目录命令?

    linux跳至子目录命令?,名字,第一,第三,侄子,女婿,贪官,重典,子目录,丞相,生

    linux交换目录的命令?

    linux交换目录的命令?,系统,工作,信息,命令,标准,名称,在线,目录,分区,内容,L

    linux目录操作命令d?

    linux目录操作命令d?,工作,系统,信息,命令,情况,基础,数据,名称,地址,目录,li

    linux命令错误的是?

    linux命令错误的是?,系统,信息,异常,密码,工具,地址,网络,实时,状态,数据,Lin

    linux访问根目录命令?

    linux访问根目录命令?,系统,位置,一致,公司,财务,设备,命令,根目录,传播,密

    linux显示错误命令?

    linux显示错误命令?,信息,系统,电脑,状态,时间,环境,命令,搜狐,密码,异常,虚

    linux退出错误命令的?

    linux退出错误命令的?,系统,电脑,环境,命令,位置,管理,工具,设备,终端,进程,L

    linux上层目录命令?

    linux上层目录命令?,系统,一致,网络,命令,目录,管理,数据,电脑,空格,文件,Lin

    linux如何目录命令?

    linux如何目录命令?,名称,首次,系统,名字,数据,命令,目录,信息,标准,文件,Lin

    linux没有该命令错误?

    linux没有该命令错误?,系统,第一,环境,命令,分析,软件,异常,文件,目录,空格,

    linux生成修复命令行?

    linux生成修复命令行?,系统,数据,一致,流程,软件,网上,第一,管理,磁盘,命令,l

    linux命令回上层目录?

    linux命令回上层目录?,电脑,系统,一致,服务,目录,命令,上级,名称,空格,终端,l

    linux生成修复命令行?

    linux生成修复命令行?,系统,数据,一致,流程,软件,网上,第一,管理,磁盘,命令,l

    linux生成静态库命令?

    linux生成静态库命令?,工程,设备,代码,管理,通用,入口,静态,文件,链接,命令,l