PY
C

Python to C

10 lessons

Progress0%
1Variables & Types2Functions3Lists → Arrays4Memory Management5String Handling6Structs7Preprocessor8File I/O9Pointers and Manual Memory10Build System: Makefile
All Mirror Courses
PY
C
Build System: Makefile
MirrorLesson 10 of 10
Lesson 10

Build System: Makefile

C projects use Makefiles (or CMake) for incremental compilation; this is the equivalent of Python's pip/setup.py/pyproject.toml workflow but for compiled artifacts.

Introduction

In this lesson, you'll learn about build system: makefile in C. Coming from Python, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.

Mirror Card
PY
From Python:

In Python, you're familiar with c projects use makefiles (or cmake) for incremental compilation; this is the equivalent of python's pip/setup.py/pyproject.toml workflow but for compiled artifacts..

C
In C:

C has its own approach to c projects use makefiles (or cmake) for incremental compilation; this is the equivalent of python's pip/setup.py/pyproject.toml workflow but for compiled artifacts., which we'll explore step by step.

The C Way

Let's see how C handles this concept. Here's a typical example:

C
C Example
# Makefile — tab-indented recipe lines are MANDATORY
CC      = gcc
CFLAGS  = -Wall -Wextra -std=c11 -g
TARGET  = myapp
SRCS    = main.c math.c utils.c
OBJS    = $(SRCS:.c=.o)       # substitute .c → .o

# Default target
all: $(TARGET)

# Link object files into executable
$(TARGET): $(OBJS)
	$(CC) $(CFLAGS) -o $@ $^

# Compile each .c to .o
# $< = first prerequisite (the .c file)
# $@ = target name (the .o file)
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

# Regenerate dependency files
# (tracks which .h files each .c depends on)
-include $(OBJS:.o=.d)

%.d: %.c
	$(CC) -MM $< > $@

clean:
	rm -f $(OBJS) $(TARGET) *.d

.PHONY: all clean

# Usage:
# make          — build
# make clean    — remove build artifacts
# make -j4      — parallel build using 4 cores

Comparing to Python

Here's how you might have written similar code in Python:

PY
Python (What you know)
# pyproject.toml (modern Python build)
# [build-system]
# requires = ["setuptools"]
# build-backend = "setuptools.build_meta"
#
# [project]
# name = "myapp"
# dependencies = ["requests", "pytest"]

# Commands:
# pip install -e .         — install in dev mode
# pip install -r requirements.txt
# python -m pytest         — run tests
# python -m build          — build distribution
Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

C
In C:

Makefile uses tab-indented recipe lines — spaces cause 'missing separator' errors

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

C
In C:

make only rebuilds targets whose prerequisites (source files) are newer — incremental builds

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

C
In C:

Automatic variables: $@ = target name, $< = first prerequisite, $^ = all prerequisites

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

C
In C:

CFLAGS -Wall -Wextra enables warnings; -g adds debug info for gdb; -O2 for optimised release

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

C
In C:

Python ships a standard library and venv; C has no package manager — libraries are installed system-wide (apt/brew) or vendored

Step-by-Step Breakdown

1. Basic Makefile Structure

A Makefile is a list of rules: target: dependencies followed by TAB-indented shell commands. make runs the first target ('all') by default.

PY
Python
# Python: python main.py
# No build step needed
C
C
CC = gcc
CFLAGS = -Wall -std=c11

all: program

program: main.o util.o
	$(CC) $(CFLAGS) -o program main.o util.o

main.o: main.c util.h
	$(CC) $(CFLAGS) -c main.c

util.o: util.c util.h
	$(CC) $(CFLAGS) -c util.c
Common Pitfall
Recipe lines MUST start with a real TAB character, not spaces. Most editors can be configured to preserve tabs in Makefiles.

2. Pattern Rules

%.o: %.c is a pattern rule — applies to any .o that needs to be built from its matching .c file. Avoids repeating compile rules.

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

# $< = the .c prerequisite
# $@ = the .o target

3. CFLAGS and Common Options

Control compilation through CFLAGS. Use -g for debugging with gdb, -O2 for release optimisation, -Wall -Wextra to catch common bugs.

PY
Python
# Python: no compilation flags
C
C
# Debug build:
CFLAGS = -Wall -Wextra -std=c11 -g -fsanitize=address

# Release build:
CFLAGS = -Wall -std=c11 -O2 -DNDEBUG

# Build with:
make CFLAGS="-O2 -DNDEBUG"

4. Clean and Phony Targets

.PHONY declares targets that are not file names (like 'clean', 'all'). This prevents conflicts if a file named 'clean' exists.

C
C
clean:
	rm -f *.o program

.PHONY: all clean

# Run tests
test: program
	./run_tests.sh

.PHONY: test
Rule of Thumb
Always declare 'all', 'clean', 'test' as .PHONY targets. Run 'make -j$(nproc)' to use all CPU cores for faster parallel builds.

Common Mistakes

When coming from Python, developers often make these mistakes:

  • Makefile uses tab-indented recipe lines — spaces cause 'missing separator' errors
  • make only rebuilds targets whose prerequisites (source files) are newer — incremental builds
  • Automatic variables: $@ = target name, $< = first prerequisite, $^ = all prerequisites
Common Pitfall
Don't assume C works exactly like Python. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • Makefile: target: prerequisites followed by TAB-indented recipes — make only rebuilds stale targets
  • Pattern rule %.o: %.c with $< (source) and $@ (target) avoids repeating compile rules for each file
  • CFLAGS -Wall -Wextra -g for dev; -O2 -DNDEBUG for release
  • .PHONY all clean — prevent conflicts with files named 'all' or 'clean'
  • make -j4 enables parallel compilation across 4 cores — essential for large projects
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your Python code in C to practice these concepts.
PreviousFinish