Fundamentals 9 min read

Mastering Makefiles: From a Simple One‑Line Rule to Smart Automation

This step‑by‑step tutorial shows how to write a Makefile for a tiny C program, then progressively improves it with separate object files, variables, pattern rules, and built‑in functions like wildcard and patsubst, while explaining each concept and its benefits.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Mastering Makefiles: From a Simple One‑Line Rule to Smart Automation

1. Introduction

After learning the basics of Makefiles, you can start writing your own. Although tools exist to generate Makefiles automatically, writing them manually deepens understanding and gives you full control over future project builds.

2. Sample Source Code

The example program consists of main.c that calls two functions defined in fun1.c and fun2.c:

// main.c
int main() {
    printf("hello world
");
    fun1();
    fun2();
}

// fun1.c
void fun1() {
    printf("this is fun1
");
}

// fun2.c
void fun2() {
    printf("this is fun2
");
}

3. First Version – A Single Rule

The whole program can be compiled with a single command: gcc main.c fun1.c fun2.c -o app Translating that command into a Makefile yields:

app: main.c fun1.c fun2.c
    gcc main.c fun1.c fun2.c -o app

This version works for tiny projects but has two major drawbacks:

It does not scale to large codebases with many source files.

Any change to a single source forces a full recompilation.

4. Second Version – Separate Object Files

To avoid recompiling everything, each source file is compiled into an object file first:

main.o: main.c
    gcc -c main.c -o main.o

The complete Makefile becomes:

app: main.o fun1.o fun2.o
    gcc main.o fun1.o fun2.o -o app

main.o: main.c
    gcc -c main.c -o main.o

fun1.o: fun1.c
    gcc -c fun1.c -o fun1.o

fun2.o: fun2.c
    gcc -c fun2.c -o fun2.o

Now only the modified file needs recompilation, but the file list is still hard‑coded and contains duplicated patterns.

5. Third Version – Variables and Pattern Rule

Introduce variables to avoid repetition and a pattern rule to handle all object files uniformly:

obj = main.o fun1.o fun2.o
target = app
CC = gcc

$(target): $(obj)
    $(CC) $(obj) -o $(target)

%.o: %.c
    $(CC) -c $< -o $@

The automatic variables $< (first prerequisite) and $@ (target) make the rule generic. Remaining issues:

The obj variable still requires manual updates when files are added or removed.

For projects with many sources, the variable becomes long and error‑prone.

6. Fourth Version – Wildcard and Patsubst Functions

Use Make’s built‑in functions to discover source files automatically and generate the object list:

src = $(wildcard ./*.c)
obj = $(patsubst %.c, %.o, $(src))
# Equivalent: obj = $(src:%.c=%.o)

target = app
CC = gcc

$(target): $(obj)
    $(CC) $(obj) -o $(target)

%.o: %.c
    $(CC) -c $< -o $@

.PHONY: clean
clean:
    rm -rf $(obj) $(target)

The wildcard function finds all .c files in the current directory, while patsubst converts them to corresponding .o files. The .PHONY target clean removes intermediate and final binaries.

7. Conclusion

Writing Makefiles by hand reinforces the underlying concepts of incremental compilation and build automation. By progressing from a single‑line rule to a fully automated Makefile that discovers sources, defines variables, and uses pattern rules, you gain a solid foundation for managing larger C projects.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Build AutomationC programmingMakefilegccMakefile Tutorial
Liangxu Linux
Written by

Liangxu Linux

Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.