Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I have a Makefile automatically rebuild source files that include a modified header file? (In C/C++)

I have the following makefile that I use to build a program (a kernel, actually) that I'm working on. Its from scratch and I'm learning about the process, so its not perfect, but I think its powerful enough at this point for my level of experience writing makefiles.

AS  =   nasm CC  =   gcc LD  =   ld  TARGET      =   core BUILD       =   build SOURCES     =   source INCLUDE     =   include ASM         =   assembly  VPATH = $(SOURCES)  CFLAGS  =   -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions \             -nostdinc -fno-builtin -I $(INCLUDE) ASFLAGS =   -f elf  #CFILES     =   core.c consoleio.c system.c CFILES      =   $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) SFILES      =   assembly/start.asm  SOBJS   =   $(SFILES:.asm=.o) COBJS   =   $(CFILES:.c=.o) OBJS    =   $(SOBJS) $(COBJS)  build : $(TARGET).img  $(TARGET).img : $(TARGET).elf     c:/python26/python.exe concat.py stage1 stage2 pad.bin core.elf floppy.img  $(TARGET).elf : $(OBJS)     $(LD) -T link.ld -o $@ $^  $(SOBJS) : $(SFILES)     $(AS) $(ASFLAGS) $< -o $@  %.o: %.c     @echo Compiling $<...     $(CC) $(CFLAGS) -c -o $@ $<  #Clean Script - Should clear out all .o files everywhere and all that. clean:     -del *.img     -del *.o     -del assembly\*.o     -del core.elf 

My main issue with this makefile is that when I modify a header file that one or more C files include, the C files aren't rebuilt. I can fix this quite easily by having all of my header files be dependencies for all of my C files, but that would effectively cause a complete rebuild of the project any time I changed/added a header file, which would not be very graceful.

What I want is for only the C files that include the header file I change to be rebuilt, and for the entire project to be linked again. I can do the linking by causing all header files to be dependencies of the target, but I cannot figure out how to make the C files be invalidated when their included header files are newer.

I've heard that GCC has some commands to make this possible (so the makefile can somehow figure out which files need to be rebuilt) but I can't for the life of me find an actual implementation example to look at. Can someone post a solution that will enable this behavior in a makefile?

EDIT: I should clarify, I'm familiar with the concept of putting the individual targets in and having each target.o require the header files. That requires me to be editing the makefile every time I include a header file somewhere, which is a bit of a pain. I'm looking for a solution that can derive the header file dependencies on its own, which I'm fairly certain I've seen in other projects.

like image 637
Nicholas Flynt Avatar asked Nov 18 '08 00:11

Nicholas Flynt


People also ask

Should header files be included in makefile?

The only way to include the header file is to treat the filename in the same way you treat a string. Makefiles are a UNIX thing, not a programming language thing Makefiles contain UNIX commands and will run them in a specified sequence.

Is makefile a source file?

The makefile is a text file that contains the recipe for building your program. It usually resides in the same directory as the sources, and it is usually called Makefile .

Where do you put makefiles?

some projects put their makefile in src/ subdirectory of the root directories of the projects, some projects put their makefiles in the root directory of the project.


1 Answers

As already pointed out elsewhere on this site, see this page: Auto-Dependency Generation

In short, gcc can automatically create .d dependency files for you, which are mini makefile fragments containing the dependencies of the .c file you compiled. Every time you change the .c file and compile it, the .d file will be updated.

Besides adding the -M flag to gcc, you'll need to include the .d files in the makefile (like Chris wrote above). There are some more complicated issues in the page which are solved using sed, but you can ignore them and do a "make clean" to clear away the .d files whenever make complains about not being able to build a header file that no longer exists.

like image 183
Udi Meiri Avatar answered Sep 28 '22 06:09

Udi Meiri