Makefileにテキストをエコーさせて、最後の改行なしにしようとしていますが、できません。 OS Xでの動作を経験しています(Linuxではすべて期待どおりに動作します)。
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フラグが正しく認識されます。
引用についての何かがmake
を混乱させます。あなたのコードは私にとって同じように動作しますが、以下は期待どおりに機能します:
_help:
@echo -n Shouldn\'t print a newline
_
実行可能ファイルへのパスのハードコーディングも機能します。
_help:
@/bin/echo -n "Shouldn't print a newline"
_
echo
のMac OS Xマニュアルページで、シェル組み込みecho
sの存在について説明しているときに、echo
のsh(1)
はサポートしていないと述べています_-n
_オプションですが、それでも(とにかく)最初の選択肢が機能する理由を説明できません。
make
がデフォルトでコマンドを実行するためにsh
を使用していることの確認。に
_Shell = bash
help:
@echo -n "Shouldn't print a newline"
@echo -n Shouldn\'t print a newline
_
両方のエコーステートメントは同じように動作します(改行は出力されません)。したがって、この変数がない場合、bash
はsh
のふりをしますが、2つの行の評価は異なります。質問1:なぜですか?質問2:2行目は、エミュレートされたbash
sh
ではなく、ネイティブecho
echoまたは_/bin/echo
_ですか?
問題は、2つの事実のnfortunate相互作用に起因します。
まず、make
には、実行するレシピの複雑さに応じて2つの操作モードがあります。
make
は組み込みコマンドを使用してレシピを直接実行します。これがb
の場合に起こります。make
はシェルを起動してレシピを解釈および実行します。これがa
の場合に起こります。次に、make
は/bin/sh
をシェルとして使用しますが、/bin/sh
の機能はMac OS XとLinuxでは異なる方法で実装されます。
/bin/sh
の機能はbash
によって実装されます。また、Mac OS Xでは、bash
は--enable-strict-posix-default
でコンパイルされます。このフラグの結果の1つは、echo
コマンドが-n
フラグを理解しないことです。/bin/sh
の機能はdash
によって実装され、POSIX仕様に関してはそれほど厳密ではありません。したがって、フラグ-n
はecho
コマンドに実装されています。ところで、Makefile buitlin echo
コマンドは、b
のケースが常に機能する理由を説明する-n
フラグを理解します。
問題を修正するクリーンで移植可能な方法は、@echo -n
レシピを@printf
レシピに置き換えることです。
echoはbashシェルの組み込みですが、makefileから実行すると、プログラムのバージョンになります。