What is the Difference Between% .c and * .c in GNU Make

What is the difference between %.c

and *.c

in makefiles. For example, we can:

vpath %.c    $(BASE_DIR)platform/$(TARGET)

      

and

Files += $(wildcard *.c) 

      

Both include all files in a specific directory that end in .c to account for them. But when do we use it %.c

and when *.c

? In other words, why can't I use

vpath *.c    $(BASE_DIR)platform/$(TARGET)

      

instead

vpath %.c    $(BASE_DIR)platform/$(TARGET)

      

?

Thank.

+3


source to share


2 answers


Both %

and *

in GNU Make is wildcard functions. The difference between the two is that it %

can be used as part of the Text Replacement Function , whereas it *

cannot.



If you're trying to make the largest possible makefile, you should try and use *

the wildcard function instead of the %

Replace function, since there should be no resources used to store the name of the matched element and replace it with a subsequent function call. If you're not worried about optimizing your production system to the limit, then you don't need to worry about which one you choose.

+1


source


Both %

and *

in GNU Make can be treated as a wildcard, but very different.

The symbol *

, which GNU does manually, invokes a wildcard : it is a glob matching, a pattern matching to files on the filesystem. For example. *.a

expands to the list of files present in the current directory whose names end with .a

, or literal *.a

if no such files exist.

For example:

sh> rm -f *.a *.b *.c
sh> cat Makefile 
all: *.a

*.a : *.b *.c
        @echo $+ > $@
sh> make
make: *** No rule to make target '*.b', needed by '*.a'.  Stop.
sh> touch x.a
sh> make
make: *** No rule to make target '*.b', needed by 'x.a'.  Stop.
sh> touch y.b
sh> make
make: *** No rule to make target '*.c', needed by 'x.a'.  Stop.
sh> touch z1.c z2.c
sh> make
sh> cat x.a
y.b z2.c z1.c

      

As you can see, it is *

interpreted by comparing it to files that exist on the file system. For example, it make

interprets *.a

as a literal filename *.a

until I create files with names ending in .a

, after which it expands to the names of those files; the same for *.b

and *.c

.



So *

only use it if you really want to specify a set of files already present on your filesystem. This is common for source files (prerequisites in rules), but it is really weird to use for target purposes like in this example.

The symbol %

also performs pattern matching, but in a completely different way: when used on either side of :

it, it is part of a template rule , and it establishes a relationship between the target file (s) names and the dependency names.

For example:

sh> rm -f *.a *.b *.c
sh> cat Makefile
all: %.a

%.a : %.b %.c
        @echo $+ > $@
sh> make
make: *** No rule to make target '%.a', needed by 'all'.  Stop.
sh> touch x.a y.b z1.c z2.c
sh> make
make: *** No rule to make target '%.a', needed by 'all'.  Stop.
sh> make x.a
make: Nothing to be done for 'x.a'.
sh> make y.a
make: *** No rule to make target 'y.a'.  Stop.
sh> touch y.c
sh> make y.a
sh> cat y.a
y.b y.c

      

The symbol is %

never matched against files in the filesystem, but instead expresses a correspondence between target and required names: %.a: %.b %.c

means: you can use this rule to create any file whose name ends in .c

from files whose names are the same, except that they are end with .a

and .b

. Thus, we can make x.a

using this rule from x.b

and x.c

, but never from y.b

or z1.c

, and this is true even when x.b

and x.b

does not exist yet, since they too can be made (although this example does not show this). If not, GNU Make will (embarrassingly) behave like this rule doesn't exist, as you can see in the example.

+1


source







All Articles