Makefile GNU make似乎忽略了中间文件的非终端匹配规则

Makefile GNU make似乎忽略了中间文件的非终端匹配规则,makefile,gnu-make,Makefile,Gnu Make,我的目录中有以下文件: FP01.c: #include <stdio.h> #include <stdlib.h> int main(void) { long double ld = 0.1L; // long double constant (L or l suffix) scanf("%Lf", &ld); return 0; } 但是,如果在make之前运行以下命令,则一切都会按预期工作: $ touch FP01 $ touc

我的目录中有以下文件:

FP01.c:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    long double ld = 0.1L; // long double constant (L or l suffix)
    scanf("%Lf", &ld);
    return 0;
}
但是,如果在
make
之前运行以下命令,则一切都会按预期工作:

$ touch FP01
$ touch FP01.c
$ make
gcc -Wall -g FP01.c -o FP01
cp FP01 FP01.elf
我是否遗漏了什么或者GNU make中有bug

make--version
提供以下输出:

make: *** No rule to make target 'FP01.elf', needed by 'all'. Stop.
GNU make 4.1
Built for i686-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Fundation, Inc.
License GPLv3+: ...
...

编辑:

看起来让match anything rule terminal某种程度上解决了这个问题,但如果可能的话,我想使用内置规则来生成FP01,不幸的是它不是terminal


另一件事是,我相信非终端规则应该可以工作,所以使用终端规则实际上并不能解决问题,因为我仍然不知道这个bug是在make中还是在我的“mental makefile解析器”中。

我不确定这是否是一个bug,我必须更深入地研究它。但解决问题的简单方法是将从
.c
文件编译的match anything模式规则设置为terminal,它应该是这样的(除非您从其他地方生成源文件):

%::%.c
cp$<$@
$make
cp FP01.c FP01
cp FP01 FP01.elf
FP01室

我认为您应该在
%:%.c
规则上使用
,因为您实际上希望它是一个终端匹配任何规则(因为您不需要构建
.c
文件):

MAKEFLAGS+=-rR
冒牌货:全部
全部:FP01.elf
%.elf:%;cp$<$@
%:%.c;gcc-墙-g$<-o$@

注意,我使用了
这里的配方表单,因为它更容易复制和粘贴,因为不需要担心标签。

添加
FP01
作为
的先决条件。中间
(特殊内置目标)似乎可以使其工作(无需修改匹配任何规则)。只是另一个解决办法

MAKEFLAGS += -rR

# the default goal
.PHONY all
all: FP01.elf

%.elf: % ; cp $< $@

# prevents non-terminal match-anything rules from matching target '%.c'
# see section 10.5.5 of GNU make manual
%.c:

# a non-terminal match-anything rule
%: %.c ; gcc -Wall -g $< -o $@

.INTERMEDIATE: FP01
MAKEFLAGS+=-rR
#默认目标
1.假冒伪劣
全部:FP01.elf
%.elf:%;cp$<$@
#防止非终端匹配任何规则与目标“%.c”匹配
#参见GNU make手册第10.5.5节
%.c:
#非终结符匹配规则
%:%c;gcc-墙-g$<-o$@
.中级:FP01

先决条件
%
出现了一些有趣的情况,从调试输出来看,它似乎递归地将其与使用的相同规则进行匹配,删除了匹配任何规则。当然它是有效的,但它没有回答问题,请参阅John Graham Cumming回答下的我的评论。另一件事是,我希望FP01.elf是gcc的输出,而不仅仅是FP01的副本。c@user657267
%
先决条件没有什么特别之处——将其更改为
FP01
没有任何区别。@AleksanderZ。你是对的,我假设它可能是
%
,因为它不是你在野外看到的东西,但它只是忽略了匹配任何东西规则。我只是在这里使用
cp
,所以我可以使用
touch FP01.c
来创建文件,而不是真正的c代码。显然,配方中调用的命令与测试makefile行为无关,因此我经常使用简单的命令,如
touch
cp
来创建最少的示例。好的,它可以工作,但是:首先,我将其简化了一点:如果可能的话,我希望使用内置规则从FP01.c生成FP01,并且由于明显的原因,我无法修改它。第二,我仍然不明白为什么非终端规则不起作用。即使只是让它成为一个常规的目标也能起作用,
FP01:
。这似乎类似于使用静态模式规则的情况。看见
%:: %.c
        cp $< $@

$ make
cp FP01.c FP01
cp FP01 FP01.elf
rm FP01
MAKEFLAGS += -rR

.PHONY: all
all: FP01.elf

%.elf: % ; cp $< $@
% :: %.c ; gcc -Wall -g $< -o $@
MAKEFLAGS += -rR

# the default goal
.PHONY all
all: FP01.elf

%.elf: % ; cp $< $@

# prevents non-terminal match-anything rules from matching target '%.c'
# see section 10.5.5 of GNU make manual
%.c:

# a non-terminal match-anything rule
%: %.c ; gcc -Wall -g $< -o $@

.INTERMEDIATE: FP01