bash 如何在 Ubuntu 下处理 GNU Make 中的 shell 扩展?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6681624/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to handle shell expansions in GNU Make under Ubuntu?
提问by Adam Lindberg
Given this very simple Makefile:
鉴于这非常简单Makefile:
all:
@mkdir -pv test/{a,b}
I get this output on OS X 10.6.8 and CentOS 5.5:
我在 OS X 10.6.8 和 CentOS 5.5 上得到这个输出:
mkdir: created directory `test'
mkdir: created directory `test/a'
mkdir: created directory `test/b'
But on Ubuntu 11.04 I get this:
但是在 Ubuntu 11.04 上我得到了这个:
mkdir: created directory `test'
mkdir: created directory `test/{a,b}'
Running the command mkdir -pv test/{a,b}manually in the shell on all platforms gives the expected result.
mkdir -pv test/{a,b}在所有平台上的 shell 中手动运行命令会给出预期的结果。
The version of GNU Make is the same on all platforms:
GNU Make 的版本在所有平台上都是相同的:
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program is built for [PLATFORM]
What's different under Ubuntu and why doesn't the shell expansion work there?
Ubuntu 下有什么不同,为什么 shell 扩展在那里不起作用?
回答by sehe
The problem is probably that Make spawns /bin/sh. It is usually a symlink to your system's default shell.
问题可能是 Make spawns /bin/sh。它通常是系统默认 shell 的符号链接。
Option 1
选项1
You could make sure it points to bash (as this is a bashism). Probably, it is now /bin/dash or /bin/sh, depending on your version of Ubuntu.
您可以确保它指向 bash(因为这是一种 bashism)。现在可能是 /bin/dash 或 /bin/sh,具体取决于您的 Ubuntu 版本。
Option 2
选项 2
Easier option:
更简单的选择:
SHELL=/bin/bash
all:
@echo a{3,4}
@bash -c 'echo a{3,4}'
This prints the same output twice unless you comment-out the SHELL=line
这将打印两次相同的输出,除非您注释掉该SHELL=行
Option 3
选项 3
If you can't/don't want to modify the make file, you can invoke it like so:
如果您不能/不想修改 make 文件,您可以像这样调用它:
make SHELL=/bin/bash
beware of interactions with sub-makefiles or includes. You might want to look at the make -eoption and the make exportkeyword: http://www.gnu.org/s/hello/manual/make/Variables_002fRecursion.html
注意与子生成文件或包含的交互。您可能想查看make -e选项和 makeexport关键字:http: //www.gnu.org/s/hello/manual/make/Variables_002fRecursion.html
回答by David W.
It's been a long, long time since I've used Make...
我已经很久很久没有使用 Make...
There are several ways to specify a particular shell to use. The default shell for old Make was the original Bourne shell. If you wanted a different shell, you had to set it yourself.
有多种方法可以指定要使用的特定 shell。旧版 Make 的默认 shell 是原始的 Bourne shell。如果你想要一个不同的外壳,你必须自己设置。
You're using Linux and GNU, so I'll assume that you're using BASH as the default shell. Try this command in your Make:
您使用的是 Linux 和 GNU,因此我假设您使用 BASH 作为默认 shell。在你的 Make 中试试这个命令:
echo "random = $RANDOM"
If this simply prints random =and doesn't include a random number, your Make is using Bourne shell as its default shell instead of BASH. (Which is weird because I didn't think there was a real Bourne shell in Linux...) To get around this:
如果这只是打印random =并且不包含随机数,则您的 Make 正在使用 Bourne shell 作为其默认 shell 而不是 BASH。(这很奇怪,因为我认为 Linux 中没有真正的 Bourne shell ......)为了解决这个问题:
- You can add in a
SHELLmacro pointing to the BASH shell. - You can include the shell in your command.
- 您可以添加
SHELL指向 BASH shell的宏。 - 您可以在命令中包含 shell。
Instead of:
代替:
@mkdir -pv test/{a,b}
Put this:
把这个:
/bin/bash -c @mkdir -pv test/{a,b}
This specifies you want to use BASH and not the standard /bin/sh Bourne shell.
这指定您要使用 BASH 而不是标准的 /bin/sh Bourne shell。
If the echo random = $RANDOMdoes print a random number, you're using BASH (or at least Kornshell), but the BRACE EXPANSION might not be set. Try using this in your Makefile:
如果echo random = $RANDOM确实打印了一个随机数,则您使用的是 BASH(或至少是 Kornshell),但可能未设置 BRACE EXPANSION。尝试在你的 Makefile 中使用它:
set -o
And make sure braceexpandis on. It could be off when you run Make.
并确保braceexpand开启。运行 Make 时它可能会关闭。

