I am new to makefiles and am struggling a little bit to get things to work how I want.
I have a header file with some structs and a bunch of macros that I have sitting in #ifndef statements so that they have a default value if they're not defined on the command line.
I have three .c files that all include this header to make use of these macros.
In my makefile, I need to be able to compile all my source files, which have the header file as a dependent.
What I would like to be able to do is when I run make, if I include new values for those macros, that the header file is updated, and this triggers the source files to also be recompiled so that they include the new values.
I don't know if this is the correct way to go about it. The issue I am trying to avoid is if I pass these new values, but say only one of these source files recompile because make only identifies it as having been changed, and therefore different values are being used across the three programs.
CodePudding user response:
What I would like to be able to do is when I run make, if I include new values for those macros, that the header file is updated, and this triggers the source files to also be recompiled so that they include the new values.
And how do you suppose that make
would recognize that the macro definitions in use have changed? It cannot very easily compare the definitions themselves to values as-of previous runs.
What make
can do pretty easily is compare the timestamp of the file wherein the macro definitions are recorded to the timestamps of the object files. It can do that by making the former file a prerequisite for each of the latter files.
The file containing the macro definitions might be the makefile itself or some file include
d into it. If you use the makefile itself then you will sometimes get recompilations for reasons other than the macro definitions having changed, but many of those reasons will in fact be good reasons. The object files and binaries have a bona fide dependency on the instructions used to build them.
So you might have something along these lines:
SOURCES = larry.c curly.c moe.c
OBJECTS = $(SOURCES:.c=.o)
DEFINES = -DOPTION1=1 -DOPTION2=0 -DOPTION3=1
prog: $(OBJECTS)
$(CC) -o $@ $^
%.o: %.c stooges.h Makefile
$(CC) -c -o $@ $(DEFINES) $<
It would possible to instead use a similar procedure update the timestamp of the header file, thus forcing recompilation indirectly, but that's synthetic. I recommend expressing the true dependencies instead.
OR, for a single-developer project, it would probably be feasible to just make it a developer responsibility to manually perform a clean build after performing makefile updates that require it. That scales poorly as you add developers, though.