web-dev-qa-db-ja.com

メイクファイルに 'cd'コマンドを書くにはどうすればいいですか?

たとえば、私のメイクファイルには次のようなものがあります。

all:
     cd some_directory

しかし、makeと入力したときは、echoコマンドのように、「cd some_directory」しか表示されませんでした。

296

実際にはコマンドを実行してディレクトリを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コマンドが実行されるコマンドを表示します(明示的に抑制されていない限り)。たとえ出力がなくても、それはあなたが見ているものです。

526
falstro

GNU make 3.82 から始めて、 .ONESHELL という特別なターゲットを使って、シェルの単一のインスタンス化ですべてのレシピ行を実行することができます(大胆な強調)。

  • 新しい特別なターゲット:.ONESHELLは、makeにシェルの単一インスタンスを呼び出し、それにレシピ全体を提供するように指示します、含まれている行数に関係なく。 [...]
.ONESHELL:
all:
    cd ~/some_dir
    pwd # Prints ~/some_dir if cd succeeded
72
Chnossos

これがディレクトリを扱いそして作るためのかわいいトリックです。複数行の文字列を使う代わりに "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
20
JoeS

それがそこに着いたらそれをどうしたいですか?各コマンドはサブシェル内で実行されるため、サブシェルはディレクトリを変更しますが、最終的には次のコマンドがまだ現在のディレクトリにあることになります。

GNU makeを使うと、次のようなことができます。

BIN=/bin
foo:
    $(Shell cd $(BIN); ls)
7
Nadir SOUALEM

ディレクトリを変更する

foo: 
    $(MAKE) -C mydir

multi:
    $(MAKE) -C / -C my-custom-dir   ## Equivalent to /my-custom-dir
1
jackotonye