Write a Makefile
In this part, you'll create a Makefile
to simplify building your code by handing the compiling and linking process for all your files. (You may want to refer back to the help page on Makefiles.)
The Train
and Car
classes are used by the test program we've provided in testtrain.cpp
, which you'll compile into the executable testtrain
.
The testtrain
program contains several test functions that you can call to make sure that your Car
and Train
classes are working as desired. It is also the first appearance of the CS 70 testing framework that you'll use to write your own tests in future assignments.
Implementation Steps
Create your Makefile
It's often useful to use an existing makefile as a template.
We'd recommend using the contents of either
example2.mak
orexample3.mak
from the make exercise as a starting point.
Your Makefile
should
-
Use at least three variables,
CXX
,CXXFLAGS
, andLDFLAGS
, defined as follows:CXX = clang++ CXXFLAGS = -gdwarf-4 -Wall -Wextra -pedantic -std=c++17 LDFLAGS = -ltestinglogger
-
Provide the standard “phony” targets of
all
andclean
, whereall
ensures ourtesttrain
executable gets built (by listing it as a prerequisite!).- It should be the first target in the
Makefile
.
- It should be the first target in the
clean
removes ourtesttrain
executable and all the.o
files.
-
Provide a target to build our
testtrain
executable. Be sure to list all the.o
files it needs as prerequisites.- Use your variables, like
$(CXX)
and$(CXXFLAGS)
- Remember the executable name is specified with
-o
- The executable needs to also be linked with the CS 70 testinglogger library—the necessary argument to the compiler should be in
$(LDFLAGS)
.
- Use your variables, like
-
Provide targets to build each of the necessary
.o
files from your.cpp
files. Each one must have the right prerequisites.- Again, when building
.o
files, you should use your variables, like$(CXX)
and$(CXXFLAGS)
- Remember that we generate an object file by passing the
-c
option.
- Again, when building
Naming Your Makefile
Note that both our autograder and the make
program will be looking for a file called Makefile
. As with all filenames in CS 70, exact names and upper/lower case matters, so don't call it something else, like makeFile
, Cakefile
, or Makefile.mak
.
In fact, a misnamed Makefile is particularly pernicious, because if the standard make
program doesn't find a Makefile
(or your Makefile
is missing a needed rule!), it may carry on anyway, trying to make a guess as to what it should do, using built-in rules that are, alas, very often wrong. Make sure your file is named Makefile
, with an uppercase letter M
and no extension.
“Make” sure, huh? Very punny. Meh.
Use Tab to Indent in a Makefile
In a Makefile
, the commands to execute need to be indented with a single Tab character, not spaces.
In theory, a good code editor will automatically recognize that you're editing a Makefile
and switch to a mode that customizes commands, changes syntax coloring, and so on. In that Makefile mode, your editor should change the behavior of the Tab key on your keyboard to insert a tab character instead of the spaces we use in C++ code and header files.
In VS Code, there's a menu for the file type in the lower-right corner that you can use to override what ever guess the editor made. Other editors have similar ways of changing the file type.
You can always check to make sure your indentation is using tabs instead of spaces by simply moving your editor's cursor over the indented whitespace. If your cursor moves in a big jump (e.g., eight characters in one go), it's a tab character, but if it moves one character at a time, you've got spaces. Most editors also have a way to show “invisible” characters such as spaces, tabs, line-ending characters, and so on.
If make
is complaining about a “missing separator” or similar, it's probably spaces instead of tabs.
Test Your Makefile
Once your rules are set up, you should be able to run cs70-make
to compile and link your code. (Just using make
also works, but cs70-make
explains what it is doing and why, which can help you figure out problems with your Makefile.)
Experiment by make
ing various targets after editing code and header files to make sure that your rules are doing what you want them to do.
Remember: Heed Compiler Warnings!
As ever, if building your code produces warnings or errors, fix them right away.
cs70-make
Is Your Friend
The CS 70 Docker image provides a program called cs70-make
, which works just like a standard make
program, but also provides a stream of useful information about what it's doing. (Believe it or not, cs70-make
actually gives significantly less output than make
does with its verbose option.)
cs70-make
provides similar functionality to the original make
program from the 1970s, which is more than sufficient to build our CS 70 code (or even some far larger projects). Over the years make
programs (particularly the widely used GNU make
) have added “extra features”; sometimes making them more complicated for inexperienced coders to use.
The autograder will build your code using GNU make
, but if your Makefile
works fine with cs70-make
, it should work with the real make
; if you're worried, you can always test it yourself!
All Good?
If running cs70-make
doesn't produce compiler errors, responds correctly when you edit various files, and, as far you can tell, your Makefile is written correctly, you are ready to move on to the next step of this homework.
If you're convinced your Makefile
is working well, you can also switch to using the regular (less chatty) make
program.
Hay! In
CXXFLAGS
, what's with-gdwarf-4
, don't we normally just use-g
?It's basically the same as
-g
(the option that tells the compiler to include extra information to help when debugging) but we need to use this longer variant to make the Valgrind tool happy.Here's all the details! The people who make Valgrind haven't been keeping up. Our compiler,
clang++
, defaults to the newer “DWARF-5” format for debugging information, but Valgrind doesn't understand that yet, so we have to use the older “DWARF-4” format instead.Meh.
Exactly.
(When logged in, completion status appears here.)