Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU Make. Why this complex syntax to generate dependencies?

I'm reading Managing Projects with GNU Make, and found this example in Chapter 2.7 - Automatic Dependency Generation. The Author says their from the GNU manual:

%.d: %c
        $(CC) -M $(CPPFLAGS $< > $@.$$$$; \
              sed s',\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
              rm -f $@.$$$$

However, I was able to do the same thing with this (note the sed):

-include $(subst .c,.d,$(SOURCES))

%.d: %.c
          @$(CC) -M $(CPPFLAGS) $<  | sed 's|:| $*.d : |'  > $@;

All these lines do is generate the dependencies, then add in the *.d name. They had to change the first line from:

  foo.o: bar.h foo.h fubar.h

to foo.o foo.d : bar.h foo.h fubar.h

Mine is simpler and seems to work quite well, but I assume that the GNU folks had a reason for their sed command. Also:

  • Why do a redirect of the file into sed? Why not simply take it as a commond line parameter
  • Why not skip the intermediary file completely?

I know the guys at GNU could have thought of these too, but for some reason, went with the more complex setup. I just want to understand their reasoning, so I can do these on the fly.

like image 386
David W. Avatar asked May 22 '12 00:05

David W.


3 Answers

Addressing the question: Why do a redirect of the file into sed? If you do:

@$(CC) -M $(CPPFLAGS) $<  | sed 's|:| $*.d : |'  > $@;

and the compilation fails (errors out and generates no output), you will create an empty target file. When make is run again, it will see the newly created empty file and not regenerate it, leading to build errors. Using intermediate files is a common defensive strategy to avoid accidentally created an empty target.

like image 20
William Pursell Avatar answered Sep 21 '22 16:09

William Pursell


An even simpler solution is to get rid of the sed call completely, as gcc can do everything you need directly:

%.d: %.c
        $(CC) -M $(CPPFLAGS) -MF $@ $< -MT "$*.o $@"
like image 22
Chris Dodd Avatar answered Sep 20 '22 16:09

Chris Dodd


Actually even the rule itself is not necessary. There is a great overview of different approaches of generating Make-style dependencies in Advanced Auto-Dependency Generation article written by Paul D. Smith.

After all, the following rule should be enough (in case of using GCC):

%.o: %.c
    $(CC) $(CPPFLAGS) $(CFLAGS) -MMD -MP -o $@ -c $<

-include $(SOURCES:.c=.d)

UPD.

I have also answered a similar question a bit earlier. It contains an explanation (quotation of GCC manual) of -MMD -MP options.

like image 196
Eldar Abusalimov Avatar answered Sep 20 '22 16:09

Eldar Abusalimov