2

を使用して変数が定義されているかどうかを確認しようとしていますが、実行時にエラーが発生しifndef/ifdef続けます。not found私は を使用しGNU Make 3.81ています。ここに私が持っているもののスニペットがあります:

all: _images                 
    $(call clean, .)         
    $(call compile, .)       
    @$(OPENER) *.pdf &       

_images:                     
    $(call clean, "images")  
    $(call compile, "images")

define clean                                             
    @rm -f ${1}/*.log ${1}/*.aux ${1}/*.pdf              
endef                                                    

define compile                                           

    ifdef ${1}                                           
        dir = ${1}                                       
    else                                                 
        dir = .                                          
    endif                                                

    ifdef ${2}                                           
        outdir = ${2}                                    
    else                                                 
        outdir = ${1}                                    
    endif                                                

    @$(COMPILER) -output-directory ${outdir} ${dir}/*.tex

endef                                                    

そして正確なエラー:

$ make                       
ifdef  "images"              
/bin/sh: 1: ifdef: not found 
make: *** [_images] Error 127

編集

Barmar のコメントを考慮すると、結論は次のようになります。

define の内容はシェル コマンド ラインであり、make ディレクティブではありません。定義ブロック内のコマンド内で改行するには、改行をエスケープする必要があります -- \; また、ワンライナー コマンドに対応する各ブロックは、それぞれが異なるシェル実行で個別に実行されます。つまり、次のワンライナー ブロックの変数値にアクセスすることを意図している場合、ローカル変数の定義は機能しません。

素敵な作業をしてくれたトリプルに感謝します。

4

1 に答える 1

4

シェルの機能をMakeの機能と組み合わせて、かなり簡潔な定義を取得できます。

define compile
        @dir="${1}"; outdir="${2}"; outdir=$${outdir:-"$dir"}; \
        $(COMPILER) -output-directory "$${outdir}" "$${dir:-.}/*.tex

2ドルは、1つのドル記号をシェルに渡すエスケープです。構成は、設定されていないか空でない限り${variable:-value}、の値を返します。$variable設定されていないか空の場合は、を返しますvalue${1}シェルがこの式を評価する前にとは静的文字列に置き換えられるため${2}、変数を調べる前に、変数に割り当てるという回り道をする必要があります。

これは、2つの「ワンライナー」を1つのシェル呼び出しに組み合わせる方法も示しています。セミコロンはステートメントターミネータ(基本的には改行と同等)であり、バックスラッシュと改行のシーケンスにより、次の行が現在の行とマージされて単一の「論理行」になります。

これは非常に複雑なので、先頭を省略することをお勧めします@が、それがどこに属するかを示すためだけに残しました。サイレント操作が必要な場合は、適切にデバッグしたら、を使用して実行しmake -sます。

于 2013-01-13T13:20:15.007 に答える