たとえば、私のメイクファイルには次のようなものがあります。
all:
cd some_directory
しかし、make
と入力したときは、echo
コマンドのように、「cd some_directory」しか表示されませんでした。
実際にはコマンドを実行してディレクトリをsome_directory
に変更しますが、これはサブプロセスShellで実行され、makeや作業しているShellには影響しません。
some_directory
内でさらにタスクを実行したい場合は、セミコロンを追加し、他のコマンドも追加する必要があります。改行は、makeの最後尾として解釈されるので使用できません。そのため、明確にするために使用する改行は、バックスラッシュでエスケープする必要があります。
例えば:
all:
cd some_dir; echo "I'm in some_dir"; \
gcc -Wall -o myTest myTest.c
バックスラッシュと改行を追加しても、各コマンドの間にセミコロンが必要であることにも注意してください。これは、文字列全体がシェルによって単一行として解析されるためです。コメントで述べたように、コマンドを結合するには '&&'を使用する必要があります。つまり、前のコマンドが成功した場合にのみコマンドが実行されます。
all:
cd some_dir && echo "I'm in some_dir" && \
gcc -Wall -o myTest myTest.c
何らかの理由でcd
が失敗した場合、クリーンアップなどの破壊的な作業を行うときには、これは特に重要です。
ただし、一般的な使い方はサブディレクトリでmakeを呼び出すことです。これを調べるとよいでしょう。これにはコマンドラインオプションがあるので、cd
を自分で呼び出す必要はないので、ルールは次のようになります。
all:
$(MAKE) -C some_dir all
これはsome_dir
に変わり、そこでターゲット "all"を指定してMakefile
を実行します。正しいmakeインスタンスを呼び出すように注意してください(たとえば、ビルド環境に特殊なmakeバージョンを使用する場合)、ベストプラクティスとして、make
を直接呼び出すのではなく$(MAKE)
を使用し、動作を少し変えます。 -t
などの特定のスイッチを使用して実行しているとき。
レコードについては、make alwaysコマンドが実行されるコマンドを表示します(明示的に抑制されていない限り)。たとえ出力がなくても、それはあなたが見ているものです。
GNU make 3.82
から始めて、 .ONESHELL
という特別なターゲットを使って、シェルの単一のインスタンス化ですべてのレシピ行を実行することができます(大胆な強調)。
- 新しい特別なターゲット:
.ONESHELL
は、makeにシェルの単一インスタンスを呼び出し、それにレシピ全体を提供するように指示します、含まれている行数に関係なく。 [...]
.ONESHELL:
all:
cd ~/some_dir
pwd # Prints ~/some_dir if cd succeeded
これがディレクトリを扱いそして作るためのかわいいトリックです。複数行の文字列を使う代わりに "cd;"各コマンドで、次のように単純なchdir関数を定義します。
CHDIR_Shell := $(Shell)
define chdir
$(eval _D=$(firstword $(1) $(@D)))
$(info $(MAKE): cd $(_D)) $(eval Shell = cd $(_D); $(CHDIR_Shell))
endef
それから、あなたがしなければならないのは、そのようにあなたの規則の中でそれを呼ぶことです:
all:
$(call chdir,some_dir)
echo "I'm now always in some_dir"
gcc -Wall -o myTest myTest.c
次のこともできます。
some_dir/myTest:
$(call chdir)
echo "I'm now always in some_dir"
gcc -Wall -o myTest myTest.c
それがそこに着いたらそれをどうしたいですか?各コマンドはサブシェル内で実行されるため、サブシェルはディレクトリを変更しますが、最終的には次のコマンドがまだ現在のディレクトリにあることになります。
GNU makeを使うと、次のようなことができます。
BIN=/bin
foo:
$(Shell cd $(BIN); ls)
ディレクトリを変更する
foo:
$(MAKE) -C mydir
multi:
$(MAKE) -C / -C my-custom-dir ## Equivalent to /my-custom-dir