2008-09-19 17 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測試它是肯定的。

相關問題