Ubuntu gnumake的奇怪重定向问题

Ubuntu gnumake的奇怪重定向问题,ubuntu,makefile,gnu-make,Ubuntu,Makefile,Gnu Make,我有一个生成makefile的系统,它在MacOSX下运行得非常好。当我在Linux下运行它时,我遇到了一个奇怪的问题。我设法将makefile简化为一个非常简单的示例: compile: gcc -o prog *.c &> compile__ chm: chmod u=rwx,g=rwx,o= prog both0: gcc -o prog *.c &> compile__ ; \ chmod u=rwx,

我有一个生成makefile的系统,它在MacOSX下运行得非常好。当我在Linux下运行它时,我遇到了一个奇怪的问题。我设法将makefile简化为一个非常简单的示例:

compile: gcc -o prog *.c &> compile__ chm: chmod u=rwx,g=rwx,o= prog both0: gcc -o prog *.c &> compile__ ; \ chmod u=rwx,g=rwx,o= prog both1: gcc -o prog *.c ; \ chmod u=rwx,g=rwx,o= prog 汇编: gcc-o prog*.c&>编译__ chm: chmod u=rwx,g=rwx,o=prog 两者都是: gcc-o prog*.c&>编译\ chmod u=rwx,g=rwx,o=prog 两者1: gcc-o prog*.c\ chmod u=rwx,g=rwx,o=prog 其思想是编译一个文件,然后更改其权限。如果我执行命令序列:

make compile make chm 编 制造chm 一切正常。但是,如果我执行:

make both0 make both1 使两者同时发生 我得到的信息是:

chmod: cannot access `prog': No such file or directory chmod:无法访问“prog”:没有这样的文件或目录 并且权限不会更改。另一方面,如果我执行:

make both0 make both1 使两者同时发生 权限已正确更改。唯一的区别是在both0下的重定向“&>compile_uuu”,我为both1删除了该重定向

有什么想法吗

&> compile__
不是可移植的重定向。在bash中,它重定向标准错误和标准输出,我认为这是您的意图。其他贝壳可能会用它做不同的事情。特别是,破折号将命令设置为背景(即
&
),并重定向标准输出(即
>编译\
)。
chmod
在编译完成并创建
prog
之前执行。使用
cc-oprog*.c>compile\uuuu2>&1
可移植地重定向标准错误和标准输出


(为什么它在mac上工作?可能是一个不同的shell,它以不同的方式解释
&>
,可能是编译器更早地打开文件,可能是竞争条件稍微不同。)

另一个解决方案是指定GNU
make
要使用的shell。手册的第二部分提供了这方面的信息。例如,以下

export SHELL=`which bash`
在一个Makefile中,似乎让Ubuntu/Debian上的Gnu Make 3.8.1选择bash作为shell


其他问题是所有shell内置的行为差异,如
echo
printf
测试
,等等。当在基于Debian的系统上运行
make
时,这些内置的神秘选项可能会神秘地失败。

我忘了提到我在Ubuntu Linux下运行gnumake 3.81版。适用于我:CentOS 5.4版(最终版);GNU Make 3.81;gcc(gcc)4.1.2 20080704(红帽4.1.2-46);你好,c;我在另一个Linux上测试了它:FedoraRelease9(Sulfur)和相同的GNUmake3.81。没问题!这似乎只发生在我的安装下:Ubuntu 10.04.2 LTS,内核2.6.32-30。在bash中,
&>
'将stdout和stderr重定向到同一个文件;它没有背景效果。我测试的三个系统(Mac OS、Fedora和Ubuntu)使用相同的GNU Bash,因此它们的行为不应该不同。Make使用系统的/bin/sh,可能不是Bash。Ubuntu系统通常使用“dash”来表示/bin/sh。dash确实在后台运行,并运行一个空命令重定向到“compile_uuuuu”@Tsf:humble me,然后尝试将其切换到“>compile_uuuu2>&1”,这是执行重定向的标准方式。@Tsf:不同的shell支持不同的语法。您的用户shell无疑是bash,它支持这种语法。Make(无论如何,默认情况下)使用系统shell,它在Ubuntu中似乎不支持这种语法。bash支持的语法是“正确的”,而其他shell不支持的语法是“不正确的”。可以肯定的是,这种语法是“非标准的”。这一点语法并不在原始的Bourne Shell中,而是来自csh。嗯,
&
做了,bash也添加了
&>
——它不太受广泛支持,我不知道为什么bash手册会推荐它。@Tsf:不,不推荐,但是当只有一个命令执行时,很难看出区别。该命令将自身设置为背景,并且不会重定向标准错误。当background是规则中唯一的命令时,它并不重要,您可以直接从命令行调用它——它最终会完成。当某些其他命令依赖于此输出时,问题就会出现,或者是在同一规则中(您是如何注意到的),或者是在另一规则中。