2004, 2005 by Marc J. Rochkind. All rights reserved. Portions marked "Open Source" may be copied under license.

 

How to Compile the Examples

This page explains how to compile the examples using some simple makefiles. The method used here is inappropriate for most software development, mainly because the makefiles don't describe all the dependencies. But, it's a fairly simple method that will at least get you started.

Each source directory that contains C code (other than ux) contains a file named makebuild.spec. Here's the file in c1,  the directory for Chapter 1:

!include common/makebuild.spec

ckstdvers c1/ckstdvers.c
ckvers -DCKVERS_UNIX98 c1/ckvers.c
err c1/errorhandling.c
opttest c1/opttest.c
suvreq -DCKVERS_UNIX98x c1/suvreq.c
sysconf c1/sysconf.c
timetst c1/timetst.c
version c1/version.c

The file resembles a makefile, in that each line starts with the name of an executable followed by the source files that need to be compiled to create it. Some lines, like the one for ckvers, have compiler options. (The language used in a makebuild.spec is my own invention, not something you'll find elsewhere.)

You'll have to modify the makebuild.spec in the common directory (referred to by the first line) for your system; more on that below.

To get an actual makefile, you process a makebuild.spec file with an Awk script. To see it, click here. To download it to your machine, right click on the link and choose "Save Link As" or "Save Target As" or whatever your browser calls it.

You run the Awk script, named makebuild.awk, with a shell command file that looks like this:

# On Solaris (and perhaps other systems), the command must be "nawk" instead
# of "awk," or you must have /usr/xpg4/bin in your path before /usr/bin.
#
AUPSRC=/aup
export AUPSRC
awk -f $AUPSRC/makebuild.awk $AUPSRC/$1/makebuild.spec >$AUPSRC/$1/Makefile

AUPSRC is the location of the source tree; if you've downloaded it to, say, /usr/marc/aupsrc, you would change the line to:

AUPSRC=/usr/marc/aupsrc

If you've named the command file makebuild, you would run it like this to build the makefile for directory c1:

$ makebuild c1

As I mentioned, you may need to change the makebuild.spec file in the common directory, the start of which looks like this when you first download it:

# Following must be defined in the environment before you run make:
#
# OS = SOLARIS or LINUX or FREEBSD or HPUX
# LIBS = regular (non-thread) libraries (eg, "-lncurses -lutil")
# TLIBS = thread libraries (eg, "-llthread -llgcc_r")
# PTHREADSTUB = stub for thread functions (eg, pthreadstub.o), if needed
# INCLUDES = additional include directory (eg, "-I/usr/local/include/pthread/linuxthreads")

# Don't forget:
# export OS LIBS TLIBS PTHREADSTUB INCLUDES

# Suggestions:
# Solaris:
# OS=SOLARIS
# LIBS="-lrt -lcurses -lsocket -lnsl"
# TLIBS="-lpthread"
#
# FreeBSD:
# OS=FREEBSD
# LIBS="-lncurses -lutil"
# TLIBS="-llthread -llgcc_r"
# PTHREADSTUB=pthreadstub.o
# INCLUDES="-I/usr/local/include/pthread/linuxthreads"
#
# Linux:
# OS=LINUX
# LIBS="-lncurses -lutil"
# TLIBS="-pthread"
#
# HPUX:
# OS=HPUX
# LIBS="-lcurses"
# TLIBS="-lpthread" (not yet checked out)

# Options below (e.g., -Wimplicit) are for gcc mostly. You will have to modify them for a non-gcc compiler.
!echo CFLAGS = $(INCLUDES) -I$(AUPSRC) -I$(AUPSRC)/include -I$(AUPSRC)/common -I$(AUPSRC)/c6 -Wimplicit -Wstrict prototypes -Wall -D$(OS) -D_REENTRANT -D_THREAD_SAFE
!echo CC = gcc
!echo CCPP = g++
!echo CCLINK = gcc

The stuff in the comments about OS, LIBS, TLIBS, PTHREADSTUB, and INCLUDES applies when you run make--it has nothing to do with running the Awk script that creates the makefile. What you may have to change in common/makebuild.spec are the last four lines shown. (The line for CFLAGS may have been wrapped by your browser, but in the makebuild.spec file it must be on one line.)

When you've made the necessary changes, run the makebuild script (shown above) to get a makefile. To see the one I got for directory c1 on my FreeBSD system, which happens to be the one in the download archive, click here.

Now, as I said, to run the makefile you need to specify some environment variables, which you can either do permanently by changing whatever profile executes when you log in, or every time you execute make, which is what I do. On FreeBSD, I use a this command file named k:

AUPSRC=/aup
OS=FREEBSD
LIBS="-lncurses -lutil"
TLIBS="-llthread -llgcc_r"
PTHREADSTUB=pthreadstub.o
INCLUDES="-I/usr/local/include/pthread/linuxthreads"
export AUPSRC OS LIBS TLIBS PTHREADSTUB INCLUDES
make $2 -f $AUPSRC/$1/Makefile $3

So, to compile the example program c1/timetst, I run this:

$ k c1 timetst

For threading examples (in Chapter 5), I have a similar command file named kt:

AUPSRC=/aup
OS="-DFREEBSD -D_THREAD_SAFE"
LINKERLIBS="-lncurses -lutil -llthread -llgcc_r"
INCLUDES="-I/usr/local/include/pthread/linuxthreads"
export AUPSRC LINKERLIBS OS INCLUDES
make $2 -f /aup/common/makefile -f /aup/$1/makefile $3

(Which is not to imply that the FreeBSD implementation of linuxthreads actually works; see Section 5.17 of the book.)

My Linux version of k looks like this:

AUPSRC=/aup
OS=LINUX
LIBS="-lncurses -lutil" # -lndbm removed
TLIBS="-pthread"
export AUPSRC OS LIBS TLIBS
rm $2.o
make $2 -f $AUPSRC/$1/Makefile $3

You'll probably want to run your k and kt commands from a working directory different from where the source is. They're set up to do that. I usually work in a directory called something like /usr/marc/aup (where my k and kt files are), whereas the source is rooted at /aup, which is mounted (always as /aup) on several machines.

If you set up common/makebuild.spec and your compiling command file for any other systems, please email them to me so I can post them here for others to use.

The code on this page is Open Source, covered by this license.