Hacker News new | ask | show | jobs
by peterfirefly 565 days ago
This is an amazingly good 2-minute introduction to makefiles. It would have been better without the last two sentences (and most of your comments on the topic).

---

Something skipped over by your introduction (and most guides to makefiles) which very quickly either makes makefiles less short or much more complicated is header files.

C files often depend on one or more header files that aren't system headers (this C compiler certainly does).

They could be added to each individual rule by hand:

  codegen/codegen.o: codegen/codegen.c codegen/codegen.h linked_list.h libc.h
       $(CC) -c -o $@ $<
or they could be put into a variable:

  HEADERS = codegen/codegen.h parser/parser.h parser/goto.h linked_list.h libc.h 

  codegen/codegen.o: codegen/codegen.c $(HEADERS)
       $(CC) -c -o $@ $<
which causes too much code to be recompiled every time a header file is changed.

Or we could do something really fancy and get only the right header files added as dependencies for each compilation unit. That requires using a feature of the gcc/clang compilers (their preprocessors, really) that causes them to output a small makefile snippet that lists the exact header dependencies for a compilation unit (the '-MD' option). These snippets can then be included in the makefile. To make this look relatively clean requires some fancy macro use that is waaaay beyond what people can learn in ten minutes.

This is an extremely common use case and it is a bit of an embarrassment that GNU make doesn't handle it better.

1 comments

I did mention that in other comments, including the C preprocessor helping. make is completely language agnostic, so it cannot “guess” header dependencies. In make, you get the dependencies you specify (whether manual or generated), that’s what I wanted to show.
Make makes the easy part easy but the rest quite hard -- which I think you agree with.

It sure would be nice to have something like this:

  codegen/codegen.o: !codegen/codegen.c
     $(CC) -c $(CFLAGS) -o $@ $<
'!' would run $(CC) with -MD to extract the header dependencies. Doing that back in 1995 would have increased the value and usability of GNU make immensely (and greatly reduced the need for all the other complexity it has).
Wouldn't this require make to run CC with -MD on each instance of ! every time it's invoked, just to collect the list of dependencies, maybe just to discover that no file has changed?