GNU Make is a tool that’s used to create executables and other non-source files from a program's source files. For example, we use it to generate our OBC-firmware.out
executable which is then flashed onto the RM46 microcontroller.
Make uses a Makefile to learn how to build the program. The Makefile lists all the non-source files (including the executable) and the steps to generate them from the source files. When you write a program, you can write a Makefile for it, so you can use GNU Make to automatically build the program.
If you’re interested in how a C source file gets turned into an executable, take a look at the C compilation process here.
To install Make on Ubuntu, try:
sudo apt-get update
sudo apt-get install build-essential # Installs make, along with some other tools
make -version # Should return the version of make if installed correctly
This is the Makefile we’ll be dissecting in the following sections.
CC = gcc # gcc is a compiler by the GNU Project
CFLAGS = -g -Wall # These are build flags which enable certain compiler functionality
HEADERS = program.h headers.h # Include files that we're dependent on
OBJECTS = program.o # Object files that we're dependent on
.PHONY: all
all: hello-world.out
.PHONY: hello-world.out
hello-world.out: $(OBJECTS)
$(CC) $(OBJECTS) -o $@
%.o: %.c $(HEADERS)
$(CC)-c $< -o $@
.PHONY: clean
clean:
-rm -f $(OBJECTS)
-rm -f hello-world.out
One way to assign a value to a variable in a Makefile is with the =
operator. There are some other operators, like :=
and ?=
, which are slightly different. We’ll ignore these for now though.
CC = gcc # gcc is a compiler by the GNU Project
CFLAGS = -g -Wall # These are build flags which enable certain compiler functionality
HEADERS = program.h headers.h # Include files that we're dependent on
OBJECTS = program.o # Object files that we're dependent on
To use any of these variables throughout the Makefile, you can use the $
operator. For example, if you’d like to use the CC variable, then you can write $(CC)
Make has some automatic variables that you can see are used throughout the Makefile. Here’s what some of them mean:
$@
→ The name of the target (Targets are covered in the next section)$<
→ The name of the first dependency (Dependencies are covered in the next section)