2016-07-21 5 views
3

私はあなたがこのような前提条件なし、とのルールのパターン固有の変数を定義することができることを理解しています。これはGNU Make documentationに明記されています。しかし、このようにあなたは、パターンの前提条件が含まれているパターンルールのパターン固有の変数を定義しない方法:パターン化された前提条件を含むメイクファイルパターンルールにパターン固有の変数を定義するにはどうすればよいですか?これは、変数<code>var</code>の.oで終わるすべてのターゲットに適用されたレシピのために2を設定します</p> <pre><code>%.o: var = 2 </code></pre> <p>:

%.o: %.c 

私はメイクファイルのこのセクションを持っていると言う:

%.o: %.c 
    (recipe here) 

%.o: %.b 
    (recipe here) 

私はパターンを定義したいです%.o: %.bルールのための特定の変数ですが、(それが可能な場合でも)それを行う方法はわかりません。私はこのようなことをしたいと思いますが、もちろん動作しません。

%.o: %.c 
    (recipe here) 

%.o: %.b: var = 2 
    (recipe here) 

これを行う方法はありますか?

答えて

1

ターゲットの変数は、ルールではなく、でのみ設定できます。 %.o: %bは、%.oがターゲットパターン(したがって、「パターン固有の名前」)であるルールです。

これを解決する通常の方法は、レシピ内の値をエーテルでハードコーディングすること、またはルール固有のフラグを使用することです(場合によってはCVARBVAR)。

編集:傷があります。回避策を思いついた。

これは、変数の再帰的評価を利用することによって実行できます。

all: a.o b.o c.o 

$(shell touch a.xx b.yy c.zz) 

## 
# Create rule-specific variable... rules 
# 
# @param 1 Target. 
# @param 2 Prerequisite. 
# @param 3 Variable name. 
# @param 4 Variable value. 
# 
rule-var = $(eval $(rule-var-body)) 
define rule-var-body 
$1: private $3 = $$(if $$(<:$2=),$(or $(value rule-var-$1-$3),$(value $3)),$4) 
$2: $3 = $4 
rule-var-$1-$3 = $$(if $$(<:$2=),$(or $(value rule-var-$1-$3),$(value $3)),$4) 
endef 

VAR = $(VAR_DEFAULT) 

# Declare couple of test values 
$(call rule-var,%.o,%.x,VAR,x-value) 
$(call rule-var,%.o,%.y,VAR,y-value) 
VAR_DEFAULT := z-value 

ECHO_RULE_RECIPE = @echo -e '[email protected]: $^\t(VAR = $(VAR))' 

%.o: %.x 
    $(ECHO_RULE_RECIPE) 
%.o: %.y 
    $(ECHO_RULE_RECIPE) 
%.o: %.z 
    $(ECHO_RULE_RECIPE) 
%.x: %.xx 
    $(ECHO_RULE_RECIPE) 
%.y: %.yy 
    $(ECHO_RULE_RECIPE) 
%.z: %.zz 
    $(ECHO_RULE_RECIPE) 

出力は次のとおり

a.x: a.xx  (VAR = x-value) 
a.o: a.x  (VAR = x-value) 
b.y: b.yy  (VAR = y-value) 
b.o: b.y  (VAR = y-value) 
c.z: c.zz  (VAR = z-value) 
c.o: c.z  (VAR = z-value) 

操作の脳マクロrule-varあります。変数の前提条件に変数値をラップします。この式は、他のルール固有の値の変数でもあるrule-var-$1-$3に保存されます。

$$(if $$(<:$2=),$(or $(value rule-var-$1-$3),$(value $3)),$4)解読:

$$(if $$(<:$2=),は、それが空の文字列のパターン($2)だ置き換えることにより第一前提値($<)をテストします。

  • パターンがない一致する場合、$(or $(value rule-var-$1-$3),$(value $3))を使用しています。これは、グローバル変数シャドウイングの回避策です。あなたの例では、%.o: %.cvarが宣言されていないので、でグローバル値を使用しますが、両方のルールは同じターゲットを共有しています。両方とも値で参照され、単一の$は変数置換フェーズで式を展開します。結果はきちんとしてorが無料です。

    • 0以外の場合は$(value rule-var-$1-$3)を使用してください。これは、このターゲットと変数名のために以前に呼び出された関数です。
    • それ以外の場合は、変数のグローバル値($(value $3))を使用します。
  • それ以外の場合は、値($4)を使用してください。

残念ながら

、継承されたとき、それはprivateとして宣言し、単純な二番目のルールで固定していますので、この場合は、他の怪物が正しく展開されません。

この例では、次の3つのルールが宣言されます。

%.o: private VAR = $(if $(<:%.y=),$(if $(<:%.x=),$(VAR_DEFAULT),x-value),y-value) 
%.y: VAR = y-value 
%.x: VAR = x-value 

でも回避策に関する制限事項

、変数のグローバル対応がまだ隠されています。デフォルト値が必要な場合は、の前に割り当て、rule-varとします。グローバル値は、ルール固有の変数の一部としてコピーされますが、使用するまでは展開されません。

+0

私はこの構文に従っていますが、少し苦労しています。 $$(<:$ 2 =)、$(または値の規則-var- $ 3)、$(値$ 3))、$ 4) 'という行が私を投げています。私はそれが 'prereq1:prereq1 ='ならば、私は前にその構文を見たことがない、あるいは 'or'で始まる次の構文を見たことがないと思います。あなたはもう少し詳しく説明できますか? – smeep

+0

@smeepあなたは行き​​ます。 –

+0

あなたはあなたのことをはっきりと知っています。私はまだあなたの答えを通して私の方法を働いているが、そうしている間、私が投稿した別の解決策を見つけたかもしれない。 – smeep

0

前提条件の比較の数に応じて、読みにくくなる可能性がありますが、別の解決策が見つかりました。おそらく、それをリファクタリングする方法があります。

# Return 1 if prerequisite ends in `.c`. 
# Return 2 if prerequisite ends in `.b`. 
build-var = $(if $(filter %.c,$<),1,$(if $(filter %.b,$<),2)) 

%.o: private var = $(build-var) 
%.o: %.c 
    (recipe here) 

%.o: %.b 
    (recipe here) 

命令var = $(build-var).oで終わる任意のターゲットに対して呼び出されます。しかし、build-varが展開されている場合は、その前提条件の終わりを調べて、そのファイルの種類を確認する必要があります。

ifステートメントは、最初の引数が空でない文字列であると評価され、filterは、例では前提条件に.cが含まれている場合は空でない文字列を返します。したがって、build-var行を歩き、前提条件(自動変数$<と表示される)が.cで終わる場合は、値1を返します。それ以外の場合は、前提条件が.bで終わる場合は、値2を戻す2番目のif文を開始します。前提条件が.cまたは.bで終わらない場合、build-varはnothing(空文字列)に設定されます。

関連する問題

 関連する問題