COMP 2673 - Lab6 In-lab Assignment Goals: This lab is a tutorial on makefiles (provided by Prof. Scott Leutenneger). __________________________________________________________________________ COMMAND REFERENCE: __________________________________________________________________________ NAME script - make record of a terminal session SYNOPSIS script [ -a ] [ filename ] DESCRIPTION script makes a record of everything printed on your screen. The record is written to filename. If no file name is given, the record is saved in the file typescript. The script command forks and creates a sub-shell, accord- ing to the value of $SHELL, and records the text from this session. The script ends when the forked shell exits or when CTRL-D is typed. OPTIONS -a Append the session record to filename, rather than overwrite it. NOTES script places everything that appears on the screen in filename, including prompts. __________________________________________________________________________ Steps: 1. Change your present working directory to IntroToCS3. 2. Copy ~sarora/IntroToCS3/lab6.tar.gz to your present working directory. 3. Extract the assignment by typing: tar -xvzf lab6.tar.gz 4. Enter the newly created directory lab6. 5. Record your following session (using the script command above) in a file, which has the name lab6_yourname where yourname is "Your Name". Email this file to your TA at the end. 6. Follow the instructions below and actually do the examples: FIRST, you need to understand how separate compilation, linking, and archives work. Read in order (all files in subdirectory compilingStuff): compilingStuff/README.cc compilingStuff/README.g compilingStuff/README.ar compilingStuff/README.I compilingStuff/README.sum This directory contains a series of Makefiles that progressively teach you about the abilities of make. They should be looked at and executed in the following order: Makefile1 Makefile2 Makefile3 . . MakefileN (where N is the largest number) To exectute them, simply do: cp Makefile1 Makefile make Or, type: make -f Makefile1 The individual .C files that are being compiled together are pretty stupid, but the goal is to learn about make. The concepts extend to real programs. View the individual .C files as components of an overall product, the product can be configured to include all of the functions or only some, just like many real products provide you a base level of support and then make you purchase individual additional components to add to the functionality. Note, each Makefile has lots of comments explaining what they do. For each Makefile below follow the steps: 1) ... N) to see what it does. ======================================================================== Makefile1: A simple makefile, explicit in all commands, compiles a single program called "gold". This program includes all the possible functionality in the product Now try some simple tests to see how makefiles work. 1) type: % cp Makefile1 Makefile % make Note how it compiles each .o file, then links them all together in gold. 2) To run the "product" type: % gold 3) type: % touch half.C % make Note that it recompiles half.o, then relinks gold 4) type: % touch half.C square.C % make Note it recompiles half.o and square.o, then relinks gold. Every time, make redoes the minimal amount of work to rebuild the most current version of gold. 5) type: % make clean % make the make clean removes all the .o files so the make has to recompile everything ======================================================================= Makefile2: Still simple, but allows compilation of any of three different product versions: gold, silver, or bronze. To compile bronze type: make bronze To compile silver type: make silver To compile gold, type: make gold or just "make" since gold is the first target in the file. 1) type: % cp Makefile2 Makefile % make Note, it only compiles gold 2) type: % make silver Note it compiles silver. 3) type: % touch fact.C % make silver Note: fact.C is not a dependency of silver, hence it is not recompiled and silver is not relinked. 4) type: % make gold fact.C IS a dependency of gold, hence fact.o is recompiled, then gold is relinked to get the most recent version. ====================================================================== Makefile3 Same as Makefile2 except will compile all of bronze, silver, and gold. The only difference is the first line which states the dependencies of target "all" are bronze, silver, and gold. Since "all" is the first target, if you just type "make" it will build bronze, silver, and gold. Example: % touch *.C % make Notice how it first builds gold by compiling each of {fact,half,double,fact,main_gold}.C file than linking them all together. For bronze and silver it only needs to compile either main_bronze.C or main_silver.C and then link together the .o files. ====================================================================== Makefile4 Demo of macro definitions 1) % make -f Makefile4 the -f option tells specifies which makefile to use. If no "-f filename" is included the default is Makefile then makefile 2) % make -s -f Makefile 4 the -s optione suppresses the print command before executing each command. ====================================================================== Makefile5 Like Makefile 1, except uses macros OPTS, OBJS, and predefined macro CXX Every place $(OPTS) appears it is expanded to -O. Similar for $(OBJS). $(CXX) expands to "g++" 1) % touch *.C % make -f Makefile5 ====================================================================== Makefile6 Uses internal macros @ and ? $@ == the target $? == the list of prerequisites that are newer than the target Note: could not use $? in "g++ -gold ..." line since it needs to link ALL the .o files together, not just those that are newer than the target ====================================================================== Makefile7 # the following links in the library libspam.a gold : main_gold.o libspam.a ${CXX} ${OPTS} -o $@ main_gold.o -L. -lspam # this is how the library is created/maintained libspam.a: ${OBJS} ar cr libspam.a ${OBJS} 1) % make -f Makefile7 % touch fact.C % make -f Makefile7 => notice it recreates the library, then relinks it with main_gold ====================================================================== Makefile8 Differs from Makefile7 : libspam.a: ${OBJS} ar cr $@ $? Thus, only those OBJS files that are more recent then libspam.a are relinked into the library. Note, ar does not need the whole list, it just updates the library with any files specified keeping the old ones. This makes the ar command run faster. 1) % make -f Makefile7 % touch fact.C % make -f Makefile7 % touch fact.C % make -f Makefile8 => NOTE the difference in the ar command run ====================================================================== Makefile9 Functionally the same as Makefile1, but much more concise since it uses suffix rules. 1) % touch double.C % make -f Makefile9 ====================================================================== Makefile10 Uses suffix rules like Makefile10 but also includes the libary. ====================================================================== Makefile11 Problem with Makefile10, can not add the -O option into the g++ -c commands. This can be done by: OPTS = -O CXXFLAGS = ${OPTS} 1) % touch *.C % make -f Makefile10 => notice -O only used in compiling gold 2) % touch *.C % make -f Makefile11 => notice -O is used in EACH compile ====================================================================== Makefile12 This makefile shows how to compile gold silver and bronze assuming each links to the library libspam.a Note, the .o files are created by the suffix rules PROBLEM: Do the following: touch fact.C make -f Makefile12 bronze The makefile compiles fact.C to fact.o, replaces the old fact.o with the new one in libspam.a, and then relinks bronze. This is a waste! bronze does not use anything from fact.C, hence it would be nice to avoid this unnecessary compilation The problem is addressed in the next makefile.... ====================================================================== Makefile13 The makefile shows how to specify that bronze is only dependent on the half.o and double.o portions of libspam.a Now do: touch fact.C make -f Makefile13 bronze It simply says bronze is up to date. Note that silver is dependent on three of the .o files in libspam.a and since gold is dependent on all I just put in the whole libary as a dependency. The makefile can be made more succinct in terms of library dependencies as shown in the next Makefile ====================================================================== Makefile14 This makefile is really the exact same as Makefile13, only if you look at the dependencies on silver and bronze you will see multiple .o files are enclosed in one () thus being more concise ====================================================================== Makefile15 Usually .c and .C files include .h files. If one of these .h files is changed, one or more .C files need compiled, creating new .o files, thus necessitating relinking one more target programs. At the end of this makefile the dependencies on .h files are listed. Type: make -f Makefile15 touch fact.h make -f Makefile15 note that the .C files that include fact.h get recompiled and any targets dependent on these .o files get relinked ====================================================================== Makefile16 Keeping track of all the .h dependencies is very difficult. In addition usually programs are dependent on system .h files. Thus most compilers provide a flag for automating creating of these dependency rules for insertion in a makefile. g++ -M *.C > q will create all the dependencies. Just append this file (q) at the end of the makefile and you are done. This makefile has .h file dependency rules created this way. ====================================================================== **** Remember to email lab6_yourname to your TA at the end. ****