Having to deal with dependencies in Makefile is a real pain, there are a lot of examples of way to deal with it on the web but none of them is satisfying.

For example using gcc -MM does not work with subfolders, a depend rule requires the user to use it everytimes he adds new files ...

Here is what is wanted:

  • Completly automatic: No user interaction is required when adding new files
  • Works with an arbitrary amount of files
  • Works with an arbitrary amount of level of folders
  • Is not recalculated when nothing changed
  • Use only one file to store dependencies
  • Do not depend on complicated regular expressions

Here is the result:

BINARY  = project.exe
CC      = gcc
CFLAGS  = 
FILES   = $(shell find src/ -name "*.c")
HEADERS = $(shell find src/ -name "*.h")
OBJS    = $(FILES:.c=.o)
 
all: $(BINARY)
 
-include Makefile.deps
 
$(BINARY): Makefile.deps $(OBJS)
        $(CC) $(CFLAGS) $(OBJS) -o $(BINARY)
 
Makefile.deps: $(FILES) $(HEADERS)
        makedepend -- $(CFLAGS) -- $(FILES) -f- > Makefile.deps

This is in fact really easy. In your $(BINARY) rule, you add Makefile.deps as a prerequisite.

In order to generate the Makefile.deps you mark all $(FILES) and $(HEADERS) as prerequisite, so every time you change a file or header it will recompile the list.
We use makedepend to generate the dependencies list. It works like gcc -MM except that it outputs the correct file path when used with folders.

Then all is required is to include the Makefile.deps. We include it with -include so it does work the first time you compile.

Thanks to Lemoine Gauthier who helped me to discover this technique.

If you liked this article, you might be interested in my Twitter feed as well.
 
  • Pingback: Makefile problem: cannot see the target

  • gbmhunter

    Doesn't this recompile everything if only one thing is changed (since $(BINARY) depends on Makefile.deps, and Makefile.deps depends on $(HEADERS), which is all header files found under src/)?

 

Related Posts

  • August 20, 2011 Idea – mouseFreeze – A solution for Browser FPS Games (8)
    There is an open problem in porting real game into the web browser related to cursor handling. Problem Many games such as First-Person Shooters require the mouse to freely move, without the constraints of screen edges. However there is no such API in the browser to make this work. If you ...
  • July 26, 2012 CSS – Cross Browser Drag Cursor (2)
    grab and grabbing are two great CSS cursors you can use when you are moving things around. Windows: Mac: Since those are not standard, it is really tricky to get them working cross browser. This article is going to show you all the available workarounds to get the best version working e...
  • September 24, 2011 Javascript: Cyclic Object Detection (5)
    URLON.stringify() suffer from a problem, when passed an object that contains a cycle, it will never stop. This article shows 3 techniques in order to detect if an object is cyclical. Edit the object: Mark In order to detect a cycle in an object, the method we learn at school is to mark each v...
  • August 19, 2011 jParser – Binary File Parsing revisited using Javascript (11)
    Writing a parser for a structured binary format such as a 3D model is extremely annoying. You have first to declare your file structure, and then go over every structure again and make a proper code to parse it. This is mainly caused because the lack of introspection of C/C++ and for performance ...
  • September 25, 2011 Javascript Object Difference (5)
    This article is about a difference algorithm. It extracts changes from one version of an object to another. It helps storing a smaller amount of information. Template In a project, I have a template object with all the default settings for a widget. var template = { achievement: { ...