Search code examples
makefilegnu-make

In the makefile script: *.c and $(wildcard *.c) are different?I am confused by my experiments


experiment 1

CC = gcc
src = *.c#$(wildcard *.c)
obj = $(src:.c=.o)
target = $(src:.c=.exe)
$(target) : $(obj)

%.exe : $(obj)
    $(CC) $< -o $@
%.o : $(src)
    $(CC) -c $< -o $@
clean:
    rm *.exe *.o

experiment 2

src = *.c
src1 = $(wildcard *.c)

p :
    @echo $(src)
p1 :
    @echo $(src1)

In experiment 1, *.c and $(wildcard *.c) has a big difference. if src (a variable) = *.c, gcc will gives me a error as follows:

       gcc -c test1.c -o *.o
       Assembler messages:
       Fatal error: can't create *.o: Invalid argument
       makefile:25: recipe for target '*.o' failed
       make: *** [*.o] Error 1

If i replace *.c with $(wildcard *.c), everything goes well.

In experiment 2, *.c and $(wildcard *.c) has a no difference in result.

   if @echo $(src)
           echo file1.c file2.c file3.c
   if @echo $(src1)
           echo file1.c file2.c file3.c

ADDITIONS:There are 3 c file for testing.


Solution

  • The wildcard function is evaluated by make when it is expanded.

    The string *.c is just a string, as far as make is concerned. So this line:

    obj = $(src:.c=.o)
    

    if src is $(wildcard *.c) then make will first expand src into foo.c bar.c baz.c then replace the .c with .o, giving foo.o bar.o baz.o.

    If src is *.c, then make will expand src but it's just the simple string *.c so no expansion is needed, then it replaces .c with .o, giving *.o.

    This rule is wrong, too:

    %.o : $(src)
            $(CC) -c $< -o $@
    

    they says "every individual object file depends on ALL the source files" which is not what you want.