Homework 3: Make Your Makefile
Now it’s time to make your own Makefile
! The Makefile
will contain all the compilation and linking steps to make an executable called our-movie
. You and your partner (together or individually) should complete the written questions in Part 1 before working on this part.
In the asciimation
directory, you'll find a file called our-movie.cpp
, which contains a main
function. There are also two pairs of header/implementation files,
sprite.cpp
andsprite.hpp
, which you’ll use to create ASCII-art–based “characters”asciimation.cpp
andasciimation.hpp
, which you’ll use to coordinate the “characters” on the screen
Reminder: Compiling by Hand
If you compiled this code by hand, you would have to run several complex commands,
clang++ -c -std=c++17 -g -Wall -Wextra -pedantic -isystem /usr/include/opencv4 our-movie.cpp
to build the object file our-movie.o
;
clang++ -c -std=c++17 -g -Wall -Wextra -pedantic -isystem /usr/include/opencv4 asciimation.cpp
to build the object file asciimation.o
;
clang++ -c -std=c++17 -g -Wall -Wextra -pedantic -isystem /usr/include/opencv4 sprite.cpp
to build the object file sprite.o
; and, finally,
clang++ -o our-movie -std=c++17 -g -Wall -Wextra -pedantic our-movie.o asciimation.o sprite.o -lopencv_imgcodecs -lopencv_core -lopencv_imgproc -lopencv_video -lopencv_videoio
to link the object files and various library files into the executable our-movie
. (Note: All the OpenCV-related include options are explained in the hints at the bottom of the page.
Remembering all the different includes and arguments for clang++
is a pain, and you will also have to figure which commands you need to rerun if you make changes to one or more files. A makefile for the project allows you to figure things out once and then let make
decide what needs to be rebuilt for later builds.
Task: Create Your Makefile
Create a makefile for your project (which, by convention, is called Makefile
when there is just one) in the asciimation
directory with all of the commands you’ll need to compile the our-movie
executable. You will be graded on how “well” your Makefile performs; for example, compiling only what’s necessary for any given change and doing those compilations correctly.
Include both the all:
and clean:
targets in your Makefile
.
If you're looking for an example you can use as a starting point, the segfault-generator
directory contains an example of a very basic Makefile
, as did the make
exercise that you saw at the start of the written part of this assignment (which also had more advanced examples, with variables).
Note that you do not have to comment your Makefile
as we did in our example. We added those comments for your benefit! For basic makefiles like the ones we will use in CS 70, it's probably not necessary to add comments. (Of course you can always include comments if you want.)
Make sure you read the hints below for some very useful information about Makefiles!
Helpful Hints
It's just called Makefile
By default, the make
program looks for a file called Makefile
. If you wanted to have lots of make files, you could use the extension .mak
, but, by default, the name is Makefile
with no file extension. And yes, it's a capital M
at the front.
Test Your Makefile
(Use cs70-make
)
Once you write your Makefile
, you should be able to successfully run cs70-make
or make
to generate any of the .o
files, and to link the .o
files together into the executable our-movie
.
Why would I use
cs70-make
rather thanmake
?The
cs70-make
program explains everything its doing and why, which can be helpful for checking that yourMakefile
is working properly.It's also often more likely to give an error when you've made a mistake in your
Makefile
. Sometimes, regularmake
assumes that you're an expert and you meant to do something weird.
Indent with Tabs (in Makefiles)
The syntax for Makefiles requires that the line below the target and dependencies begins with a literal tab character followed by the command it should run. Check the example Makefile
you were given for examples. Note that in the bottom bar in VS Code there is a convenient way to switch between using tabs/spaces for a given file. (If you have the Makefile support that VSCode offers to install, it will automatically set the indentation character to a tab in Makefiles.)
Headers that Include Headers
Remember that a header file can include another header file. If a .cpp
file includes a .hpp
file that includes another .hpp
file, it depends on both of them! That is, if either header file changes, the .cpp
file should be recompiled to stay up-to-date.
Fancy Makefile Tricks Are Optional
You don’t have to use the fancy tricks described on the Makefile
resource page (or any of the terrifying shortcuts found on the internet)—if your Makefile
doesn’t use any tricks fancier than the example provided for segfaultGenerator
, that’s fine.
Using the OpenCV Library
Like Homeworks 1 & 2, ASCIImation
uses OpenCV, this time to generate a video. So your code that uses OpenCV will need the same -isystem /usr/include/opencv4
option when you compile it and depends on a bunch of libraries added when linking. The video parts of OpenCV need access to even more parts of the library than our previous projects. If you give the name OPENCV_LIBS
to all of those libraries at the top of your Makefile
,
OPENCV_LIBS=-lopencv_imgcodecs -lopencv_core -lopencv_imgproc -lopencv_video -lopencv_videoio
then you can link in all the extra libraries by including OPENCV_LIBS
in your compilation command. For example, if generateSegfault
required opencv
(it doesn’t, but just as a hypothetical), you’d write the following line to do the linking:
clang++ -o generateSegfault -g -std=c++11 -pedantic -Wall -Wextra generateSegfault.o helloSayer.o $(OPENCV_LIBS)
(When logged in, completion status appears here.)