2016-09-26 49 views
1

我似乎在製作Makefile,列表處理和模式規則方面存在一些問題。當我的源代碼安裝在名稱包含'%'的目錄中時,它無法正確構建。我已經將它歸結爲任何人都可以運行的簡單測試案例。製作和百分號登錄路徑

我有下面的Makefile:

INSTALL_DIR=$(shell pwd)/idir 

INSTALL_TREE = 
INSTALL_TREE += $(INSTALL_DIR)/dir1 
INSTALL_TREE += $(INSTALL_DIR)/dir2 
INSTALL_TREE += $(INSTALL_DIR)/dir3 

create_tree: $(INSTALL_TREE) 
$(INSTALL_TREE): 
    mkdir -p [email protected] 

我把這個目錄中名爲Test1,當我運行它,我得到我想要的東西......在INSTALL_TREE中列出的所有目錄中創建:

% make -n 
mkdir -p /home/christopher.arguin/test/test1/idir/dir1 
mkdir -p /home/christopher.arguin/test/test1/idir/dir2 
mkdir -p /home/christopher.arguin/test/test1/idir/dir3 

現在使用完全相同的Makefile文件名爲test%2目錄,這就是我得到:

% make -n 
mkdir -p /home/christopher.arguin/test/test2%/idir/dir1 

它在第一個目錄之後停止。有趣的是,如果第一個目錄沒有%符號,他們都得到產生......,例如,

INSTALL_TREE = 
INSTALL_TREE += ./idir/dir4 
INSTALL_TREE += $(INSTALL_DIR)/dir1 
INSTALL_TREE += $(INSTALL_DIR)/dir2 
INSTALL_TREE += $(INSTALL_DIR)/dir3 

給我:

mkdir -p dir4 
mkdir -p /home/christopher.arguin/test/test2%/idir/dir1 
mkdir -p /home/christopher.arguin/test/test2%/idir/dir2 
mkdir -p /home/christopher.arguin/test/test2%/idir/dir3 

另一個有趣的事情是,文件名正確的...如果%被誤解爲前綴規則或者你可能期望有一些替換,但是如果我讓它創建目錄,它絕對是正確的。

我試過轉義%字符,但無濟於事。添加以下代碼:

PERCENT := % 
ITREE = $(subst $(PERCENT),$(PERCENT)$(PERCENT),$(INSTALL_TREE)) 
create_tree2: $(ITREE) 

$(ITREE): 
    mkdir -p [email protected] 

就產生

mkdir -p /home/christopher.arguin/test/test2%%/idir/dir1 

的替代工作,但它實際上並沒有逃脫百分號。 「$(PERCENT)」替換爲「%」,因爲文件名後面只包含了$(PERCENT)。

我發現了兩個相關的問題, Does GNU Make support '%' in a filename?How to correctly escape "%" sign when using pattern rules and patsubst in GNU make? 但那些都遭受了基本的問題,我有......我的源目錄是在我的掌握。

背景: 原因是這對我來說是一個問題,我試圖遷移到詹金斯多分支管道。當詹金斯檢測到提交時,它會根據分支的名稱創建一個工作區。如果你的分支命名約定恰好有斜線,Jenkins會做正確的事情並將它們轉換爲「%2F」。我的makefile與這些文件發生衝突。

+0

你可以做一個符號鏈接嗎? – Beta

+0

不幸的是,因爲在這種情況下,工作區的名稱由Jenkins處理。 –

+0

看起來詹金斯傢伙現在正在積極努力避免這個問題:https://issues.jenkins-ci.org/browse/JENKINS-34564 –

回答

1

含有%目標定義的圖案規則,並與多個目標圖案規則的處理是不同的:

https://www.gnu.org/software/make/manual/make.html#Pattern-Intro

模式規則可以具有多於一個的目標。與一般規則不同,這不具有許多具有相同先決條件和配方的不同規則。如果一個模式規則有多個目標,就知道規則的配方負責製作所有的目標。 該配方僅執行一次以製作所有目標。

您可以通過定義路徑規則時引用%解決這個問題。請注意,對於create_tree的依賴關係,這不是必需的,因爲這是一個常規規則,事實上,如果您這樣做,它將不起作用,因爲make會查找帶有字面值\%的目標。

INSTALL_DIR := $(abspath .)/idir 

INSTALL_TREE += $(INSTALL_DIR)/dir1 
INSTALL_TREE += $(INSTALL_DIR)/dir2 
INSTALL_TREE += $(INSTALL_DIR)/dir3 

.PHONY: create_tree 
create_tree: $(INSTALL_TREE) 
$(subst %,\%,$(INSTALL_TREE)): 
    mkdir -p [email protected] 
+0

我明白了;我曾嘗試將同樣的事情變成一個變量,但這個問題得到解釋還爲時過早。它必須直接作爲模式的一部分來完成。 –

+0

@ChrisArguin只要您僅將它用於目標,而不是您需要的路徑未引用的依賴關係時,它將作爲變量工作。 – user657267

+0

我接受了這個答案,因爲它確實解決了問題(並且似乎是解決問題的唯一方法),但在我的情況下,這將涉及重寫很多規則,因爲您無法準備字符串的轉義版本。正如Jenkins所做的那樣,Jenkins已經在做一個解決方案來完全避免這個問題,並且只是更新到本週的版本中。 –