Module 7: Build Automation with Make
- First read this page then start the module with the GitHub classroom link below.
- Github Classroom Link: https://classroom.github.com/a/XGPs_SzF
Compilation
When you compile a C++ program, the compiler often does the following steps:
- Preprocessing: Handles macros, #includedirectives, and other preprocessor commands.
- Compilation: Translates C++ code into assembly language. This is where a .sfile can be generated if desired.
- Assembly: Converts the assembly code into machine code, producing an object file (usually with a .oor.objextension).
- Linking: Combines multiple object files and resolves references to produce the final executable or shared library.

Exercise 1
Go to the exercise1 directory of your module 8 GitHub repository. Put your answers to the questions below in the README.md in your module 8 GitHub repository.
- Run the following commands to inspect the file type of each file.
    $ file calculate.cpp $ file functions.cpp $ file functions.h
- Read the contents of the calculate.cpp,functions.cpp, andfunctions.hfile.
- What is the purpose of including the functions.hfile incalculate.cpp?
- Run the following commands to run the preprocessing step.
    $ g++ -E -P calculate.cpp > calculate.i $ g++ -E -P functions.cpp > functions.i
- Read the contents of calculate.iandfunctions.i.
- What has changed compared to the .cppversions of these files?
- Now run the following commands to run the compilation step.
    $ g++ -S calculate.i $ g++ -S functions.i
- Run the following commands to inspect the file type of each file.
    $ file calculate.s $ file functions.s
- Read the contents of calculate.sandfunctions.s.
- What has changed compared to the .iversions of these files?
- Now run the following commands to run the assembly step.
    $ g++ -c calculate.s $ g++ -c functions.s
- Run the following commands to inspect the file type of each file.
    $ file calculate.o $ file functions.o
- Read the contents of the calculate.oandfunctions.oby running.$ xxd -bits calculate.o $ xxd -bits functions.o
- What has changed compared to the .sversions of these files?
- Now run the following command to run the linking step.
    $ g++ calculate.o functions.o -o calculate
- Why did we have to provide both .ofiles at the same time when linking?
- Run the following commands to inspect the file type of the executable.
    $ file calculate
- How is the calculateexecutable file different from the.ofiles?
- Run the executable.
    $ ./calculate
- In Linux (and Unix-like systems), the return value (or exit status) of the last command executed is stored in a special shell variable ?. You can access this value using$?.$ echo $?
- Is the return value what you expected from running calculate?
Build Automation Tools: Make
Makefile: The make utility reads a special file known as a makefile.
- The makefile (or Makefile) describes the files involved in the project and the dependencies among them.
- Each group of lines in a makefile has the following form.
    target: dependencies <Tab> commands
- In this context,
    - target is a file to be created
- dependencies is a list of files on which the target depends
- commands is a list of commands used to (re)create the target.
 
- If any of the files in a dependency list is modified, make will recompile and/or relink the target.
- Important: a Tabcharacter must precede the commands — not spaces.
Exercise 2
Go to the exercise2 directory of your module 8 GitHub repository. Put your answers to the questions below in the README.md in your module 8 GitHub repository.
- Review the Makefilein theexercise2directory.
- Run the makecommand. Copy and paste the result of issuing the make command.
- Run the makecommand again. Copy and paste the result of issuing the make command.
- Run the commands:
    $ touch functions.h $ makeCopy and paste the result of issuing both commands. 
- What did the touchcommand do in this case (man touch)?
Exercise 3
Go to the exercise3 directory of your module 8 GitHub repository. Put your answers to the questions below in the README.md in your module 8 GitHub repository.
- One way to avoid having all files be recompiled each time is to make use of object files.
- To create an object file for the hello.cpp source file, you could issue the command g++ -c hello.cpp(but do not do so here).
- The result would be a file hello.o. This file is not executable because no linking has taken place, only compilation — the result of using the-cflag.
- Create a rule in your Makefilefor creatinghello.osimilar to the following (remember tab, not spaces!):hello.o: hello.cpp functions.h g++ -g -Wall -c hello.cpp
- Notice that the dependencies for hello.oarehello.cppandfunctions.h.
- The hello.cppsource file as a dependency should be obvious. The function.h is also a dependency because it is included in the file hello.cpp.
- Now create similar rules for creating main.o and factorial.o. (What dependencies do these two need? Make sure to modify the corresponding commands in the current Makefile as well.)
- Run make. List all.ofiles created by the make command.
- Run make. Explain the result.
- Run make main.o. Copy and paste the result of issuing this command.
- Run
    $ make factorial.o $ ls -alIs there an executable present for running main? 
- Create another rule as the last rule in Makefile that will create the target hellobased on the dependencieshello.o,main.o, andfactorial.o. Hint:g++ hello.o main.o factorial.o -o hello
- Run:
    $ make hello $ ./helloCopy and paste the output from issuing both commands. 
- Run:
    $ rm *.o hello $ make $ ./helloCopy and paste the output from issuing the commands. 
- Explain the previous output.
- Make the necessary modification to have hellobe the default target created bymake.
- Run:
    $ touch functions.h $ makeCopy and paste the output from issuing the commands. 
- Explain the previous output.
- Run:
    $ touch hello.cpp $ makeCopy and paste the output from issuing the commands. 
- Explain the previous output.
- Run: rm *.o hello
- Could we get make to handle cleanup work like this for us? Yes — the target does not have to be a file-to-be-created. In the examples we have seen thus far, the command has been a compile command which naturally creates a file. We can issue other command-prompt commands that do not result in a created file. The typical way to have make handle the cleanup is to create a new rule at the end of your makefile. The rule should have a target called clean(no dependencies) with the command/bin/rm -f *.o hello. Add this rule to the endMakefile.
- Run:
    $ make $ make clean
- Copy and paste the output from issuing the commands.
- Should the cleantarget be first in the makefile? Explain.