我试图让我的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所发现的那样,使用makefile中/bin/echo
的完整路径正确理解-n标志。
答案 0 :(得分:23)
问题来自两个事实的不幸互动。
首先,make
有两种操作模式,具体取决于要运行的配方的复杂程度:
make
将使用其内置命令直接运行配方。这就是b
案例中发生的情况。make
将生成一个shell来解释并运行配方。这就是a
案例中发生的情况。其次,make
使用/bin/sh
作为shell,但/bin/sh
的功能在Mac OS X和Linux上的实现方式不同:
/bin/sh
的功能由bash
实现。同样在Mac OS X上,bash
使用--enable-strict-posix-default
进行编译。此标志的一个结果是echo
命令无法理解-n
标志。/bin/sh
的功能由dash
实现,对于POSIX规范不太严格。因此,标志-n
在echo
命令中实现。 BTW,Makefile buitlin echo
命令理解-n
标志,这解释了b
案例始终有效的原因。
解决问题的简便方法是用@echo -n
食谱替换@printf
食谱。
答案 1 :(得分:18)
关于引号的一些内容会使make
混淆。您的代码对我来说行为相同,但以下工作符合预期:
help:
@echo -n Shouldn\'t print a newline
硬编码可执行文件的路径也可以:
help:
@/bin/echo -n "Shouldn't print a newline"
echo
的Mac OS X手册页,在讨论shell内置echo
的存在时,提到echo
的{{1}}不支持sh(1)
选项,但无法解释(无论如何)为什么我的第一个替代方案有效。
确认-n
默认使用make
执行命令。在
sh
两个echo语句表现相同(没有打印换行符)。因此,如果没有该变量,我们假装SHELL = bash
help:
@echo -n "Shouldn't print a newline"
@echo -n Shouldn\'t print a newline
为bash
,但对这两行进行了不同的评估。问题1:为什么?问题2:第二行是原生sh
回音还是bash
,而不是模拟的/bin/echo
sh
?
答案 2 :(得分:3)
echo是内置的bash shell,但是当你从makefile运行它时,它是程序版本