Skip to main content

Makefile

Why do Makefiles exist?

A Makefile is a special file used by the make utility to automate the build process of software projects. It defines a set of rules that dictate how to compile and link programs. When working on a project with multiple source files and dependencies, a Makefile can greatly simplify the build process by specifying:

  1. Targets: These are typically files that you want to generate, like executables or object files. A target can also represent a task, like running tests or cleaning up compiled files.

  2. Dependencies: Files or targets that must be up-to-date before a target can be built. For example, a .c file depends on a corresponding .h header file.

  3. Commands: Shell commands to be executed to build the target. These typically include commands like gcc for compiling or g++ for linking.

Here's an example dependency graph that you might build with Make. If any file's dependencies changes, then the file will get recompiled:

dependency_graph.png

Interpreted languages like Python, Ruby, and raw Javascript don't require an analogue to Makefiles. The goal of Makefiles is to compile whatever files need to be compiled, based on what files have changed. But when files in interpreted languages change, nothing needs to get recompiled. When the program runs, the most recent version of the file is used. However, it can automate tasks in other environments, like managing dependencies in a Python or JavaScript project.

Basic Structure: 

target: dependencies
    command

Example Make file for Simple C++ project

# Compiler and flags
CC = gcc
CFLAGS = -Wall -g

# Target program
TARGET = my_program

# Source files
SRCS = main.c foo.c bar.c

# Object files (generated from source files)
OBJS = $(SRCS:.c=.o)

# Default target
all: $(TARGET)

# Rule to build the target program
$(TARGET): $(OBJS)
    $(CC) $(CFLAGS) -o $(TARGET) $(OBJS)

# Rule to build object files from source files
%.o: %.c
    $(CC) $(CFLAGS) -c $<

# Clean rule to remove generated files
clean:
    rm -f $(OBJS) $(TARGET)

Key Points:

  • $(CC) and $(CFLAGS): Variables for the compiler and flags.
  • $< and $@: Special automatic variables where $< refers to the first dependency, and $@ refers to the target.
  • clean target: Commonly used to delete object files and executables after building.

Why Use Makefiles?

  • Efficiency: Only recompiles files that have changed.
  • Automation: Simplifies repetitive tasks like compilation, linking, or testing.
  • Portability: Works across different systems without needing to write custom build scripts.