Reputation: 341
I'm trying to write a rule that would replace a set of .c files with .o files for a variable.
To make sure it works, I'm echoing their values. the .c files are obtained from the current working directory via a shell wildcard
sources := *.c
However, nothing gets printed out for the .o files, as 'sources' doesn't seem to get expanded for this, whether I do with using patsubst or the handier $(src:%.c=%.o).
On the other hand, if I set the value of 'manually', everything works as expected, e.g.
sources := source1.c source2.c source3.c
The makefile:
sources := *.c
srcs = one.c two.c
objects := $(sources:.c=.o)
objs := $(patsubst %.c, %.o, $(srcs))
prints:
@echo sources
@echo $(sources)
@echo objects
@echo $(objects)
@echo $(objs)
Output:
sources
source1.c source2.c source3.c source4.c
objects
*.o
one.o two.o
As you can see, 'objects' (based on the wildcard-using 'sources') is a no-go, but 'objs' (based on the manally-set 'srcs' works as expected).
What am I missing. I know it must have to do with when or how the expansion takes place.
Upvotes: 0
Views: 386
Reputation: 100916
Make is not the shell. This line:
sources := *.c
sets the make variable sources
to the literal string *.c
. Then this line:
objects := $(sources:.c=.o)
sets objects
to the literal string *.o
.
Then this line:
@echo $(sources)
Sends echo *.c
to the shell, and the SHELL expands the *.c
to the list of files that match that glob.
Then this line:
@echo $(objects)
sends echo *.o
to the shell, and since there are no files that match the *.o
glob, it just prints the glob itself *.o
.
If you want to get a list of files in make you have to use the wildcard
function:
sources := $(wildcard *.c)
Also, you have fallen prey to two different common errors people make when they are trying to debug makefiles:
First, you should never, EVER use @
in your recipe lines to hide the commands. This is like trying to debug your makefile with a blindfold on. Seeing what make is sending to the shell gives you absolutely vital information as to what is happening here. I personally don't use @
even after my makefile is working, except for some trivial operations, and I definitely never use it while trying to debug.
Second, if you want to see the contents of make variables in recipes you should always use single quotes around them. If you leave them unquoted or use double quotes, then the shell will come along and mess with those values (depending on what the values are) and you won't be able to see what they really are. Either use ''
around them or else use a make function like $(info ...)
to see their value rather than a shell program like echo
.
If you had written your test makefile like this:
prints:
echo sources
echo '$(sources)'
echo objects
echo '$(objects)'
echo '$(objs)'
it would have been more immediately obvious what the problem was.
Upvotes: 2