This week's lab introduces an important Unix tool: the make facility. This facility allows you to easily maintain and keep your files up to date when you are working on a project that is split across several .c files (and their associated header files). You will find your multi-file programs easier to manage if you keep all of the files for one project in a directory, and create a makefile, as described below, to manage the compilation of the files.
cp /cs/cs2301-b07/labs/lab5/* .
If you now list the files in your directory, you should see entries for
intarray.c, intarray.h, sinewave.c, and makefile.
if sinewave.c or intarray.h changes, then sinewave.o must be regenerated by giving the compiler command:
gcc -Wall -c -g sinewave.c
This requirement to sometimes regenerate sinewave.o is one of the
dependencies that the example makefile expresses. To see this
dependency, use emacs to open up the file named makefile.
Near the bottom of the file you'll find these two lines:
sinewave.o: intarray.h sinewave.c
gcc -Wall -c -g sinewave.c
The first line is called a target line, which begins with a file name and a colon. After the colon is a list of more file names. Here's how to interpret the line: The file before the colon (called the target file) depends on the other files (after the colon). Whenever one of the files after the colon changes, the make tool knows that the target file needs to be recompiled. After the target line, there is a series of commands that tell exactly how to regenerate the target file. For the case of sinewave.o, we only need the one gcc command to regenerate the file. (Notice that we included the -c flag to indicate that we should only compile and not create an executable file yet. We also included the -g flag in case we want to use the debugger.)
There is one other peculiar requirement: The command lines (such as the gcc command) must each begin with a tab (not with 8 spaces!).
As a second example of a dependency, the executable file sinewave is created by compiling together the object files intarray.o and sinewave.o. If either of these two object files should change, then sinewave also needs to be recreated. Here is the appropriate target line and command from our makefile:
sinewave: intarray.o sinewave.o
gcc -Wall -g sinewave.o intarray.o -o sinewave
This target line says that if sinewave.o or intarray.o should happen to change, then the sinewave program must be regenerated with the gcc command that is shown.
make intarray.o
The make command will find the dependency information in the makefile file. It sees that intarray.o depends on other files, so it will first ensure that those files are present (and regenerate them if necessary). In this example, the two files intarray.h and intarray.c are necessary for generating intarray.o. These two files are present, so the make command proceeds to generate intarray.o, using the gcc command that is specified in the makefile. When the gcc command is executed, it is displayed on the screen, so you will see this appear on the screen:
gcc -Wall -c -g intarray.c
After this command finishes, you should list the files in your directory, where you will find the object file intarray.o is now present.
make
Without a specified file, the make command will regenerate the first target that it finds in makefile. Try this now, and you will see that the executable file sinewave is regenerated, since sinewave is the first target file in makefile. During the process of regenerating the sinewave file, the make command had to carry out several steps. In the first step, the make command realizes that sinewave depends on intarray.o and also on sinewave.o. But the file sinewave.o is not present. So, the make command first regenerates sinewave.o, and then it can proceed to regenerate the executable file sinewave. On the screen you'll see the two steps displayed:
gcc -Wall -c -g sinewave.c
gcc -Wall -g sinewave.o intarray.o -o sinewave
<ENTER>).
What happens? The emacs compile command automatically issues the "make -k" command (the -k tells make to continue as much as possible after an error). The make program realizes that sinewave.c has changed, and therefore the object file sinewave.o is regenerated with the command:
gcc -Wall -c -g sinewave.c
Next, the make program realizes that sinewave.o has just changed, and therefore the executable file sinewave is regenerated with:
gcc -Wall -g sinewave.o intarray.o -o sinewave
But, notice that the object file intarray.o was not recompiled. The dependencies in the makefile were sufficient to show that intarray.o did not need recreation.
There's nothing to turn in this week...your attendance counts as your credit.
See you next week.