Reputation: 569
I am new to makefiles and trying to understand some code:
%.o:%.c
$(CC) $^ -c -Wall
$(CC) -MM $*.c > $*.dep
$(OBJECTDUMP) -d -M intel -S $@
@mv -f $*.dep $*.dep.tmp
@sed -e 's|.*:|$*.o:|' < $*.dep.tmp > $*.dep
@sed -e 's/.*://' -e 's/\\$$//' < $*.dep.tmp | fmt -1 | \
sed -e 's/^ *//' -e 's/$$/:/' >> $*.dep
@rm -f $*.dep.tmp
Can someone please explain what the last 5 lines of code are doing?
Upvotes: 1
Views: 240
Reputation: 99094
The purpose of those lines is to deal with a problem with dependency handling.
Suppose you have a header file bar.h
, and a source file foo.c
that contains the line
#include "bar.h"
Now generate the dependency file:
$(CC) -MM $*.c > $*.dep
The file foo.dep
now contains:
foo.o: foo.cc bar.h
Wonderful. I'm sure the makefile has a line like -include *.dep
, so now Make will handle foo's dependencies correctly. But now suppose you edit foo.c
, remove that #include
line, and delete the no-longer-needed bar.h
. The next time you try to make foo
, Make will read the old foo.dep
which calls for bar.h
, see that there is no such header and no known way to build it, and abort. Make will not know that the header is not needed until it rebuilds the dep file, which it cannot do because the header is missing and Make thinks it is needed.
One solution is to delete foo.dep
when this situation arises (before Make aborts, if possible). Another is to add a line to foo.dep
:
bar.h:
which will assuage Make's fears about the missing header. The first approach requires human attention, the second can be automated:
@mv -f $*.dep $*.dep.tmp # rename foo.dep -> foo.dep.tmp
@sed -e 's|.*:|$*.o:|' < $*.dep.tmp > $*.dep # this does nothing and appears to be vestigal
@sed -e 's/.*://' \ # remove the target, leaving foo.c bar.h
-e 's/\\$$//' \ # remove line continuation marks, if any
< $*.dep.tmp | fmt -1 | \ # put each word on its own line
sed -e 's/^ *//' \ # remove leading whitespace
-e 's/$$/:/' \ # add a colon to the end of each line (making it a rule)
>> $*.dep # save the result as foo.dep
@rm -f $*.dep.tmp # delete the temporary file
Upvotes: 4
Reputation: 753725
$*
corresponds roughly to the %
in the first line.
@mv
line moves the old basename.dep
file to basename.dep.tmp
@sed
line edits what's in the basename.dep.tmp
, replacing anything up to a colon with basename.o:
(because the $*
is expanded by make
, not the shell).@sed
line and the following line do some more editing — appending another variant of the basename.dep.tmp
file to the end of basename.dep
.@rm
line removes the temporary basename.dep.tmp
file.A more thorough analysis of the second sed
sequence requires more detailed knowledge of what's in the .dep
file and exactly what fmt -1
does for you.
However, it seems that the goal is to update the dependencies that apply to the source file, based on the information from the compiler plus massaging it in a way to suit the programmer. The why is not clear to me.
Upvotes: 3