MAKEFILE Introduction
Contents
Introduction to Makefiles
Makefiles are automation tools used to manage project builds and workflows. Originally created for software compilation, they can automate any task with file dependencies.
Key features:
- Dependency tracking
- Incremental builds
- Portable automation
- Parallel execution
Basic Syntax
Components
target
: File/action nameprerequisites
: Dependenciesrecipe
: Commands to execute
target: prerequisite1 prerequisite2
<TAB>recipe-command1
<TAB>recipe-command2
Simple Example
hello: hello.c
gcc hello.c -o hello
Variables
User-defined Variables
CC = gcc
CFLAGS = -Wall -O2
Automatic Variables
Variable | Meaning |
---|---|
$@ | Target name |
$< | First prerequisite |
$^ | All prerequisites |
Variable Usage Example
app: main.o utils.o
$(CC) $^ -o $@
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
Implicit Rules
Pattern Rules
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
Suffix Rules (Legacy)
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
Phony Targets
For targets not representing files:
.PHONY: clean
clean:
rm -f *.o app
Key Properties
- Dependency Resolution: Builds targets only when prerequisites are newer
- Incremental Builds: Skips up-to-date targets
- Variable Expansion: Supports recursive and simple variables
- Parallel Execution: Use
-j N
flag for parallel jobs
Common Automations
Multi-stage Build
all: compile test package
compile: app
test: compile
./run-tests.sh
package: compile
tar -czf app.tar.gz app
Automated Testing
test: CFLAGS += -coverage
test: app
./run-tests.sh
gcov main.c
Documentation Generation
docs:
doxygen Doxyfile
pandoc README.md -o docs.pdf
Advanced Features
Conditional Logic
DEBUG ?= 0
ifeq ($(DEBUG),1)
CFLAGS += -g -DDEBUG
endif
Functions
SOURCES = $(wildcard src/*.c)
OBJECTS = $(patsubst src/%.c,build/%.o,$(SOURCES))
Include Directives
include config.mk
Complete Example Project
CC = gcc
CFLAGS = -Wall -O2
SRC = src/main.c src/utils.c
OBJ = $(SRC:.c=.o)
EXEC = app
.PHONY: all clean
all: $(EXEC)
$(EXEC): $(OBJ)
$(CC) $^ -o $@
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJ) $(EXEC)
Best Practices
- Always declare .PHONY targets
- Use variables for compiler/linker flags
- Structure targets from specific to generic
- Add help target with usage documentation
- Use
-MMD
flag for automatic dependency generation
Conclusion
Makefiles provide powerful automation through:
- Declarative dependency management
- Flexible pattern matching
- Extensible variable system
- Cross-platform compatibility