For quite some time I've had a skeleton project for C that I can quickly start new projects with. The core of this is a boilerplate Makefile, recently I noticed that when editing just a header file it wouldn't recompile the project unless I touched a source file. With this in mind I added dependency tracking to the Makefile.
The Makefile is below, but first a few note on how its intended to be used
There are a number of targets you can use, generally if you need to change from one type of executable to another you will need to do a clean first
Target | Use |
all (or unspecified) | This defaults to the debug target |
debug | create an executable suitable for debugging (with gdb for example) |
release | create a more optimised executable |
inst | create an executable suitable for analysis (valgrind for example) |
style | tidy source and include (depends on astyle) |
clean | removes the executable and all the build artifacts |
APPNAME := $(notdir $(CURDIR)) # Use for valgrind etc INSTR := -fsanitize=address,leak,undefined,pointer-compare,pointer-subtract INSTR += -fno-omit-frame-pointer # Add required libraries here
LDFLAGS := -lm CFLAGS := -Wfatal-errors -Wall -Wextra -Werror CFLAGS += -std=c99 -I ./include CFLAGS += -MMD -MP # Add flags for dependency generation SRC := $(wildcard src/*.c) OBJ := $(SRC:src/%.c=.build/%.o) DEP := $(OBJ:.o=.d) # Dependency files CC = gcc all: debug # Target for creating the .build directory .build: @mkdir -p .build # Linking $(APPNAME): $(OBJ) $(CC) $(OBJ) -o $(APPNAME) $(LDFLAGS) # Object and dependency creation .build/%.o: src/%.c | .build $(CC) $(CFLAGS) -c $< -o $@ .PHONY: debug release inst clean style debug: CFLAGS += -g debug: $(APPNAME) @echo "*** made DEBUG target ***" release: CFLAGS += -O3 -Ofast release: $(APPNAME) @echo "*** made RELEASE target ***" inst: CFLAGS += -g $(INSTR) inst: LDFLAGS += $(INSTR) inst: $(APPNAME) @echo "*** made INSTRUMENTATION target ***" clean: rm -rf .build rm -f $(APPNAME) style: astyle -A10 -s4 -S -p -xg -j -z2 -n src/* include/* # Include the dependency files -include $(DEP)
Enjoy!