如何预防;目录已存在错误";使用mkdir时在makefile中
我需要在我的makefile中生成一个目录,我不想一遍又一遍地得到“directory ready exists error”,即使我可以很容易地忽略它 我主要使用mingw/msys,但也希望其他shell/系统也能使用 我试过了,但没用,有什么想法吗如何预防;目录已存在错误";使用mkdir时在makefile中,makefile,directory,exists,Makefile,Directory,Exists,我需要在我的makefile中生成一个目录,我不想一遍又一遍地得到“directory ready exists error”,即使我可以很容易地忽略它 我主要使用mingw/msys,但也希望其他shell/系统也能使用 我试过了,但没用,有什么想法吗 ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR) ))) -mkdir $(OBJDIR) endif 如果目录已经存在对您来说不是问题,那么您可以为该命令重定向stderr,从而消除错误消
ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR) )))
-mkdir $(OBJDIR)
endif
如果目录已经存在对您来说不是问题,那么您可以为该命令重定向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)
它也适用于多个目录,例如
OBJDIRS := $(sort $(dir $(OBJECTS)))
$(OBJDIRS):
mkdir $@
添加$(OBJDIR)
作为第一个目标效果很好。在Windows上
if not exist "$(OBJDIR)" mkdir $(OBJDIR)
在Unix | Linux上
if [ ! -d "$(OBJDIR)" ]; then mkdir $(OBJDIR); fi
下面是我使用GNUMake创建编译器输出目录的技巧。首先定义此规则:
%/.d:
mkdir -p $(@D)
touch $@
然后使进入该目录的所有文件依赖于该目录中的.d文件:
obj/%.o: %.c obj/.d
$(CC) $(CFLAGS) -c -o $@ $<
跳过.d文件,并直接依赖于目录,将不起作用,因为每次在该目录中写入文件时,目录修改时间都会更新,这将在每次调用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)
OBJDIR:=OBJDIR
OBJS:=$(addprefix$(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o:%.c
$(COMPILE.c)$(输出选项)$<
全部:$(OBJS)
$(OBJS):|$(OBJDIR)
$(OBJDIR):
mkdir-p$(OBJDIR)
您应该在这里看到| pipe操作符的用法,它定义了一个仅限订单的先决条件。
这意味着为了构建当前目标,$(OBJDIR)
目标应该存在(而不是最近的)
请注意,我使用了mkdir-p
。与文档示例相比,添加了-p
标志。
请参阅其他答案以了解另一种选择。它在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
这应该不会在并行模式中造成竞争危险-但我还没有测试它以确定。这也有在Windows上工作的优点。别忘了命令前面的“-”,这样make就不会保释了。啊,谢谢,我正试着让这样的东西起作用。我不想在几个目标上使用“test-d foo | | mkdir foo”,因为使用“make-j2”会同时测试它们,两个测试都给出false,然后两个进程会尝试mkdir,最后一个失败。这肯定是解决这个问题的官方方法。@CraigMcQueen:我真正的意思是“应该存在
$(OBJDIR)
目标”。检查文件是否存在(以及时间戳),以确定是否需要构建目标。因此,在这里,如果$(OBJDIR)
不存在,它将构建它,这样它就存在,以便构建将在内部创建的当前目标$(OBJS)
(我正在尝试在windows/linux之间生成尽可能通用的makefiles)-这几乎是我唯一可以使用的makefiles,但它工作得很好!:)“一般来说,坚持广泛支持的(通常是posix指定的)这些程序的选项和功能。例如,不要使用“mkdir-p”,尽管它可能很方便,因为一些系统根本不支持它,与其他系统一起,并行执行是不安全的。“-p
在Windows上不工作,这大概就是问题所在。不知道这是怎么被接受的。对于Windows,请投票:如果你在MinGW外壳之外使用GNU Make,你可能做错了什么。不过,这是您的选择。如果您需要makefiles在Windows(使用gnuwin32和PowerShell)和POSIX兼容操作系统中工作,这是首选的方法。前提是您有gnuwin32 CoreUtils包来提供“测试”实用程序。这里已经很晚了,但我想指出,在并行构建时,此解决方案可能会中断(make-j
)由于测试目录是否存在与创建目录之间存在竞争条件。一个作业可以测试它是否不存在,但在创建它之前,另一个作业会创建目录。然后,当第一个尝试创建它时,它将失败,因为目录已经存在。在这种情况下,最好的解决方案是使用@TeKa的答案(应该是公认的答案)中提到的仅限订单的先决条件。@MarcusJ在我的OS X El Capitan上工作。哪个版本打破了它?@C0deH4cker-原谅我的无知。。。哪个答案是TeKa?我认为TeKa在你发表评论后更改了他的/她的名字。这对mingw的make很有效,不需要额外的工具。这一个适用于Windows。/bin/sh:1:语法错误:文件结尾意外(应为“then”)
第一个版本适用于Windows,第二个选项适用于Linux,正如@checksum所说的,第一个是Windows,版本不是原子的,因此当另一个进程(例如,并行模式下的规则)在“不存在”和“mkdir”之间创建目录时,版本不起作用。
something_needs_directory_xxx : xxx/..
%/.. : ;@mkdir -p $(@D)
mkdir 2>/dev/null || true