Makefile
make is a utility that helps keep your object code and executable
files up-to-date. It automates the compilation process by checking
dependencies and only recompiling files that have changed.
The make utility looks for a file named makefile (or Makefile)
in the current directory, which contains the rules you’ve written
to define how your files should be compiled and linked.
Why Make?
Section titled “Why Make?”Using a makefile simplifies the process of compiling and linking your
C++ programs. Instead of typing long and complex commands every time you
want to compile your code, a makefile allows you to automate the process
with a single, simple command. This becomes especially useful as your
programs grow and involve multiple files, making make an essential tool
for efficient development.
Syntax
Section titled “Syntax”Makefiles follow a specific syntax to define rules and instructions for compiling and linking your programs. In this section, we’ll explore the basic structure and components, including how to add comments and define rules.
Commenting
Section titled “Commenting”You can make single-line comments in a makefile by starting the line
with a #:
# A comment in a makefileMake Rule
Section titled “Make Rule”A make rule defines how a specific file (the target) is created or updated. It consists of three main parts:
- Target: The file to be created or updated (e.g., an object file or executable).
- Prerequisite(s): The file(s) the target depends on, such as source files or header files.
- Recipe Command(s): The shell commands to generate or update the target.
target: Prerequisite(s) recipe command(s)hello.o : hello.cc g++ -c hello.cc-
The rule above says the target
hello.ois dependent on the prerequisite hello.cc -
When you enter
make hello.ointo the terminal, it will check to see ifhello.cchas been updated more recently thanhello.o, and if so, the recipe command will execute:
make hello.og++ -c hello.ccFlags are options passed to the compiler to control how your program is compiled. In this course, the following flags will be used:
-Wall: Enables most compiler warnings, helping you identify potential issues in your code.-std=c++17: Specifies that the program should be compiled using the C++17 standard.
Lets update the makefile to include these flags:
hello.o : hello.cc g++ -c -Wall -std=c++17 hello.ccMultiple Rules
Section titled “Multiple Rules”Makefiles allow you to define multiple rules, each with specific commands, to handle different parts of the compilation process. For example, you can create separate rules to compile individual source files, link them into an executable, and even 🚀 run the program.
The following updates the makefile to compile, link, and execute a program:
# Compilehello.o : hello.cc g++ -c -Wall -std=c++17 hello.cc
# Link and Executehello : hello.o g++ -Wall -std=c++17 hello.o -o hello ./hello// Copyright 2024 CSCE240#include <iostream>
using std::cout;using std::endl;
int main() { cout << "Hello makefile!" << endl; return 0;}make hellog++ -c -Wall -std=c++17 hello.ccg++ -Wall -std=c++17 hello.o -o hello./helloHello makefile!-
make hellowill first examine the rule for prerequisite hello.o, and run the recipeg++ -c -Wall -std=c++17 hello.cc -
Then it will check if
hello.ohas been updated more recently than the executablehelloand, if so, the recipe below will executeg++ -Wall -std=c++17 hello.o -o hello -
Finally it will run the command to execute the
helloprogram./hello
Variables
Section titled “Variables”Variables in makefiles are useful for reducing repetition and minimizing the
chance of errors. Instead of typing out long commands or file names multiple
times, you can define them once as a variable and reuse them throughout your
makefile.
The following is the basic syntax:
# Definevariable_name = value# Use Variable$(variable_name)The following are common variables found in the course:
compiler = g++flags = -Wall -std=c++17compile = $(compiler) -clink = $(compiler) $(flags) -o $@Makefiles include several built-in variables that can simplify your commands by automatically referring to parts of a rule:
$<: Represents the first prerequisite in the rule.$^: Represents all prerequisites in the rule.$@: Represents the target of the rule.
Lets update the makefile we’ve been working on with variables:
# Variablescompiler = g++flags = -Wall -std=c++17compile = $(compiler) $(flags) -clink = $(compiler) $(flags)
# Compilehello.o : hello.cc $(compile) $<
# Linkhello : hello.o $(link) $^ -o $@ ./$@A rule you’ll encounter in each makefile in this course is clean. It
is a rule to remove all of the object code files, executable files, and
any other temporary files in the directory.
clean : rm *.o helloWhat the command is saying is “remove any files with a .o extension and any file that is
called hello” which is the name chosen for the executable.
Lets finalize our makefile, update the source code, execute our program, and clean our folder:
# Variablescompiler = g++flags = -Wall -std=c++17compile = $(compiler) $(flags) -clink = $(compiler) $(flags)
# Compilehello.o : hello.cc $(compile) $<
# Link and Executehello : hello.o $(link) $^ -o $@ ./$@
# Clean Folderclean : rm *.o hello// Copyright 2024 CSCE240#include <iostream>
using std::cout;using std::endl;
int main() { cout << "Hello makefile!" << endl; cout << "Thanks for being around!" << endl; return 0;}make hellog++ -Wall -std=c++17 -c hello.ccg++ -Wall -std=c++17 hello.o -o hello./helloHello makefile!Thanks for being around!make cleanrm *.o hello