【问题标题】:Can not disable "default" suffix-rules, in Gnu-Make无法在 Gnu-Make 中禁用“默认”后缀规则
【发布时间】:2015-09-13 04:16:47
【问题描述】:

我的 Makefile,如下所示:

.SUFFIXES:foo


# Disable "default" suffix-rules.
MAKEFLAGS=-r


# A rule without a recipe!
all.o::

# File 'all.c' is "ought to exist".
all.c:
    touch '$@'


执行,我得到:

# Gnu-make still applies the "default" suffix-rule '.c.o'. Wrong?
$ make
cc    -c -o all.o all.c


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

【问题讨论】:

  • make -r;它在读取 makefile 之前读取默认规则以发现它不应该读取默认规则。
  • @Jonathan 这仅适用于旧版本的 Gnu-Make。现代版本也允许 Makefile 级别的语法。
  • 现在我们需要定义古代和现代。我最后一次看到这类问题大概是在 1993 年,所以可能是古代非常古老。
  • @JonathanLeffler 4.0 及更高版本。
  • 这很新。例如,还有很多系统仍在使用 3.8x。可能是旧版本,但仍在使用中。

标签: c gcc makefile gnu-make


【解决方案1】:

问题在于添加-r 标志只会删除default 后缀规则设置。当您使用 .SUFFIXES: foo 时,您正在向现有设置添加新的后缀规则。执行此操作后,.SUFFIXES 的值不再与默认值相同,因此添加 -r 标志不会更改它。如果您想在Savannah 上提交它,这可能会被视为有用的增强请求。

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

.SUFFIXES:
.SUFFIXES: foo

【讨论】:

    【解决方案2】:

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

    $ cat Makefile
    .SUFFIXES:
    foo.c:
        touch $@
    $ rm -f foo.* ; make foo.o
    make: *** No rule to make target `foo.o'.  Stop.
    

    注意:要仅取消使.o.c 的隐式规则,还可以添加不带配方的模式规则:

    %.o: %.c
    

    关于MAKEFLAGS,根据文档,它的主要用途似乎是将选项传递给子制作。但是,文档还指出:

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

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

    $ 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
    

    但它适用于 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.* ; 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
    • 是的,你可以做这个或那个等等。但是,一个选项是:MAKEFLAGS = -r。然而,事实证明它只在某些时候有效。也许吧。
    • make 文档解释了如何使用MAKEFLAGS 将选项传递给子make。这是它的主要用途。它还指出您还可以在 makefile 中设置 MAKEFLAGS,以指定也应该对该 makefile 有效的其他标志但是,您是对的,这不适用于 -r。也许我们应该将其报告为文档错误。?
    • 您的错误报告在 4.0 中已“修复”。然而,我的问题表明“修复”仍然需要另一个修复。
    • 有趣。显然,.SUFFIXES 目标、MAKEFLAGS 变量和all.o 目标以奇怪的方式交互。取决于您是否声明它们(8 种组合,当未定义 all.o 目标时输入 make all.o 而不是 make),您将获得 all.o 构建、make: Nothing to be done for 'all.o'.make: *** No rule to make target 'all.o'. Stop.
    猜你喜欢
    • 2015-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多