Makefiles


Table of Contents

Make is used to manage executables and program compilation, and it is very effective for large projects because it recompiles only what has changed.

Make is also useful for various small tasks, such as archiving files, etc.

How to use Make

To use make, first create a file named : Makefile

Here is what a makefile consists of :

<target> : <prerequisites>
	<command>

Makefiles can define variables (strongly recommended); these variables follow common conventions, are optional, and save a lot of time.

# CC / CXX -> CXX = C++ -> Compilers
# CFLAGS / CXXFLAGS -> Compilation flags
# LDFLAGS -> Linker flags
# SRC -> where the .c files are located
# OBJ -> selects the .o files
# EXEC -> executable name
# Special (automatic) variables
$@ -> target name
$< -> first prerequisite name
$^ -> list of prerequisites
$? -> prerequisites newer than the target
$* -> filename stem without its extension

# Variable declarations:
CC = gcc
EXEC = prog
CFLAGS = -Wall -Wextra -Werror
SRC = $(wildcard *.c) -> Tell it to take all .c files
OBJ = $(SRC:.c=.o) -> Same as SRC but replace .c with .o

# To reference a variable, just write:
$(CC)

It is possible to write conditionals in a makefile.

WINDOWS = yes
ifeq ($(WINDOWS), yes) # If the WINDOWS variable equals yes (ifeq = if equal)
    $(EXEC) = prog.exe
else
    $(EXEC) = prog
endif
# Makefile layout

#===================================================================#
Layout "BruteForce"

all : prog

prog : main.o code.o # Create prog from main.o and code.o; if they don't exist, build them below *1
    gcc -o prog main.o code.o # prog depends on main.o and code.o

main.o : main.c # Build main.o here *2
    gcc -o main.o main.c # main.o depends on main.c
     
code.o : code.c # Then build code.o and go back up *3
    gcc -o code.o code.c # code.o depends on code.c
	
#===================================================================#
Layout "Fast but not safe"

all : $(EXEC) # Same idea as above

# Use % to mean “any”
%.o : %.c # Like (*2 / *3): every .o depends on the corresponding .c
    $(CC) -o $(OBJ) -c $(SRC) # Same command as the two above (*2 / *3)
     
$(EXEC) : $(OBJ) # Then build the target program (*1)
    $(CC) -o $(EXEC) $(OBJ) # Same idea as (*1)
	
#=====================================================================#
Layout "Safe when files depend on each other"

all : $(EXEC)

%.o : %.c
    $(CC) -o $@ -c $< # $@ = target (%.o), $< = first prerequisite (%.c)
     
$(EXEC) : $(OBJ)
    $(CC) -o $@ -c $^ # $@ = target ($(EXEC)), $^ = list of prerequisites ($(OBJ)), i.e., all .o files

You can also create targets to organize your files, for example a clean target.​

clean : # No prerequisites needed here
    rm -rf *.o

Sources : Makefile tutorial

Share :

Related Posts

Linked Lists

Linked Lists

Lists do not natively exist in C; they are the result of manipulating pointers and structures.

Read More