![]()
![]()
COMP2100
Lab 8: Make & RCSSummary
Some exercises to introduce the build tool `make' and the version control system `RCS'.
Aims
Give you some experience using make and writing simple Makefiles. You will need to use this knowledge in Assignment 3.
Give an introduction to using the RCS version control system.
Hints
The UNIX command touch is very useful when experimenting with make. Running the command `touch f' has the following effect:
If the file f does not exist, then an empty file with that name is created.
If the file f exists and is writable, then the time at which it was last updated is set to the time when the touch command was run.
Another useful thing to remember when experimenting with make is the -l option to ls. Typing ls -l shows the times at which files were last updated.
Note that the commands in a Makefile must be indented by a single tab character, not spaces. The file must also end with a new-line character, something Emacs does not always guarantee. These two invisible restrictions on Makefiles are the most annoying features of Make, and the most common source of errors by new users.
Exercise 1
Download the following files:
sort.c: A simple insertion sort routine.
sort.h: A header describing the sort.
harness.c: A simple, and quite ugly, test harness for the sort routine.
tests.txt: A list of test cases for the harness.
Note: the selection of these test cases leaves a lot to be desired.
expected.txt: The corresponding list of expected answers.
Now, perform the following steps:
Compile sort.c to get sort.o with the following command:
gcc -c -Wall sort.cThe `-c' means compile only; do not attempt to link with other modules to form an executable.
Compile harness.c to get harness.o similarly.
Link sort.o and harness.o to make an executable called harness with the following command:
gcc -o harness sort.o harness.oRun harness on tests.txt and place the output in output.txt.
Hint: You can do this using the UNIX shell I/O redirection symbols `<' and `>'.
If you compare the files output.txt and expected.txt (using the diff command), you will see there is a difference for Test 1. This is, in fact, caused by an error in the expected output for Test 1, but we'll come back to that later.
Exercise 2
Draw a diagram showing the dependencies between the various files in Exercise 1. Use the diagrams from Lecture 24 as your model.
Exercise 3
Construct a Makefile, which should be called `Makefile', that can be used to rebuild output.txt with the minimum amount of work whenever it is out of date with respect to the other files.
Test your Makefile by using the touch command to alter the time stamp on some of the other files, and then examining the actions that make subsequently performs. See the hint at the beginning of these exercises or the manual page for touch for more information on this command.
Exercise 4
Extend your Makefile so that it can automatically produce a file called `errors.txt' that contains the differences between output.txt and expected.txt.
Hint: Actually, this exercise is a little harder than it looks, and you do not yet have all the information you need to complete it. Nevertheless, the best way to proceed is to try to complete the exercise anyway. You should be able to get something that looks right and almost works. The following paragraph will help you finish it off.
By now you should have extended your Makefile with a rule to build the file errors.txt using the diff command. You should also have found than when you try to make errors.txt, the make program complains about an error. Make checks the return code of each command it executes. If any command returns a nonzero code, which usually indicates an error, then it reports the error and aborts the run. The problem is that the diff program does not obey this convention: it returns 0 if the files compared were the same, 1 if the files were different, and 2 if an error occurred. The result is that when diff is used in a Makefile and the files compared differ, then Make will report an error. You can tell Make not to check the return code of a command by inserting a `-' in front of it. For example, in your Makefile you should have a line of the form:
diff expected.txt output.txt > errors.txtIf you replace that with the following line, your Makefile should be correct.
-diff expected.txt output.txt > errors.txtExercise 5
We would now like to use RCS to manage the maintenance of the source files of this system, i.e., those files that are not created by your Makefile.
First, create a subdirectory called `RCS'. (Just create it, don't change into it.) Place the file sort.c under the control of RCS with the command `ci sort.c', to `check in' the file. Since this file is new to RCS you will be asked to provide a short description of it. One line of text should do, perhaps the following:
A function to sort an array of integers.
You can `check out' a copy of sort.c to look at by using the command co sort.c. Check in (and out) all the other source files.
Exercise 6
Use the command co -l sort.c to get a writable, `locked', copy of sort.c. Add the following line near the start of the file (outside any function).
char sort_header[] = "$Header:$";Check the file back in to RCS using the command ci -u sort.c to leave yourself with a readable, `unlocked', copy.
Have a look at sort.c now. What happened to the line you added?
Add a similar line defining a string called `harness_header' to harness.c, and check that in to RCS as well.
Use the command make harness to recompile the harness, then type the command ident harness. What does its output tell us about the harness program?
Exercise 7
The string `$Revision:$' also has a special significance to RCS, but it is replaced with just the revision number of a file. Modify the system so that the harness prints out which revision of the sort module it is using before testing begins.
You don't have to do any fancy formatting; a message like the following is acceptable:
Using sort $Revision:$.Hint: Since this year you are not being asked to write C code, this question is a bit too hard. So here's the answer. Follow these steps and then look at the results. Think about what you're doing; even though you're not expected to write your own C code, you are expected to read and understand it.
Add the line:
extern char sort_version[];to sort.h. This tells all users (clients) of the sort routine that there is a string called sort_version somewhere.
Add the line:
char sort_version[] = "$Revision:$";to sort.c. This will be replaced by $Revision: a.b$ by RCS (where a.b is the number of the current revision, for example 1.2).
Add the line:
printf("Using sort %s\n", sort_version);at the beginning of harness.c between the declaration of local variables in main and the beginning of the first for loop. This causes the test harness to print the words `Using sort ' followed by the contents of the string sort_version and a newline at the start of its output.
Exercise 8
You can also access the RCS commands to check files and in and out from the Emacs Tools menu. Use Emacs to edit the file expected.txt. The Emacs status line should start with something like this:
--:%% expected.txtThe `%%' part of the status line indicates that the file is read-only. To check out and lock the file for changing you should select the Check In/Out option from the Version Control submenu of the Tools menu. The percent symbols should disappear, indicating that the file may now be changed. Fix the error in this file, then save it and check it back in using the Check In/Out option again.
When you look at the menu, you'll see that there is a command key equivalent for this action; it's C-x v v.
When you check the file back in using Emacs, it will prompt you for a description of the changes by splitting the window in half and putting the cursor in the bottom part. Type a brief (usually one line is enough) description, and then finish the process with the command keys C-c C-c. It tells you this only briefly, and the message disappears before most first-time users have read it...
Exercise 9
The `rlog' command lets you inspect the revision history of any file under RCS control. Use it to inspect the history of your files.
Exercise 10
The command `co -rn foo' retrieves revision n of the file foo. Use this command to retrieve and rebuild the original version of the system.
Exercise 11
The versions of each file foo are recorded by RCS in the versions file RCS/foo,v. Have a look at the versions files for each of the source files. Can you see how RCS is able to store many versions of the same file efficiently?
![]()
![]()
Copyright © 2004, Jim Grundy & Ian Barnes, The Australian National University
Feedback & Queries to
comp2100@iwaki.anu.edu.au
Version 2004.1, 10 May 2004, 11:54:37