Makefile Basics — compilation pipeline - MarekBykowski/readme GitHub Wiki

The pipeline:

source.c  →  [preprocessor]  →  source.i
source.i  →  [compiler]      →  source.s  (assembly)
source.s  →  [assembler]     →  source.o  (object file)
source.o  →  [linker]        →  binary / .elf / .so
CC      = arm-none-eabi-gcc
CFLAGS  = -Wall -Wextra -O2 -mcpu=cortex-m4 -mthumb
LDFLAGS = -T linker.ld -lc

# Pattern rule — compile any .c to .o
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

# Link all objects into final binary
firmware.elf: main.o uart.o mavlink.o
	$(CC) $(LDFLAGS) $^ -o $@

# Useful targets
clean:
	rm -f *.o *.elf

# Force rebuild if header changes
main.o: main.c uart.h mavlink.h

Key flags to know:

Flag Meaning
-c compile only, don't link → produces .o
-o output filename
-Wall -Wextra enable warnings (always use)
-O0 no optimisation (debug)
-O2 optimise (production)
-g include debug symbols
-I path add include search path
-L path add library search path
-l name link library libname.a
-D NAME define preprocessor macro
-mcpu=cortex-m4 target CPU (embedded)
-mthumb use Thumb instruction set
-fstack-usage report stack usage per function

💡 For embedded: always check .map file after linking — it shows exactly where each symbol lands in flash/RAM. Critical for catching BSS/data overflows on small MCUs.