web-dev-qa-db-ja.com

Makefile `echo -n 'が機能しない

Makefileにテキストをエコーさせて、最後の改行なしにしようとしていますが、できません。 OS Xでの動作を経験しています(Linuxではすべて期待どおりに動作します)。

Makefile

a:
    @echo -n "hello"

b:
    @echo -n hello

c:
    @/bin/echo -n "hello"

出力:

$make a
-n hello
$make b
hello$make c
hello$

つまり、make aが壊れています。正確には何が起こっていますか? makeは組み込みのエコーを使用していますか?明らかに二重引用符が存在すると動作が変わりますが、なぜですか?

更新

@chepnerが発見したように、makefileで/bin/echoへの完全パスを使用すると、-nフラグが正しく認識されます。

27
Chris

引用についての何かがmakeを混乱させます。あなたのコードは私にとって同じように動作しますが、以下は期待どおりに機能します:

_help:
        @echo -n Shouldn\'t print a newline
_

実行可能ファイルへのパスのハードコーディングも機能します。

_help:
        @/bin/echo -n "Shouldn't print a newline"
_

echoのMac OS Xマニュアルページで、シェル組み込みechosの存在について説明しているときに、echosh(1)はサポートしていないと述べています_-n_オプションですが、それでも(とにかく)最初の選択肢が機能する理由を説明できません。


makeがデフォルトでコマンドを実行するためにshを使用していることの確認。に

_Shell = bash
help:
        @echo -n "Shouldn't print a newline"
        @echo -n Shouldn\'t print a newline
_

両方のエコーステートメントは同じように動作します(改行は出力されません)。したがって、この変数がない場合、bashshのふりをしますが、2つの行の評価は異なります。質問1:なぜですか?質問2:2行目は、エミュレートされたbashshではなく、ネイティブecho echoまたは_/bin/echo_ですか?

18
chepner

問題は、2つの事実のnfortunate相互作用に起因します。

まず、makeには、実行するレシピの複雑さに応じて2つの操作モードがあります。

  • コマンドがeasyの場合、makeは組み込みコマンドを使用してレシピを直接実行します。これがbの場合に起こります。
  • コマンドがcomplexの場合、makeはシェルを起動してレシピを解釈および実行します。これがaの場合に起こります。

次に、make/bin/shをシェルとして使用しますが、/bin/shの機能はMac OS XとLinuxでは異なる方法で実装されます。

  • Mac OS Xでは、/bin/shの機能はbashによって実装されます。また、Mac OS Xでは、bash--enable-strict-posix-defaultでコンパイルされます。このフラグの結果の1つは、echoコマンドが-nフラグを理解しないことです。
  • Linuxでは、/bin/shの機能はdashによって実装され、POSIX仕様に関してはそれほど厳密ではありません。したがって、フラグ-nechoコマンドに実装されています。

ところで、Makefile buitlin echoコマンドは、bのケースが常に機能する理由を説明する-nフラグを理解します。

問題を修正するクリーンで移植可能な方法は、@echo -nレシピを@printfレシピに置き換えることです。

24

echoはbashシェルの組み込みですが、makefileから実行すると、プログラムのバージョンになります。

3
pizza