GNU make seems to ignore non-terminal match-anythi

2019-07-29 05:51发布

I have the following files in a directory:

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;
}

makefile:

MAKEFLAGS += -rR

# the default target
.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 $@

If FP01 does not exist, running make gives the following output:

make: *** No rule to make target 'FP01.elf', needed by 'all'. Stop.

However, if I run the following commands before make, then everything works as expected:

$ touch FP01
$ touch FP01.c
$ make
gcc -Wall -g FP01.c -o FP01
cp FP01 FP01.elf

Am I missing something or there is a bug in GNU make?

make --version gives the following output:

GNU make 4.1
Built for i686-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Fundation, Inc.
License GPLv3+: ...
...

EDIT:

It seems that making match-anything rule terminal somehow fixes the problem, but I want to use built-in rule to generate FP01 if possible and unfortunately it is non-terminal.

Another thing is that I believe that non-terminal rule should work so using terminal rule doesn't actually solve the problem as I still don't know whether the bug is in make or in my "mental makefile parser".

3条回答
够拽才男人
2楼-- · 2019-07-29 05:56

Adding FP01 as a prerequisite of .INTERMEDIATE (special built-in target) seems to make it work (no need to modify the match-anything rule). Just another workaround.

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
查看更多
Lonely孤独者°
3楼-- · 2019-07-29 05:58

I'm not sure if this is a bug or not, I'd have to look more deeply into it. But the simple way to fix your problem is to set the match-anything pattern rule that compiles from the .c file as terminal, which is how it should be (unless you're generating the source files from somewhere else):

%:: %.c
        cp $< $@

$ make
cp FP01.c FP01
cp FP01 FP01.elf
rm FP01
查看更多
霸刀☆藐视天下
4楼-- · 2019-07-29 06:22

I think you should use :: on the % : %.c rule because you actually want that to be a terminal match-anything rule (since you don't need the .c file to be built):

MAKEFLAGS += -rR

.PHONY: all
all: FP01.elf

%.elf: % ; cp $< $@
% :: %.c ; gcc -Wall -g $< -o $@

Note that I used the ; form for the recipes here because it's easier to copy and paste because no need to worry about tabs.

查看更多
登录 后发表回答