2008-09-19 12 views
96

我需要在我的makefile中生成一个目录,并且我希望不会一遍又一遍地得到“目录已存在的错误”,即使我可以轻松忽略它。如何防止使用mkdir时生成的makefile中的“目录已存在的错误”

我主要使用mingw/msys,但希望能够在其他shell /系统上运行。

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

ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR)))) 
-mkdir $(OBJDIR) 
endif 

回答

95

在UNIX只要使用此:

mkdir -p $(OBJDIR) 

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

+36

“一般来说,坚持这些程序的广泛支持(通常是posix指定的)选项和功能。例如,不要使用'mkdir -p',因为它可能很方便,因为少数系统不支持它和所有其他人一样,并行执行并不安全。“http://www.gnu.org/s/hello/manual/make/Utilities-in-Makefiles.html – 2011-12-19 17:28:52

+5

`-p`不起作用在Windows上,这大概是问题的问题。不知道这是如何被接受。 – Antimony 2014-05-06 02:00:52

+2

对于Windows,请对此投票:https://connect.microsoft.com/PowerShell/feedback/details/1074131/mkdir-and-rm-needs-unix-like-most-pertinent-switches – 2015-01-02 22:08:06

11

如果具有目录已经存在是不是对你的问题,你可以只重定向标准错误该命令,摆脱错误消息:

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

这也有在Windows上工作的优势。不要忘记命令前面的' - ',所以不要保释。 – 2008-09-19 03:45:27

11

里面你的Makefile:

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

您可以使用测试命令:

test -d $(OBJDIR) || mkdir $(OBJDIR) 
+7

如果您需要makefile在Windows(使用gnuwin32和PowerShell)和POSIX兼容的操作系统中工作,则这是首选方式。 – 2012-01-06 18:56:37

+6

提供了你有gnuwin32 CoreUtils包来提供'测试'工具。 – davenpcj 2013-08-02 01:36:09

7
ifeq "$(wildcard $(MY_DIRNAME))" "" 
    -mkdir $(MY_DIRNAME) 
endif 
6
$(OBJDIR): 
    mkdir [email protected] 

这也适用于多个目录,e.g ..

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

$(OBJDIRS): 
    mkdir [email protected] 

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

8

在Windows

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

在Unix | Linux

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

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

%/.d: 
      mkdir -p $(@D) 
      touch [email protected] 

然后做出进入目录依赖于该目录中的文件.D的所有文件:

obj/%.o: %.c obj/.d 
    $(CC) $(CFLAGS) -c -o [email protected] $< 

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

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

.PRECIOUS: %/.d 

跳过.D文件,并直接在该目录根据,是行不通的,因为该目录的修改时间是每一次更新文件被写入该目录,这将在每次调用make时强制进行重建。

109

看着the official make documentation,这里是一个很好的办法做到这一点:

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标志。 另请参阅其他解答。

3

它的工作原理下的mingw32/MSYS/Cygwin的/ Linux的

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

比拉斯的回答稍微简单一些:

something_needs_directory_xxx : xxx/.. 

和通用规则:

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

没有触摸文件清理或制作.PRECIOUS :-)

如果你想看到另一个小的通用gmake技巧,或者如果你对最小脚手架的非递归制作感兴趣,你可能会关注Two more cheap gmake tricks以及该博客中其他与制作相关的帖子。

0

如果你明确地忽略返回代码并转储错误流然后如果它发生的make忽略的错误:

mkdir 2>/dev/null || true 

这应该不会造成并行make比赛危险 - 但还没t测试它是肯定的。

相关问题