CSC 161 Grinnell College Fall, 2011
Imperative Problem Solving and Data Structures

Program Management: Header Files and make


This lab provides practice dividing a program into pieces, compiling those pieces separately, linking components together to form an executable, and automating this process using the Unix utilities make and Makefile.


Structs and typedefs in C.


Many ideas that follow come from exercises by Marge Coahran.


  1. Header and Implementation Files
  2. Makefiles

Steps for this Lab

  1. Be sure you understand the reading on headers and Makefiles for this lab.

Part A: Header and Implementation Files

The work that follows utilizes the array implementation of queues from a recent lab.

  1. For safety, make a new directory for multi-file queues and copy your queue-array program to it.

  2. Separate the code in your queue-array program into three files as follows:

    • queue.h — containing the definition of the stringQueue type and the function prototypes for queues.
    • queue-proc.c — containing the implementation of all queue functions, except main.
    • queue-test — containing your main function.

    In order to get these source files to compile, both queue-proc.c and queue-test.c should contain the following line at the top of the file:

       #include "queue.h"

    You should not #include your source file queue-proc.c anywhere. (It is good practice to only include header files, and not implementation files, in other source files.)

    As discussed in the reading, your header file should contain the following lines, and they should surround all other code in the file (i.e., all other code goes where the ellipses are shown).

       #ifndef _QUEUEINFO_H
       #define _QUEUEINFO_H
  3. Try building your program with the following command, typed at the shell prompt. Do you understand why it gives the error it does?

       gcc -ansi queue-test.c

    Compile each of your source files (to create object files, but still not an executable program) with the following commands, typed at the shell prompt:

       gcc -Wall -ansi -c queue-proc.c
       gcc -Wall -ansi -c queue-test.c

    Use the shell command "ls -l" to check that the object files were produced.

    Now create an executable file with the following command:

       gcc -o queue-test queue-test.o queue-proc.o

    Check that the file queue-test exists with "ls -l", and the run the program with: "./queue-test"

    Finally, compile both source files and link the resulting object files together with the following single command.

       gcc -o queue-test queue-test.c queue-proc.c

    Note, however, that building large programs this way quickly becomes tedious since every source file must be recompiled from scratch.

As you finish this part of the lab, note that you have converted your queueString code into an abstract data type. By listing the function prototypes, the header file tells other programmers what operations are supported by the data type. It does not specify how they are implemented; that is done in the implementation file.

Your data type may now be used in client programs, such as queue-test.c. Doing so requires only the following simple steps:

Part B: Makefiles

The reading for this lab describes a detailed Makefile with directions for compiling, linking, and cleaning files related to a namelist.c program. This part considers a simplied Makefile.

  1. Copy a simplified Makefile to your account and review it. Do you understand what is accomplished by each line in the file?

  2. Adapt the Makefile so that it can be used to build your queue-test program. (You will, of course, want to change the "Author" comment at the top of the file when you do this.)

  3. In the terminal window, type these commands:

    • "ls -l" -- to see a listing of your files
    • "make clean" -- to prepare for a fresh build
    • "ls -l" -- to view the result
    • "make" -- to compile and link all source files
    • "ls -l" -- to view the result
  4. Make a change in the source file queue-proc.c. For example, you could add or modify a printf statement in some function. Which rules in the makefile do you expect will be run, the next time you invoke make, as a result of this change?

    Run make again, to verify your prediction experimentally.

  5. Make a change in the header file queue.h. For example, you could add a comment to the top of the file. Which rules in the makefile do you expect will be run, the next time you invoke make, as a result of this change?

    Run make again, to verify your prediction experimentally.

  6. If you still have time, take a look at GNU's documentation regarding make and makefiles here: Makefiles and the GNU make utility.

    Note that this documentation is very lengthy, and it is not necessary for you to read or understand all of it in order to begin using makefiles. Reading through Section 3.2 or so provides a good introduction to the topic.

Reminder: Complete Evaluation Form

When you have finished this lab, be sure to fill out its evaluation form in the "Lab Evaluation" section for CSC 161 on Pioneer Web.