(makeドキュメントの文脈で)サブシェルとは何ですか?

(makeドキュメントの文脈で)サブシェルとは何ですか?

この命令に関する本を読んでいますが、makeその中に次の段落があります。

前提条件に関連する規則がある場合は、まずその規則を更新してみてください。次に、ターゲットファイルを考えます。前提条件がターゲットよりも最新の場合は、コマンドを実行してターゲットを再生成します。各コマンドラインはシェルに渡され、独自のサブシェルで実行されます。

そこで使用されるサブシェルの概念と、そのようなサブシェルを使用する理由を説明できますか?

ベストアンサー1

make(1)シェルコマンド自体を実行する方法がわかりません。この方法で行うこともできますが、Unixのアプローチは懸念をすばやく分離することです。つまり、make(1)何をすべきかを決定するために依存関係グラフを作成する方法を知り、sh(1)コマンドを実行する方法を知る必要があります。

作成者が言うべき点は、ファイルシステムを介している場合を除いて、後者のコマンドラインが前のコマンドラインに依存するようにコマンドラインを作成できないことです。たとえば、次は機能しません。

sometarget: some.x list.y of-dependencies.z
    foo=`run-some-command-here`
    run-some-other-command $$foo

これが2行のシェルスクリプトである場合、最初のコマンドの出力は2番目のコマンドの引数として渡されます。ただし、各コマンドは別々のサブシェルで実行されるため、最初のサブシェルが$foo存在すると変数の値が失われるため、最初のサブシェルに渡すことはありません。

前述のように、この問題を解決する1つの方法はファイルシステムを使用することです。

TMPDIR=/tmp
TMPFILE=$(TMPDIR)/example.tmp
sometarget: some.x list.y of-dependencies.z
    run-some-command-here > $(TMPFILE)
    run-some-other-command `cat $(TMPFILE)`

2番目のコマンドが値をロードできるように、最初のコマンドの出力を永続的な場所に保存します。

時々初心者を混乱させるもう1つのことmake(1)は、シェルスクリプトで読みやすくするために、通常は複数行に分割される構成を1行に書き込む必要があることです。または、Makefile.loopにある場合、これの良い例は機能しません。 :

someutilitytarget:
    for f in *.c
    do
        munch-on $f
    done

すべてを1行に入れるには、セミコロンを使用する必要があります。

someutilitytarget:
    for f in *.c ; do munch-on $f ; done

私自身の場合は、これを実行して、コマンドラインが約80文字を超えるたびに読み取れるように外部シェルスクリプトに移動します。

おすすめ記事