Makefile `echo -n' 不工作
Posted
技术标签:
【中文标题】Makefile `echo -n\' 不工作【英文标题】:Makefile `echo -n' not workingMakefile `echo -n' 不工作 【发布时间】:2012-07-25 09:07:45 【问题描述】:我试图让我的 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 标志。
【问题讨论】:
【参考方案1】:引号中的某些内容使make
感到困惑。您的代码对我来说表现相同,但以下代码按预期工作:
help:
@echo -n Shouldn\'t print a newline
硬编码可执行文件的路径也可以:
help:
@/bin/echo -n "Shouldn't print a newline"
echo
的 Mac OS X 手册页在讨论 shell 内置 echo
s 的存在时,提到 sh(1)
的 echo
不支持 -n
选项,但失败了解释(对我来说,无论如何)为什么我的第一个替代方案有效。
确认make
默认使用sh
执行命令。 Make manual 5.3.2 Choosing the Shell 指定此行为:
用作shell的程序取自变量SHELL。如果 此变量未在您的 makefile 中设置,使用程序 /bin/sh 作为外壳。传递给 shell 的参数取自 变量.SHELLFLAGS。 .SHELLFLAGS 的默认值通常是 -c, 或 -ec 符合 POSIX 的模式。
在
SHELL = bash
help:
@echo -n "Shouldn't print a newline"
@echo -n Shouldn\'t print a newline
两个 echo 语句的行为相同(不打印换行符)。所以没有那个变量,我们有bash
伪装成sh
,但对这两行的评估不同。问题一:为什么?问题二:第二行是原生的bash
echo还是/bin/echo
,而不是模拟的sh
echo
?
【讨论】:
实际上,我刚刚意识到这一点,并正在改变我的问题以反映它。但是为什么make
会感到困惑......我怎么能明确告诉 make
我想将 -n 标志传递给 echo(没有明确的路径?) make 使用某种内置的 echo 吗?
整个配方使用$SHELL
指定的shell 执行,如果未设置该变量,则使用/bin/sh
。所以通常情况下,如果有问题的 shell 有一个内置的,除非路径是硬编码的,否则它将使用它。这里奇怪的是,尽管$SHELL
被设置为'/usr/local/bin/bash'(无论如何对我来说),问题行似乎是使用sh
内置执行的,而不是bash
内置。
我之前遇到了 -e
标志的问题,所以所有标志都因为一些奇怪的原因而造成混淆......【参考方案2】:
问题来自两个事实的不幸交互。
首先,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
标志。
在 Linux 上,/bin/sh
的功能由 dash
实现,这在 POSIX 规范方面不太严格。因此,-n
标志在 echo
命令中实现。
顺便说一句,Makefile buitlin echo
命令理解 -n
标志,这解释了为什么 b
案例始终有效。
解决问题的简洁和便携的方法是将@echo -n
食谱替换为@printf
食谱。
【讨论】:
有点相关:至少在 Mac Lion 10.7 上,root 的默认 shell 是 /bin/sh 而不是 /bin/bash。最好使用 'chsh' 命令将其更改为 /bin/bash(无需参数),以便 'echo -n' 在 .bashrc 等中工作。【参考方案3】:echo 是一个内置的 bash shell,但是当你从 makefile 运行它时,它是程序版本
【讨论】:
-n
被内置程序和独立程序支持。
程序版本(/bin/echo)实际上支持-n,所以如果Makefile使用/bin/echo,它会正常工作。以上是关于Makefile `echo -n' 不工作的主要内容,如果未能解决你的问题,请参考以下文章
Makefile 问题:错误 127、255,在 makefile 中运行程序