Lab 1 Goals

By the end of this lab, you should be able to use the source code control system Subversion confidently to work individually and with a small number of partners, use the build tool make, and author a Makefile.

Subversion

Subversion is a source code control system - it is a repository, often on another machine, that tracks directories of files and their updates. In this class, you will be using the client-side command line tool svn and accessing the server phoenixforge.cs.uchicago.edu. You will store most of your homework and lab exercises there as you work on them, and the course administrators will also pick up your submissions from the repository. Comprehensive documentation for subversion is available in their free online book.

The subversion client, svn, will access the repository through the URL https://phoenixforge.cs.uchicago.edu/svn/. Your personal directory is https://phoenixforge.cs.uchicago.edu/svn/USER-154, where USER should be your CNetID, unless you have been told otherwise.

Redmine is software that provides a graphical frontend for account management, issue tracking, and browsing the repository. You may explore the graphical browsing tools at http://phoenixforge.cs.uchicago.edu/ later; for the purposes of the lab please just use the commandline tools as listed below.

Walkthrough

You should perform these steps to get a feel for subversion and source code control. First, create a local copy of your personal directory. Replace USER with your CNetID. This is what you will do any time that you move to a new machine.

$ cd ~
$ svn checkout https://phoenixforge.cs.uchicago.edu/svn/USER-154 cs154

After typing that, you should first be prompted to accept the SSL certificate for the phoenixforge server. Enter 'p' to permanently accept it. Then, you will be prompted for your password - please enter the password you use with your CNetID.

If you get a 403 error from svn, check to make sure that the path and username are typed correctly. If you run into any other errors, please flag down the TA immediately for assistance!

This command will create a directory named cs154 and will populate it with all of the files for the lab. This directory will be world-readable by default, allowing others to easily steal your homework. Use the following command to restrict access to only your account:

$ chmod 700 cs154

You should now change into the 'testSVN' portion of lab 1 and follow the steps below:

$ cd ~/cs154/lab1/testSVN
$ emacs test.c

Edit the comment at the top of the file test.c to have your name in it instead of mine and to remove the extra blank line, save, and exit emacs (or your favorite editor). To take a look at the change, perform the following command:

$ svn diff

You should see some header information talking about what the base version number of the file in the repository is and a note that the file being compared against is the working copy (what subversion calls the set of files you have on-disk after performing a "checkout"). Notice that the top one is prefixed with "---" and the working copy is prefixed by "+++" - these are the characters that appear in the contextual differences below to indicate a line that appears in the base version of the file ("-") or in your modified version ("+"). Make sure you understand what the diff is saying about which line is in which file!

Next, add a file to the directory and then see what changes are pending locally for commit back to the repository with the following commands:

$ echo "" > documentation.txt
$ svn status

The status command will show you all of the files that have been modified, added, deleted, or have just 'appeared'. Note that the file test.c will have an M before it, for modified. The file documentation.txt, though, will have a ?. This indicates that it is a new file on disk that has not yet been added to the repository.

$ svn add documentation.txt
$ svn status

And now, documentation.txt should have an A before it, for added.

$ svn delete test.c

This command should generate an error message, as you can't delete a modified file, you must revert it first. Reverting discards any changes you have made to a file and replaces it with the copy that you last got from the repository. Note that it does not copy down the most recent version in the repository - it just restores what you were working from originally.

$ svn revert test.c
$ svn delete test.c
$ svn status

Now it should say that you have removed the file. Let's make sure the files in the local directory are up to date:

$ svn update

Subversion should tell you what version of the files you currently have, but not make any local changes as you are already up to date. Unless you provide extra arguments, this command will check all of the files in and below the current directory to see if they need to be updated with new status from the repository. The USER-154 directory in gForge will be regularly populated with new assignments and labs by the teaching staff, and running update from the cs154 directory is how you will pick them up.

At this point, you can do an svn commit to submit the changes made above to the repository. Commit (and several other subversion commands) require a log message to associate with your change. You may either provide this at the command-line by using an argument of the form -m "Log message" or by setting the EDITOR environment variable and just running the command. For example, if you do the following, emacs will be launched whenever the svn client needs you to edit text. You should edit the file to contain a comment about the commit, save, and exit.

$ export EDITOR=emacs
$ svn commit

If svn cannot launch your editor and is not able to get a log message, you will get an error message stating that the commit failed, with a possibly confusing error message involving the file svn-commit.tmp. Just set your EDITOR environment variable or provide the -m "Log message" argument on the command-line and try again.

Write log messages that concisely describe the reasons and goals for the changes that were made. Do not include your name or the date, as the repository already has that information.

Exercises

Just follow the instructions for the exercises. Your lab submission for these will be the correct files and structure in your personal lab directory. Note that if you are working with a partner, you will both need to complete the commands in your subversion project directories.

Exercise 1 (create the lab readme)

If you followed the walkthrough above, you should have a ~/cs154 directory that has a checkout of your personal files from gForge. If you skipped straight to the exercises, go back and do that!

In the lab1 subdirectory of cs154, create a file called readme.txt. Put your name in it and the name of anyone you are working with. Issue the following commands to add it to the subversion server.

$ svn add readme.txt
$ svn commit readme.txt -m "Readme file"

That's it for the first exercise! You will be creating this file for every lab this quarter.

Exercise 2 (just change some files)

In your ~/cs154/lab1/ex2/ directory, there are a set of files. Find them, perform one (1) edit, one (1) deletion, and then commit your changes to the repository. Type the following commands, paste the output of the log into the readme.txt file from the previous step, and commit the changes.

$ svn up
$ svn log

Exercise 3 (creating and exploring history)

First, you'll need to create a directory to store the file that you will create.

$ mkdir ~/cs154/lab1/ex3

This command will create a directory on your file system under your local copy of the files in the Subversion repository. In that directory, create a file named 'names.txt', put your last name in it and add that file.

If you just did an 'svn add names.txt', then you should get an error from svn that says that "'.' is not a working copy." Subversion relies on a .svn/ directory in each local directory to understand where the files are from and what the original copies were. In the case of a new directory, that .svn/ directory doesn't exist! You will need to change to the parent directory and perform the add from there.

$ cd ~/cs154/lab1
$ svn add ex3

Now svn will add the directory and all of that directory's contents. If there were any files in that directory that you did not want to add, you would need to 'svn revert' them. Now use svn to commit the directory and file additions.

Edit the names.txt file in the ex3 directory to have your full name instead of just your last name, and commit again.

Now use the history commands log and diff to show the change between the two revisions of names.txt. There is a good section in the SVN book on examining history. In your lab1/readme.txt file, make note of:

Please also include the exact command input strings (though not the output!) that you used to find your information. Remember to commit the changes you've just made to your readme.txt file!

Exercise 4 (on second thought...)

Continue to work in the lab1/ex3 directory for this exercise. We have decided to return to the previous version of names.txt, with just the last name. While you could simply edit the file to return it to its previous state, often you will need to undo a much more substantial change. Svn's merge command can make this much easier!

To start the merge, issue the following command, substituting A with the revision number associated with the first file in exercise 3, and B with the revision number from the second file. Note that order matters here!

$ svn merge -r B:A names.txt

At this point, you should do an svn diff and look at the output. Please copy that output into your lab1/readme.txt file and commit. It should basically be the inverse of the output from the diff in exercise 3.

You can now do an svn commit to commit your changes. If this had been a more complicated revision - in particular, one that was from the "middle" of a series of changes - there could have been a merge conflict and you might have had to do some small cleanup by hand before doing the commit. There's additional guidance on this in the SVN book.

Make

Make is a tool for building programs. It reads a Makefile, expands the variables in it, and executes the rule requested when run from the commandline. If no rule is provided, make runs the first rule it finds in the Makefile.

The makefile has two parts. Variables are of the form:

OBJS = foo.o bar.o baz.o blork.o 

By convention, variables are in all capital letters. Rules are of the form:

clean:
	rm -rf *.o

main: foo.o
	gcc foo.o -o main

A rule is either a file name or a phony target. In either case, make looks on disk to see if there is a file with the name of the rule. If it does not exist or if a file with the rule name exists but is older than the list of files to the right of the colon, then make runs the command on the second line.

IMPORTANT! the second line starts with a tab. If there is anything other than a tab at the start of that line, make will not run the commands.

Make has a comprehensive manual

Walkthrough

You should perform these actions in your ~/cs154/lab1/testMake/ directory, but will not need to submit any changes.

Perform an ls and look at the files. There's a Makefile, two .c files, and two .h files. To build sources into an executable, just run make.

$ make

You will see output from gcc compiling the two files and then linking them into a single binary. Now do another ls. You will see two .o files and an executable binary named main. Edit the file named foo.h - just use your favorite editor to add a blank line someplace safe, save, and exit. Now re-run make as above.

You should see just the file foo.c rebuilt into foo.o, and then the binary named main rebuilt. bar.o should not have been rebuilt. Open up the Makefile to see why! When you ran make, it loaded the makefile and built the first target, main. Main depends on foo.o and bar.o. Bar.o's files have not changed, so it did not need to be updated. However, foo.o's last modified date was older than foo.h's, so it was rebuilt. The important thing to take away from this is that the Makefile is what specified the dependency, not the compiler or source! If you don't keep the dependencies up to date, make will not know what to rebuild when a file is edited.

You can revert the change with the svn revert command:

$ svn revert foo.h

Exercise 5 (simplify)

Your subversion user directory has been populated with a lab1/ex5 directory that contains a Makefile and some sources. You will be editing and simplifying this project.

Part 1: If you look at the rules, they have a lot of copied code! Create variables CC for the compiler, CFLAGS for the compiler flags, etc. and move all constant statements to the top of the file as variables. As an example, if a rule looked like the following:

clean:
	rm -rf a.o b.o c.o

You would turn it into:

RM = rm
RMFLAGS = -rf
OBJS = a.o b.o c.o

clean:
	$(RM) $(RMFLAGS) $(OBJS)

Part 2: Listing all of those files both in the prerequisite line and on the commandline seems like a lot of redundant redundancy! Use automatic variables to simplify them. As an example, if a rule looked like the following:

frob: thing1.c thing2.c thing3.c
	tweak -o frob thing1.c thing2.c thing3.c

You would turn it into:

frob: thing1.c thing2.c thing3.c
	tweak -o $@ $^

Just commit the files when you are done. Be sure to run 'make clean' followed by 'make' periodically to check that you didn't break anything! There are multiple correct final solutions to this exercise.

Bonus Problems

Do not attempt these problems until you have completed all of the Subversion and Make exercises.

BONUS 1 (bindir)

Creating all of those files in the same directory as your source is messy! Make another copy of the project into lab1/ex5 into a bonus1 directory, and change it to generate all of the .o files and the output binary into a subdirectory named bin. Note that you can make a copy quickly via the svn copy command:

$ cd ~/lab1
$ svn copy ex5 bonus1
$ svn commit -m "Initial bonus1 checkin"

Make sure to check this into your directory at https://phoenixforge.cs.uchicago.edu/svn/USER-154/lab1/bonus1

BONUS 2 (now with SVN support!)

Create a copy of exercise 5 in your source tree at bonus2. Make a new version of the 'clean' target that removes any files that are not in the subversion repository. svn stat and sed & awk (or Your Favorite Parsing Language) may be of assistance.

Last modified: Wed Mar 30 18:14:59 CDT 2011