CS 70

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

  • LHS Cow speaking

    It's often useful to use an existing makefile as a template.

  • RHS Cow speaking

    We'd recommend using the contents of either example2.mak or example3.mak from the make exercise as a starting point.

Your Makefile should

  1. Use at least three variables, CXX, CXXFLAGS, and LDFLAGS, defined as follows:

    CXX = clang++
    CXXFLAGS = -gdwarf-4 -Wall -Wextra -pedantic -std=c++17
    LDFLAGS = -ltestinglogger
    
  2. Provide the standard “phony” targets of all and clean, where

    • all ensures our testtrain executable gets built (by listing it as a prerequisite!).
      • It should be the first target in the Makefile.
    • clean removes our testtrain executable and all the .o files.
  3. 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).
  4. 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.

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.

  • Goat speaking

    “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 makeing 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.

  • Horse speaking

    Hay! In CXXFLAGS, what's with -gdwarf-4, don't we normally just use -g?

  • LHS Cow speaking

    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.

  • Rabbit speaking

    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.

  • Goat speaking

    Meh.

  • LHS Cow speaking

    Exactly.

To Complete This Part of the Assignment…

You'll know you're done with this part of the assignment when you've done all of the following:

(When logged in, completion status appears here.)