31

我试图让我的 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它坏了。到底发生了什么?是否使用内置回声?显然双引号的存在会改变行为,但为什么呢?

更新

正如@chepner 所发现的,/bin/echo在makefile 中使用完整路径可以正确理解-n 标志。

4

3 回答 3

30

问题来自两个事实的不幸相互作用。

首先,make根据要运行的配方的复杂性,有两种操作模式:

  • 如果命令很简单make将直接使用其内置命令运行配方。这就是你的b情况。
  • 如果命令很复杂make将生成一个 shell 来解释和运行配方。这就是你的a情况。

其次,make用作/bin/shshell,但/bin/sh在 Mac OS X 和 Linux 上实现的功能不同:

  • 在 Mac OS X 上, 的功能/bin/shbash. 同样在 Mac OS X 上,bash使用--enable-strict-posix-default. 该标志的一个后果是该echo命令不理解该-n标志。
  • 在 Linux 上, 的功能/bin/sh是由其实现的dash,相对于 POSIX 规范不那么严格。因此,该标志-necho命令中实现。

顺便说一句,Makefile buitlinecho命令理解-n标志,它解释了为什么这种b情况总是有效的。

解决问题的干净便携的方法是用食谱替换你@echo -n@printf食谱。

于 2013-01-02T11:28:29.927 回答
26

一些关于报价的东西令人困惑make。您的代码对我来说表现相同,但以下内容按预期工作:

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

硬编码可执行文件的路径也可以:

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

的 Mac OS X 手册页echo在讨论 shell 内置echos 的存在时提到echoofsh(1)不支持该-n选项,但这无法解释(无论如何对我来说)我的第一个替代方案为何有效。


make默认情况下用于sh执行命令的确认。制作手册 5.3.2 选择 Shell指定此 hehavrior:

用作 shell 的程序取自变量 SHELL。如果您的 makefile 中未设置此变量,则程序 /bin/sh 将用作 shell。传递给 shell 的参数取自变量 .SHELLFLAGS。.SHELLFLAGS 的默认值通常是 -c,或者在符合 POSIX 的模式下是 -ec。

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

两个 echo 语句的行为相同(不打印换行符)。因此,如果没有该变量,我们就bash假装是sh,但对这两行的评估方式不同。问题一:为什么?问题2:第二行是本机bash回声还是/bin/echo,而不是模拟sh echo

于 2012-07-26T18:32:53.637 回答
3

echo 是内置的 bash shell,但是当您从 makefile 运行它时,它是程序版本

于 2012-07-26T17:55:53.450 回答