3

リストの内容に基づいてCファイルを生成するmakefileルールがあります。

LIST = foo \
       bar

generated.c:
    @echo "Creating $@"
    (echo "#include <stuff.h>";      \
    echo "void init_local() {";      \
    for i in $(LIST) ; do            \
       echo "    init_$$i();";       \
    done;
    echo "}") > $@

Linuxプラットフォームでは、これにより、期待する結果が得られます。

#include <stuff.h>
void init_local() {
    init_foo();
    init_bar();
}

ただし、GNU Make 3.82(x86_64-w64-mingw32)を使用するWindows 7 64ビットプラットフォームで
は、次のようになります(すべて1行で)。

"#include <stuff.h>";   \"void init_local() {"  \ 
   for i in foo bar; do echo "  init_$i();"; done; echo "}"

また、個々の行のルールを破ろうとしました。

    echo "#include <stuff.h>" > %@
    echo "void init_local() {" >> $@
    ...

その解決策では、1行に1つの文字列がありますが、引用符はまだあります。

LinuxとWindowsの両方のプラットフォームで生成されたファイルを正しくするためにルールを変更するにはどうすればよいですか?

4

1 に答える 1

1

これは、DOSに独自のコマンドセパレータ- ( bashの;と同様)があるためです。ただし、DOSおよびbashで機能するシェルエコーの代わりにmakeエコーを使用することをお勧めします。

ただし、出力に引用符( "" )は必要ないことを理解しているので、これだけではありません。そのため、引用符をエコーに渡すのではなく、^で特殊記号をエスケープする必要があります。

ifeq ($(OS_TYPE),linux)
    Q="
    ESC=
else
    Q=
    ESC=^
endif

generated.c:
    @echo "Creating $@"
    echo $(Q)#include $(ESC)<stuff.h$(ESC)>$(Q) > $@ 
    echo $(Q)void init_local() {$(Q) >> $@
    ...

さらに、あなたのbash for ..; do ..; done; 両方のシェルで正しくなるように、ループをmake $(foreach、$(LIST)、echo ...)に置き換える必要があります。

はい、私は知っています、これは醜く見えますが、それは奇妙なDOSルールのためです。たくさん生成する必要がある場合は、awk、python、またはperlを使用することをお勧めします。

于 2012-11-29T21:32:57.863 に答える