EECS 280 Tutorials
make
and Makefiles
The make
utility automates compiling a program. It reads a file that’s usually called Makefile
.
Prerequisites
This tutorial relies on command line tools. If you haven’t installed CLI tools on your machine yet, follow one of these tutorials first.
macOS | Windows | Linux |
We’re also assuming you are familiar with a text editor or IDE. If you haven’t already done so, follow one of these tutorials.
VS Code (recommended) | Visual Studio | Xcode |
Finally, you’ll need to be familiar with the command line interface (CLI). If you haven’t seen it yet, take a look at the Command Line Tutorial.
Example program
We’ll work in a directory called make-example
just for this tutorial.
$ mkdir make-example
Create a file called main.cpp
and copy-paste this Hello World program.
#include <iostream>
using namespace std;
int main() {
cout << "Hello World!\n";
}
Create a file called Makefile
and copy-paste this code.
CXX ?= g++
CXXFLAGS ?= -Wall -Werror -pedantic -g --std=c++17 -Wno-sign-compare -Wno-comment
# Run regression test
test: main.exe
./main.exe < main_test.in > main_test.out
diff main_test.out main_test.out.correct
echo PASS
# Compile the main executable
main.exe: main.cpp
$(CXX) $(CXXFLAGS) main.cpp -o main.exe
# Remove automatically generated files
clean :
rm -rvf *.exe *~ *.out *.dSYM *.stackdump
Your directory should look like this:
$ tree
.
├── Makefile
└── main.cpp
Compile
Compile manually, then remove the executable.
$ g++ -Wall -Werror -pedantic -g --std=c++17 -Wno-sign-compare -Wno-comment main.cpp -o main.exe
$ ./main.exe
Hello World!
$ rm main.exe
Compile using make
. Notice that it automated the long compile command.
$ make main.exe
g++ -Wall -Werror -pedantic -g --std=c++17 -Wno-sign-compare -Wno-comment main.cpp -o main.exe
Run the executable created by the previous make
command.
$ ./main.exe
Hello World!
Clean up using make
. Notice that it automated the rm
command.
$ make clean
rm -rvf *.exe *~ *.out *.dSYM *.stackdump
removed 'main.exe'
Test
Makefiles are useful for automating tests, sometimes called a regression test.
Put input (stdin) in a file. We’ll use main_test.in
in this example.
this program doesn't read stdin,
so this text doesn't matter
Put the correct output in a file. We’ll use main_test.out.correct
. In EECS 280 and EECS 281, a few correct output files are typically provided.
Hello World!
Run manually with input redirection and output redirection. Compare with diff
. No output means the files match.
$ ./main.exe < main_test.in > main_test.out
$ diff main_test.out main_test.out.correct
Run the regression test automatically with make
.
$ make test
./main.exe < main_test.in > main_test.out
diff main_test.out main_test.out.correct
Pro-tip: Run commands in parallel with make -j
.
$ make -j4 test
Makefile syntax
This section explains basic Makefile
syntax.
A Makefile
consists of rules that look like this:
target: prerequisites
recipe
This is a concrete example of a rule.
main.exe: main.cpp
g++ main.cpp -o main.exe
A target is usually the name of a file that is created by the rule, like main.exe
.
A prerequisite is a file that is used as input to create the target, like main.cpp
. There could be multiple prerequisites.
A recipe is a command that make
runs, like g++ main.cpp -o main.exe
. There might be more than one command.
Pitfall: Every recipe line must start with a TAB character.
A variable is helpful for avoiding duplication, like the compiler flags.
CXX ?= g++
# primer-spec-highlight-start
CXXFLAGS ?= -Wall -Werror -pedantic -g --std=c++17 -Wno-sign-compare -Wno-comment
# primer-spec-highlight-end
main.exe: main.cpp
# primer-spec-highlight-start
$(CXX) $(CXXFLAGS) main.cpp -o main.exe
# primer-spec-highlight-end
unit_tests.exe: unit_tests.cpp unit.cpp
# primer-spec-highlight-start
$(CXX) $(CXXFLAGS) unit_tests.cpp unit.cpp -o unit_tests.exe
# primer-spec-highlight-end
Acknowledgments
Original document written by Andrew DeOrio awdeorio@umich.edu.
This document is licensed under a Creative Commons Attribution-NonCommercial 4.0 License. You’re free to copy and share this document, but not to sell it. You may not share source code provided with this document.