Table of contents
Open Table of contents
Complier
The first thing we need to do is define the compiler and shell that we will be
using. In this example, we will be using gcc
and /bin/bash
, respectively. We
will also define the compiler flags that we will be using.
# The compiler executable.
CC := gcc
# The compiler flags.
CFLAGS := -Wall -Wextra -Werror -pedantic -std=c99
# The linker executable.
LD := gcc
# The linker flags.
LDFLAGS := -Wall -Wextra -Werror -pedantic -std=c99
# The shell executable.
SHELL := /bin/bash
Testing and Debugging
Next, we will define some variables that will be used for testing and debugging our project. We will define the name of the test executable, the name of the debug executable, and provide some flags that will be used by the memory checker and debugger.
# The memory checker executable.
MEMCHECK := valgrind
# The memory checker flags.
MEMCHECK_FLAGS := --leak-check=full --show-leak-kinds=all --track-origins=yes
# The debugger executable.
DEBUGGER := gdb
# The debugger flags.
DEBUGGER_FLAGS :=
# The name of the test input file
TEST_INPUT :=
# The name of the test output file
TEST_OUTPUT :=
# The name of the reference executable
REF_EXE :=
# The name of the reference output file
REF_OUTPUT :=
Directories
One of the cool things about make is we can set varibles to be the output of
shell commands by using the :=
operator. This way, we can define variables
that refer to directories related to the root directory of the project. We are
going to work under the assumption that the project has the following directory
structure:
.project/ # root directory of the project
├── include/ # header files
├── lib/ # external libraries
├── obj/ # object files
├── src/ # source files
└── target/ # build artifacts
├── debug/ # debug build
└── release/ # release build
To achieve this, we can define the following variables:
# top directory of project
TOP_DIR := $(shell pwd)
# directory to locate source files
SRC_DIR := $(TOP_DIR)/src
# directory to locate header files
INC_DIR := $(TOP_DIR)/include
# directory to locate external libraries files
LIB_DIR := $(TOP_DIR)/lib
# directory to locate object files
OBJ_DIR := $(TOP_DIR)/obj
# directory to place build artifacts
BUILD_DIR := $(TOP_DIR)/target/release/
Targets
Now that we have defined all the necessary variables, we can start defining the
targets that will be used to build our project. The first target that we will
define is the all
target, which will build the program.
# The default target.
.PHONY: all
all: $(BUILD_DIR)/$(TARGET)