2011-03-04 116 views
8

我有一個makefile完成通常的目錄的創建:gnu make:當mkdir -p不可用時如何在makefile中創建一個目錄?

$(Release_target_OBJDIR)/%.o: %.cpp 
    mkdir -p $(dir [email protected]) 
    $(COMPILE.cpp) $< $(CFLAGS) $(INCLUDES) -o [email protected] 

不幸的是,當我運行此下scratchbox2 -p命令的mkdir總是默默地失敗。

我嘗試下面的雜牌組裝電腦不工作:

$(Release_target_OBJDIR)/%.o: %.cpp 
    mkdir $(dir $(dir $(dir [email protected]))) 
    mkdir $(dir $(dir [email protected])) 
    mkdir $(dir [email protected]) 
    $(COMPILE.cpp) $< $(CFLAGS) $(INCLUDES) -o [email protected] 

此輸出:

的mkdir -p /家庭/富/項目/ HTC/ARM/OBJ/CBAR /發行/
的mkdir -p /家庭/富/項目/ HTC/ARM/OBJ/CBAR /發行/
的mkdir -p /家庭/富/項目/ HTC/ARM/OBJ/CBAR /發行/

...尾部的斜線可防止dir函數剝離最後的目錄以我想要的方式。

寫一個腳本或小的C應用程序來複制「-p」功能的缺點,沒有人有任何想法創建的Makefile子目錄?

沒有-p選項當makefile嘗試創建一個已經存在的目錄時,mkdir將會報錯。我可以做mkdir等2/dev/null,但我冒着失去其他錯誤信息的風險。

有沒有人有任何想法,爲什麼mkdir -p不能在scratchbox2下工作?

編輯基於由bobbogo建議我把這個一起

。它看起來相當複雜,但似乎工作,即使在scratchbox2。

# Generic variables for use in functions 
comma:= , 
empty:= 
space:= $(empty) $(empty) 

# Make directory function 
forlooprange = $(wordlist 1,$(words $1),1 2 3 4 5 6 7 8 9 10) 
forloop = $(foreach n,$(call forlooprange,$1),$(call $2,$n,$3)) 
mkdirfunc0 = test -d $1 || mkdir $1; 
mkdirfunc1 = $(call mkdirfunc0,/$(subst $(space),/,$(foreach n,$(wordlist 1,$1,$2),$n))) 
mkdirfunc2 = $(call forloop,$1,mkdirfunc1,$1) 
mkdirmain = $(call mkdirfunc2,$(subst /, ,$1)) 

.PRECIOUS: %/.sentinel 
%/.sentinel: 
    $(call mkdirmain,$*) 
    touch [email protected] 

回答

4

你可以用您的森林替換您的mkdir s:

$(Release_target_OBJDIR)/%.o: %.cpp 
    $(foreach d,$(subst /, ,${@D}),mkdir $d && cd $d &&): 
    ∶ 

這將創建一個像這樣的shell命令:

mkdir projects && cd projects && mkdir htc && cd htc && mkdir arm && cd arm && : 

這適用於每次編譯。不是很優雅。你可以通過使用某種標識文件來優化這個。例如:

$(Release_target_OBJDIR)/%.o: %.cpp ${Release_target_OBJDIR}/.sentinel 
    ∶ 

%/.sentinel: 
    $(foreach d,$(subst /, ,$*),mkdir $d && cd $d &&): 
    touch [email protected] 

.sentinel被所有對象之前創建一次,並且是make -j友好。事實上,即使mkdir -p適用於您,您也應該這樣做(在這種情況下,您將使用mkdir -p而不是$(foreach) hack 解決方案)。

+0

感謝您的支持。一件奇怪的事情是:我在鏈接階段以及編譯階段添加了一個標記,以創建輸出目錄。這(以某種方式)觸發了make文件爲這些標記生成rm命令,但不是編譯時的命令。我添加了一個「觸摸」的哨兵規則來創建哨兵。 shell命令不太正確,但是您已經提供了足夠的信息來完成某些任務。 – 2011-03-04 14:18:53

+0

@Simon:是的,我添加了「touch」,以免我看起來不太傻。 TVM。 – bobbogo 2011-03-04 14:26:35

+0

@Simon:您可能需要'.PRECIOUS'和'.SECONDARY'的組合。你也可以把哨兵模式規則變成靜態模式規則(yay!)。 – bobbogo 2011-03-04 14:30:37

0

有一個更簡單的方法。您可以撥打的mkdir這樣的外殼函數內部:

 
foobar: 
     $(shell mkdir -p mydirectoryname) 

在GNU化妝的shell功能shell命令字shell後執行命令。

+0

如果'mkdir -p'不是*可用,那麼爲什麼GNU make的'$(shell ...)'可用? – jww 2018-02-05 10:47:52