CII Installation Guide

David R. Hanson, Google


  • Introduction
  • Installation on UNIX
  • Installation on Windows 95/NT
  • Reporting Bugs
  • Introduction

    This page describes how to install the software from my book C Interfaces and Implementations: Techniques for Creating Reusable Software (Addison-Wesley Professional Computing Series, 1997, ISBN 0-201-49841-3). A CII distribution includes the following files and directories.

    README distribution identification
    install.html this file
    makefile UNIX makefile
    makefile.nt Windows 95/NT makefile
    include/ interfaces (.h files) for the CII library
    src/ implementations (.c files) for the CII library
    examples/ example clients, including those from the book
    misc/ miscellaneous tools, e.g., maxalign.c

    The CII distributions are numbered X.Y where X is the major release number and Y is the minor release number. Starting with major release 1, minor releases fix bugs and perhaps make improvements, but do not change interfaces. The interfaces and the compiled library are compatible with earlier and later minor releases; for example, a program compiled with the 1.3 release is compatible with release 1.8 and vice versa. Major releases occur when one or more interfaces are changed or extended, or when new interfaces are added.

    It's usually best to follow a similar naming scheme when installing CII so that programs compiled with one major release can be recompiled even after a subsequent major release has been installed. The minor release number can be omitted. On UNIX, for example, this convention can be accomplished by installing the interfaces in, say, /usr/local/lib/cii/X/include, where X is the major release number, and installing the library, libcii.a, in /usr/local/lib/cii/X/libcii.a.

    At UNIX sites with multiple platforms (architectures and OSes) and a single /usr/local hierarchy, the library can be installed in a platform-specific location below /usr/local/cii/X, e.g., /usr/local/lib/cii/X/alpha-osf/libcii.a. The interfaces are machine independent and thus don't need platform-specific locations. Similar conventions can be used on Windows 95/NT.

    Following this scheme permits the actual installation locations to be confined to specifying prefixes, like /usr/local/lib/cii/X/include and /usr/local/lib/cii/X/, in makefiles; programs can include interfaces by giving just the names of their header files.

    On UNIX systems, it's also useful to plant release-independent symbol link to the latest CII release, e.g., make /usr/local/include/cii point to /usr/local/lib/cii/X/include and /usr/local/lib/libcii.a point to /usr/local/lib/cii/X/libcii.a.

    NB: If you use several compilers, you may need compiler-specific variants of libcii.a, and thus use platform names that denote a specific architecture, OS, and compiler. For example, the Text interface uses small structures and passes them by value, and, on some platforms, one C compiler might generate code for src/text.c that is incompatible with another compiler. This problem is not specific to CII; it can occur with any library.

    The installation makefile is designed so that CII can be installed from a read-only file system or directory, which is common in networked environments, so the distribution can be unloaded on a central file server. If you're installing CII on a UNIX system, continue with the next section. If you're installing CII on a Windows NT 4.0 or Windows 95 system, read the next section first, then follow the Windows NT/95 instructions.

    Installation on UNIX

    The CII components (include files and the library) are installed in a single build directory. On multi-platform systems supported by a central file server, it's common to store the build directory in a location specific to the platform and to the version of CII, as suggested above. For example, installation on a UNIX system involves the following steps. Below, the build directory is referred to as BUILDDIR, and the commands shown assume the distribution directory is the current working directory. If you want to build in the distribution directory, leave BUILDDIR undefined and start at step 3.

    1. Create the build directory, using a version- and platform-specific naming convention as suggested above, and record the name of this directory in the BUILDDIR environment variable:
      % setenv BUILDDIR /usr/local/lib/cii/1/alpha-osf/
      % mkdir -p $BUILDDIR

      The trailing slash is required, because BUILDDIR is concatenated with file names in the makefile, e.g., $(BUILDDIR)atom$O. Here and below, commands assume the C shell. Also, you'll need a version of mkdir that supports the -p option, which creates intermediate directories as necessary, or create them with individual mkdir commands.

    2. Create the include directory in the build directory, and copy the include files:
      % mkdir ${BUILDDIR}include
      % cp -p include/*.h ${BUILDDIR}include

      Some users create a symbolic link to the include directory in the distribution instead of making repeated copies of the include files. For example, at Princeton, the distributions are stored under /proj/pkg/cii, so the include files are "installed" by creating one symbolic link:

      % ln -s /proj/pkg/cii/1.1/include ${BUILDDIR}include
    3. Build everything using the appropriate make command for your environment:
      ALPHA OSF/1 V3.2A % make CC='cc -std1 -Dalpha' AS='as -Dalpha'
      MIPS IRIX 6.2 % make
      MIPS Ultrix 4.3 % gmake CC=gcc LD=gcc
      SPARC SunOS 5.5.1 (Solaris) % make -k CC='cc -DMAXALIGN=8' THREADS=
      X86_32 Linux % make CC='cc -DMAXALIGN=4' AS='cc -c -x assembler-with-cpp -traditional'
      X86_64 Linux, Apple Intel Mac OS X 10.5.x % make -k THREADS=

      This command builds, in BUILDDIR, libcii.a, memchk.o, and the examples. There may be some warnings on some platforms. The assignment THREADS= appears on those platforms for which there is no Thread implementation. On these platforms, examples that use Thread won't link correctly, so use the -k option so make keeps going.

      On most platforms, malloc returns pointers to blocks that are aligned on addresses that are multiples of the size of the largest basic data type. Some CII functions use a union to determine this multiple (cf. union align on p. 80). Alignments are less restrictive on some platforms and, for these, MAXALIGN must be defined as the alignment required as shown above. maxalign.c is a C program that attempts to determine the correct value for MAXALIGN, if one is necessary, and echo the appropriate -D option. The method used relies on the C compiler using the same alignments as malloc, which is not required. malloc is the final authority: If it returns addresses that are multiples of sizeof (union align), then MAXALIGN is unnecessary; otherwise, MAXALIGN must provide the alignment. So, maxalign.c calls malloc(1) to determine if the address it returns has an alignment less strict than that used by the C compiler.

      The command make maxalign compiles and executes maxalign.c; the output shows the appropriate -D option, if one is needed. Incorrect values of MAXALIGN can cause crashes and assertion failures.

      src/{memcmp,memmove,strncmp}.c are implementations of the similarly named ANSI library functions. These are included in the distribution because some of them are implemented incorrectly on some UNIX platforms. The corresponding object files are assigned to EXTRAS; if some of these functions are implemented correctly on your system, you can omit the CII versions by either editing libcii.a, or including the appropriate assignment to EXTRAS, e.g.,

      % make EXTRAS=${BUILDDIR}memcmp.o
    4. The makefile includes the file named by the CUSTOM macro; the default is, and an empty is included in the distribution. If desired, prepare a site-specific customization file and define CUSTOM to the path of that file when invoking make in the previous step. For example, on the ALPHA, I use
      % cat
      CC=cc -std1 -Dalpha
      AS=as -Dalpha
      % make
    5. Run a few of the test programs, e.g.,
      % ${BUILDDIR}wf <makefile
      % ${BUILDDIR}cref src/fmt.c src/str.c

      and then clean up:

      % make clean

      This command removes everything except include and libcii.a. If you want to leave memchk.o installed, rebuild it, e.g.,

      % make ${BUILDDIR}memchk.o

      memchk.c uses MAXALIGN, so if you defined MAXALIGN when building libcii.a, include it when rebuilding memchk.o, e.g.,

      % make CC='cc -DMAXALIGN=8' ${BUILDDIR}memchk.o

      make clobber removes everything from BUILDDIR.

    6. If desired, plant release-independent symbolic links to the include directory and to the installed library, e.g.,
      % ln -s ${BUILDDIR}include /usr/local/include/cii
      % ln -s ${BUILDDIR}libcii.a /usr/local/lib/libcii.a

    Installation on Windows 95/NT

    On Windows NT or Windows 95, you can use a directory organization similar to the one described above for UNIX as follows. The commands below assume the distribution is rooted at C:\dist and that the C compiler is Microsoft Visual C/C++ 5.0.

    1. Create the build directory and set BUILDDIR:
      C:\dist>set BUILDDIR=\lib\cii\1
      C:\dist>mkdir %BUILDDIR%

      Change the assignment to BUILDDIR to suit your local conventions. On Windows, BUILDDIR must not include the trailing backslash.

    2. Create the include directory in the build directory, and copy the include files:
      C:\dist>mkdir %BUILDDIR%\include
      C:\dist>copy include\*.h %BUILDDIR%\include
    3. Build everything using nmake:
      C:\dist>nmake -f makefile.nt BUILDDIR=%BUILDDIR%

      This command builds, in BUILDDIR, libcii.lib, libcii.pdb, memchk.obj, and the examples. The default BUILDDIR is \lib\cii\1, so the assignment to BUILDDIR above can be omitted if you use this default.

    4. Run a few of the test programs, e.g.,
      C:\dist>%BUILDDIR%\wf <makefile

      and then clean up:

      C:\dist>nmake -f makefile.nt BUILDDIR=%BUILDDIR% clean

      This command removes everything except include, libcii.a, and libcii.pdb. If you want to leave memchk.obj installed, rebuild it, e.g.,

      C:\dist>nmake -f makefile.nt BUILDDIR=%BUILDDIR% %BUILDDIR%\memchk.obj

      make clobber removes everything from BUILDDIR

    5. src\libcii.def is a module definition file for the CII library. To create a DLL instead of a statically linked library, execute
      C:\dist>nmake -f makefile.nt BUILDDIR=%BUILDDIR% libcii.dll

      This command creates %BUILDDIR%\libcii.dll, overwrites %BUILDDIR%\libcii.lib with the import library, and creates the export library %BUILDDIR%\libcii.exp. If you use libcii.dll, you'll need to move it to a directory on your PATH.

    Some users copy the include and library files into their Visual C/C++ 5.0 distribution, e.g.,

    C:\dist>mkdir "\Program Files\DevStudio\VC\include\cii"
    C:\dist>copy include\*.h "\Program Files\DevStudio\VC\include\cii"
    C:\dist>copy %BUILDDIR%\libcii.* "\Program Files\DevStudio\VC\lib"

    Reporting Bugs

    Devise the shortest possible example program that elicits the bug. Prune your example until it can be pruned no more without sending the error into hiding. I prune most error demonstrations to only a few lines. Annotate your example with C comments that describe the bug and your suggested fix, if you have one. If the example crashes, please report the last part of the call chain if you can.

    Send your example by electronic mail to me (see below). Please send only valid C programs; put all remarks in C comments so that I can process reports semi-automatically.

    David Hanson