In my working directory, there is a makefile
, an empty obj
folder and a src
folder that contains foo.c
. I have a simple rule that takes an object file, substitutes everything until the first slash with src and replaces the ending .o with .c.
Example: obj/foo.o --> src/foo.c
With the help of MadScientist (credits to him) I obtained the pattern rule below (Please do not propose easier rules --> I am aware of their existance, but only this rule demonstrates my problem):
OBJFILES=obj/foo.o
all: $(OBJFILES)
@echo "all executed"
Y = $(shell echo $1 | sed -e 's,^[^\/]*,src,' -e 's,\.o$$,.c,')
.SECONDEXPANSION:
%.o: $$(call Y,$$@)
@echo "OBJECTS executed for $@ - [$^]"
src/foo.c:
@echo "Congrats"
Once I run the above makefile, I get a circular dependency:
xxxx@null:~/Desktop/experiment$ make
make: Circular src.o <- src dependency dropped.
OBJECTS executed for obj/foo.o - [src/foo.c]
all executed
The reason is found quickly: Make
creates the implicit rule Makefile: Makefile.o
, which triggers my pattern rule. Since Makefile.o
does not contain a slash, sed
evaluates to src
. Make
again applies the implicit rule src:src.o
which eventually causes the circular dependency. This can be seen in the make output:
make --print-data-base | grep src
make: Circular src.o <- src dependency dropped.
OBJECTS executed for obj/foo.o - [src/foo.c]
Y = $(shell echo $1 | sed -e 's,^[^\/]*,src,' -e 's,\.o$$,.c,')
# src (device 64769, inode 14031369): No files, no impossibilities so far.
Makefile.o: src
src: src.o
# Implicit/static pattern stem: 'src'
src.o:
# Implicit/static pattern stem: 'src'
# @ := src.o
# * := src
# < := src.o
obj/foo.o: src/foo.c
# + := src/foo.c
# < := src/foo.c
# ^ := src/foo.c
# ? := src/foo.c
src/foo.c:
If we now redefine Y
in that way: Y = $(patsubst obj/%.o,src/%.c,$1)
, no circular dependency occurs, because make
doesn't even try to apply the implicit rule Makefile:Makefile.o
make --print-data-base | grep src
OBJECTS executed for obj/foo.o - [src/foo.c]
Y = $(patsubst obj/%.o,src/%.c,$1)
# src (device 64769, inode 14031369): No files, no impossibilities so far.
obj/foo.o: src/foo.c
# + := src/foo.c
# < := src/foo.c
# ^ := src/foo.c
# ? := src/foo.c
src/foo.c:
When does make
create the implicit rule Makefile: Makefile.o
? What is the difference between the two different definitions of Y
?