I came across the following makefile in a software:
CFLAGS = -O6 -g -Wall
CC = gcc
VPATH = ./code
LIB_MOD = common arith inout log
valid_MOD = valid $(LIB_MOD)
xporta_MOD = porta four_mot portsort largecalc mp $(LIB_MOD)
ALL_MOD = $(valid_MOD) $(xporta_MOD)
all: xporta valid
valid: $(valid_MOD:%=%.d) $(valid_MOD:%=%.o)
$(CC) -o bin/$@ $(valid_MOD:%=%.o)
xporta: $(xporta_MOD:%=%.d) $(xporta_MOD:%=%.o)
$(CC) -o bin/$@ $(xporta_MOD:%=%.o)
clean:
rm -f *.o bin/xporta bin/valid
%.d: %.c
$(SHELL) -ec 'gcc -MM $(CPPFLAGS) $< \
| sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \
[ -s $@ ] || rm -f $@'
include $(ALL_MOD:%=%.d)
While I am able to understand the other parts of it, I am unable to understand what the following line does towards the bottom of the makefile:
| sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \ [ -s $@ ] || rm -f $@'
What does this expand to and what is the equivalent syntax without the sed
function call?
This is an old software written in C and I am trying to rewrite the makefile into a format that is more verbose so that I can understand what is going on.
This is a cross post from /r/c_programming I made where I could not get a specific answer.
The actual sed
command is:
sed 's/\($*\)\.o[ :]*/\1.o $@ : /g'
'\''
is needed because this is inside the argument to $(SHELL) -ec
, which is a single-quoted string; it terminates that quote, adds a literal quote, then continues the quoted string.
$*
and $@
are automatic variables that get replaced by make
.
$*
is replaced with the stem of the rule, which is the part of the filename that matched %
in the rule.$@
is replace with the target of the pattern.So if the rule is being used to create foo.d
, the stem is foo
and the target is foo.d
. Therefore, the sed
command becomes
sed 's/\(foo\)\.o[ :]*/\1.o foo.d : /g'
This basically finds any instances of foo.o :
in the output of gcc -MM $<
and inserts foo.d
between foo.o
and :
.
gcc -MM
is used to create a file containing makefile rules describing all the preprocessor dependencies in the C file. This adds a corresponding .d
file to any .o
targets that it generates.