Let's say I have a makefile with the rule
%.o: %.c
gcc -Wall -Iinclude ...
I want *.o to be rebuilt whenever a header file changes. Rather than work out a list of dependencies, whenever any header file in /include
changes, then all objects in the dir must be rebuilt.
I can't think of a nice way to change the rule to accomodate this, I'm open to suggestions. Bonus points if the list of headers doesn't have to be hard-coded
Most answers are surprisingly complicated or erroneous. However simple and robust examples have been posted elsewhere [codereview]. Admittedly the options provided by the gnu preprocessor are a bit confusing. However, the removal of all directories from the build target with
-MM
is documented and not a bug [gpp]:The (somewhat newer)
-MMD
option is probably what you want. For completeness an example of a makefile that supports multiple src dirs and build dirs with some comments. For a simple version without build dirs see [codereview].This method works because if there are multiple dependency lines for a single target, the dependencies are simply joined, e.g.:
is equivalent to:
as mentioned at: Makefile multiple dependency lines for a single target?
As I posted here gcc can create dependencies and compile at the same time:
The '-MF' parameter specifies a file to store the dependencies in.
The dash at the start of '-include' tells Make to continue when the .d file doesn't exist (e.g. on first compilation).
Note there seems to be a bug in gcc regarding the -o option. If you set the object filename to say obj/_file__c.o then the generated file.d will still contain file.o, not obj/_file__c.o.
A slightly modified version of Sophie's answer which allows to output the *.d files to a different folder (I will only paste the interesting part that generates the dependency files):
Note that the parameter
is used to ensure that the targets (i.e. the object file names) in the generated *.d files contain the full path to the *.o files and not just the file name.
I don't know why this parameter is NOT needed when using -MMD in combination with -c (as in Sophie's version). In this combination it seems to write the full path of the *.o files into the *.d files. Without this combination, -MMD also writes only the pure file names without any directory components into the *.d files. Maybe somebody knows why -MMD writes the full path when combined with -c. I have not found any hint in the g++ man page.
Martin's solution above works great, but does not handle .o files that reside in subdirectories. Godric points out that the -MT flag takes care of that problem, but it simultaneously prevents the .o file from being written correctly. The following will take care of both of those problems:
I prefer this solution, over the accepted answer by Michael Williamson, it catches changes to sources+inline files, then sources+headers, and finally sources only. Advantage here is that the whole library is not recompiled if only a a few changes are made. Not a huge consideration for a project with a couple of files, bur if you have 10 or a 100 sources, you will notice the difference.
The following works for me: