3

我有一个生成文件规则,它根据列表的内容生成一个 C 文件。

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 位平台上,
我得到以下信息(全部在一行上):

"#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 个字符串,但引号仍然存在!

我将如何更改规则以使生成的文件在 Linux 和 Windows 平台上都正确?

4

1 回答 1

1

这是因为 DOS 有自己的命令分隔符 - &(类似于bash 中的;)。但我建议使用 make echo 而不是在 DOS 和 bash 中工作的 shell echo:

但这还不是全部,据我所知,您不需要在输出中使用引号 ( "" ),这就是为什么您不应该将它们传递给 echo,而是使用^转义特殊符号。

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; loop 应替换为 make $(foreach, $(LIST), echo ...)以对两个 shell 都正确。

是的,我知道,这看起来很难看,但那是因为奇怪的 DOS 规则。如果你需要生成很多东西,我建议使用 awk、python 或 perl。

于 2012-11-29T21:32:57.863 回答