2016-09-26 15 views
1

私は、Makefile、リスト処理、およびパターンのルールに関して、奇妙なことをしたようです。ソースが '%'を含むディレクトリにインストールされていると、正しくビルドできません。私はそれを誰かが実行できる簡単なテストケースに煮詰めました。サインインのパスとパーセント記号

私は、次のMakefile持っている:私はTEST1というディレクトリにこれを入れて、私はそれを実行したとき、私は私が... INSTALL_TREEに記載されているすべてのディレクトリが作成されたい正確に何を得る

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] 

を:

% 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 

今テスト%2というディレクトリにまったく同じMakefileを使用しており、これは私が得るものです:

% 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 Multibranch Pipelineに移行しようとしていることです。 Jenkinsは、コミットを検出すると、ブランチの名前に基づいてワークスペースを作成します。ブランチ命名規則にスラッシュがある場合、Jenkinsは正しいことを行い、それらを "%2F"に変換します。私のメイクファイルはそれらのファイルと衝突しています。

+0

シンボリックリンクを作成できますか? – Beta

+0

悲しいことに、この場合、ワークスペースの名前はJenkinsによって処理されるためです。 –

+0

この問題を避けるためにJenkinsの人たちが積極的に取り組んでいるようです:https://issues.jenkins-ci.org/browse/JENKINS-34564 –

答えて

1

%を含むターゲットパターンルールを定義し、複数のターゲットのパターンルールは異なる方法で処理される:

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

パターンルールが複数のターゲットを有することができます。通常のルールとは異なり、これは同じ前提条件とレシピを持つ多くの異なるルールとして機能しません。パターンルールに複数のターゲットがある場合、makeはルールのレシピがすべてのターゲットを作成する責任があることを認識します。 レシピはすべてのターゲットを作成するために1回だけ実行されます。

これは、パスルールを定義するときに%を引用することで解決できます。これは通常の規則である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はこの問題を完全に回避するために既に回避策を講じていましたが、今週のバージョンに更新するだけで問題は解決しました。 –

関連する問題