C “不能禁用”;“违约”;后缀规则,在Gnu Make中

C “不能禁用”;“违约”;后缀规则,在Gnu Make中,c,gcc,makefile,gnu-make,C,Gcc,Makefile,Gnu Make,我的Makefile如下所示: 执行,我得到: 为什么不能禁用后缀规则?定义的先决条件。后缀将添加到已知后缀列表中。它不会删除已知的后缀。作为一种例外情况,如果为后缀定义规则时没有先决条件,则会取消所有隐式规则: $ cat Makefile .SUFFIXES: foo.c: touch $@ $ rm -f foo.* ; make foo.o make: *** No rule to make target `foo.o'. Stop. 注意:要仅取消从.c生成.o的隐

我的Makefile如下所示:


执行,我得到:



为什么不能禁用后缀规则?

定义
的先决条件。后缀将添加到已知后缀列表中。它不会删除已知的后缀。作为一种例外情况,如果为
后缀定义规则时没有先决条件,则会取消所有隐式规则:

$ cat Makefile
.SUFFIXES:
foo.c:
    touch $@
$ rm -f foo.* ; make foo.o
make: *** No rule to make target `foo.o'.  Stop.
注意:要仅取消从
.c
生成
.o
的隐式规则,还可以添加不带配方的模式规则:

%.o: %.c
关于
MAKEFLAGS
,根据文档,它的主要用途似乎是将选项传递给子make。然而,文件还指出:

您还可以在makefile中设置MAKEFLAGS,以指定也应该对该makefile生效的其他标志

因此,从逻辑上讲,在makefile中定义
MAKEFLAGS=-r
应该与调用
make-r
具有相同的效果。这是你所期望的行为。显然,情况并非如此(GNU make版本3.81和3.82):

以及:

$rm-f foo.*;制作——版本;做foo.o
GNU Make 3.82
为i686 pc linux gnu构建
版权所有(C)2010免费软件基金会。
许可证GPLv3+:GNU GPL版本3或更高版本
这是自由软件:您可以自由更改和重新发布它。
在法律允许的范围内,不存在任何担保。
触摸foo.c
cc-c-o foo.o foo.c
但它与GNU make 4.0和4.1兼容:

$ rm -f foo.* ; make --version ; make foo.o
GNU Make 4.0
Built for i686-pc-linux-gnu
Copyright (C) 1988-2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
make: *** No rule to make target 'foo.o'.  Stop.
$rm-f foo.*;制作——版本;做foo.o
GNU Make 4.0
为i686 pc linux gnu构建
版权所有(C)1988年至2013年自由软件基金会。
许可证GPLv3+:GNU GPL版本3或更高版本
这是自由软件:您可以自由更改和重新发布它。
在法律允许的范围内,不存在任何担保。
make:**没有将目标设置为“foo.o”的规则。停止
以及:

$rm-f foo.*;制作——版本;做foo.o
GNU Make 4.1
为i686 pc linux gnu构建
版权所有(C)1988年至2014年自由软件基金会。
许可证GPLv3+:GNU GPL版本3或更高版本
这是自由软件:您可以自由更改和重新发布它。
在法律允许的范围内,不存在任何担保。
make:**没有将目标设置为“foo.o”的规则。停止

显然,该错误已被修复。

问题在于添加
-r
标志只会删除默认的后缀规则设置。当您使用
.suffix:foo
时,您正在向现有设置添加新的后缀规则。执行此操作后,
.suffix
的值不再与默认值相同,因此添加
-r
标志不会改变它。如果您想将其归档,则可以将其视为有用的增强请求

如果您想使用新的后缀规则,而不是任何预定义的规则,您可以使用永久可用的方法,甚至是POSIX标准所要求的方法;首先删除所有现有的,然后添加新的:

.SUFFIXES:
.SUFFIXES: foo

make-r
;它先读取默认规则,然后再读取makefile,以发现它不应该读取默认规则。@这仅适用于Gnu Make的旧版本。现代版本也允许Makefile级别的语法。现在我们需要定义古代和现代。“我上一次研究这类问题大概是在1993年,所以它可能是非常古老的。”JonathanLeffler 4.0及更高版本。这是非常新的。例如,许多系统仍在使用3.8x。可能是较旧的版本,但仍在使用中。不幸的是,这是不正确的。是的,您可以这样或那样做。但是,一个选项是:
MAKEFLAGS=-r
。然而,事实证明,它只在某些时候起作用。可能吧。make文档解释了如何使用
MAKEFLAGS
将选项传递给子make。这是它的主要用途。它还指出,您也可以在makefile中设置MAKEFLAGS,以指定也应该对该makefile有效的其他标志,但是,您是对的,这不适用于
-r
。也许我们应该报告一些文档错误。您的错误报告在4.0中已“修复”。然而,我的问题表明“修复”仍然需要另一个修复。有趣。显然,
后缀
目标、
MAKEFLAGS
变量和
all.o
目标以奇怪的方式交互。根据您是否声明它们(8个组合,当
all.o
目标未定义时,键入
make
而不是
make
),您将得到
all.o
构建,
make:all.o无需执行任何操作。
make:**无规则将目标设置为“all.o”。停止。
$ cat Makefile
MAKEFLAGS += -r
foo.c:
    touch $@
$ rm -f foo.* ; make --version ; make foo.o
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 built for i686-pc-linux-gnu
touch foo.c
cc    -c -o foo.o foo.c
$ rm -f foo.* ; make --version ; make foo.o
GNU Make 3.82
Built for i686-pc-linux-gnu
Copyright (C) 2010  Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
touch foo.c
cc    -c -o foo.o foo.c
$ rm -f foo.* ; make --version ; make foo.o
GNU Make 4.0
Built for i686-pc-linux-gnu
Copyright (C) 1988-2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
make: *** No rule to make target 'foo.o'.  Stop.
$ rm -f foo.* ; make --version ; make foo.o
GNU Make 4.1
Built for i686-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
make: *** No rule to make target 'foo.o'.  Stop.
.SUFFIXES:
.SUFFIXES: foo