web-dev-qa-db-ja.com

メイクファイル内にディレクトリが存在するかどうかをテストします

彼の answer @Grundlefleckでは、ディレクトリが存在するかどうかを確認する方法を説明しています。私は次のようにmakefile内でこれを使用しようとしました:

foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then
        echo "Dir exists"
    fi

ランニング make foo.bak (とすれば foo.barが存在する場合)次のエラーが発生します。

echo "foo"
foo
if [ -d "~/Dropbox" ]; then
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [foo.bak] Error 2

回避策は、テストが実装されているスタンドアロンのbashスクリプトを使用して、makefileからスクリプトを呼び出すことでした。ただし、これは非常に面倒です。 makefile内からディレクトリが存在するかどうかを確認するより良い方法はありますか?

51
Dror

シェルコマンドの場合、コマンドを1行にするか、ライン拡張にバックスラッシュを使用して複数行にする必要があります。したがって、このアプローチは機能します。

foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then echo "Dir exists"; fi

または

foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then \
        echo "Dir exists"; \
    fi
58
lurker

このアプローチは、最小限のエコーで機能します。

.PHONY: all
all:
ifneq ($(wildcard ~/Dropbox/.*),)
        @echo "Found ~/Dropbox."
else
        @echo "Did not find ~/Dropbox."
endif
39
cforbish

ディレクトリの不在に基づいて行動する

ディレクトリが存在しないかどうかだけを知る必要があり、ディレクトリを作成するなどしてそのディレクトリに基づいて動作する場合は、通常のMakefileターゲットを使用できます。

directory = ~/Dropbox

all: | $(directory)
    @echo "Continuation regardless of existence of ~/Dropbox"

$(directory):
    @echo "Folder $(directory) does not exist"
    mkdir -p $@

.PHONY: all

備考:

  • |は、makeがタイムスタンプを気にしないことを示します( order-only-prerequisite です)。
  • mkdir -p $@と書く代わりに、falseと書いて終了するか、別の方法でケースを解決できます。

また、ディレクトリのexistenceに対して特定の一連の命令を実行する必要がある場合は、上記を使用できません。つまり、次と同等です。

if [ ! -d "~/Dropbox" ]; then
    echo "The ~/Dropbox folder does not exist"
fi

elseステートメントはありません。

ディレクトリの存在に基づいて行動する

逆のif文が必要な場合は、これも可能です。

directory = $(wildcard ~/Dropbox)

all: | $(directory)
    @echo "Continuation regardless of existence of ~/Dropbox"

$(directory):
    @echo "Folder $(directory) exists"

.PHONY: all $(directory)

これは次と同等です:

if [ -d "~/Dropbox" ]; then
    echo "The ~/Dropbox folder does exist"
fi

繰り返しますが、elseステートメントはありません。

ディレクトリの有無に応じて行動する

これはもう少し面倒になりますが、最終的には両方の場合に素晴らしいターゲットを提供します:

directory = ~/Dropbox
dir_target = $(directory)-$(wildcard $(directory))
dir_present = $(directory)-$(directory)
dir_absent = $(directory)-

all: | $(dir_target)
    @echo "Continuation regardless of existence of ~/Dropbox"

$(dir_present):
    @echo "Folder $(directory) exists"

$(dir_absent):
    @echo "Folder $(directory) does not exist"

.PHONY: all

これは次と同等です:

if [ -d "~/Dropbox" ]; then
    echo "The ~/Dropbox folder does exist"
else
    echo "The ~/Dropbox folder does not exist"
fi

当然、ワイルドカードの展開はif-else-statementよりも遅い場合があります。ただし、3番目のケースはおそらく非常にまれであり、完全性のために追加されただけです。

21
Anne van Rossum

これを試して:

.PHONY: all
something:
    echo "hi"
all:
    test -d "Documents" && something

これは、somethingが存在する場合にのみ、Documentsの下のコマンドを実行します。

コメントに記載されている 問題 に対処するには、次のような変数を作成します。

PATH_TEST = ~/SomeDirectory

test -d $(PATH_TEST) && something
10
user1508519

Makefile上記のアプローチが機能しない場合。 here このように使用できる素敵なソリューションを見つけました:

MY_DIRNAME=../External
ifneq "$(wildcard $(MY_DIRNAME) )" ""
  # if directory MY_DIRNAME exists:
  INCLUDES += -I../External
else
  # if it doesn't:
  INCLUDES += -I$(HOME)/Code/External
endif

これは、MY_DIRNAMEに保存されているディレクトリが存在するかどうかに基づいて、変数INCLUDESを変更します。

(動機:私の場合、この変数は後で最初に含まれる別のMakefileで使用されます:

include $(SFRAME_DIR)/Makefile.common

2つの異なる環境で同じMakefileを簡単な方法で動作させたかったのです。)

9
fuenfundachtzig

1つのシェルでifステートメントを想定したとおりに使用できるようにする非常に異なる回答があります。

.ONESHELL:
foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then
        echo "Dir exists"
    fi

唯一の違いはONESHELL 特別なターゲット であることに注意してください。

1
Anne van Rossum