Makefiles work by defining a set of rules that specify how to build and manage dependencies for a project. The make utility reads the Makefile and executes the defined commands based on the specified targets and their dependencies. Here's a breakdown of how Makefiles work:
Structure of a Makefile
-
Targets: A target is typically a file that is generated by a command, such as an executable or an object file. It can also be a label for a specific action (e.g.,
clean). -
Dependencies: These are files that the target depends on. If any of the dependencies are newer than the target, the target will be rebuilt.
-
Commands: These are the shell commands that are executed to create or update the target. Commands must be indented with a TAB character.
Basic Workflow
-
Reading the Makefile: When you run the
makecommand, it looks for a file namedMakefileormakefilein the current directory. -
Evaluating Targets:
makeevaluates the first target in the Makefile. If the target is up to date (i.e., it exists and is not older than its dependencies),makedoes nothing. If it is out of date, it proceeds to execute the commands associated with that target. -
Checking Dependencies: For each target,
makechecks its dependencies. If any dependency is newer than the target,makewill execute the commands to rebuild the target. -
Executing Commands: The commands associated with the target are executed in the order they are defined. If a command fails (returns a non-zero exit status),
makestops execution unless specified otherwise. -
Special Targets: Makefiles can include special targets like
clean, which is often used to remove generated files and reset the project state.
Example
Here’s a simple example of a Makefile:
# Makefile example
CC = gcc
CFLAGS = -Wall
all: program
program: main.o utils.o
$(CC) -o program main.o utils.o
main.o: main.c
$(CC) $(CFLAGS) -c main.c
utils.o: utils.c
$(CC) $(CFLAGS) -c utils.c
clean:
rm -f *.o program
Explanation of the Example
- Targets:
program,main.o,utils.o, andcleanare targets. - Dependencies:
programdepends onmain.oandutils.o.main.odepends onmain.c, andutils.odepends onutils.c. - Commands: The commands under each target specify how to compile the source files and link them into an executable.
By using Makefiles, developers can automate the build process, manage dependencies efficiently, and simplify the workflow of compiling and linking code.
