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 内置 echos 的存在时,提到 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,但对这两行的评估不同。问题一:为什么?问题二:第二行是原生的bashecho还是/bin/echo,而不是模拟的shecho

【讨论】:

实际上,我刚刚意识到这一点,并正在改变我的问题以反映它。但是为什么 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 上的实现方式不同:

在 Mac OS X 上,/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工作方式

Makefile 问题:错误 127、255,在 makefile 中运行程序

从另一个makefile在Makefile中追加/替换字符串

4.Makefile工程管理

Makefile相关知识

Make:变量赋值