# Chapter 5. Libraries, Headers, and Frameworks

#### Contents:

Header Files
The System Library: libSystem
Shared Libraries Versus Loadable Modules
Library Versions
Creating and Linking Static Libraries
Prebinding
Interesting and Important Libraries

In this chapter, we discuss the linking phase of building Unix-based software under Mac OS X. In particular, we discuss header files in Mac OS X and libraries.

## 5.1. Header Files

There are two types of header files in Mac OS X.

Ordinary header files
  These header files are inserted into source code by a preprocessor prior to compilation. Ordinary header files have a .h extension.
Precompiled header files
  These header files have a .p extension.

Header files serve four functions:

- They contain C declarations.

- They contain macro definitions.

- They provide for conditional compilation.

- They provide line control when combining multiple source files into a single file that is subsequently compiled.

> TIP: The mechanism for enabling strict POSIX.1 compliance is built into the system header files. The preprocessor variables `_ANSI_SOURCE`, `_ _STRICT_ANSI_ _`, and `_POSIX_SOURCE` are supported.

Unix developers will find the ordinary header files familiar, since they follow the BSD convention. The C preprocessor directive `#include` includes a header file in a C source file. There are essentially three forms of this syntax:

`#include <``headername``.h>`
  This form is used when the header file is located in the directory /usr/include.
`#include <``directory/headername``.h>`
  This form is used when the header file is located in the directory /usr/include/`directory`, where `directory` is a subdirectory of /usr/include.
`#include "``headername``.h"`
  This form is used when the header file is located in a user or nonstandard directory. The form should either be in the same directory as the source file you are compiling or in a directory specified by cc's -I``directory`` switch.

You can use `#include`, followed by a macro, which, when expanded, must be in one of the aforementioned forms.

As noted in the previous chapter, frameworks in Mac OS X are common when you step outside of the BSD portions of the operating system. You must use `#import` instead of `#include` when working with a framework. To include a framework header file in Objective-C code, use the following format:

>     #import <frameworkname/headerfilename.h>

where ``frameworkname`` is the name of the framework without the extension and ``headerfilename`` is the name of the header file. For example, the included declaration for a Cocoa application would look like:

>     #import <Cocoa/Cocoa.h>

When preprocessing header files or any preprocessor directives, the following three actions are always taken:

- Comments are replaced by a single space.

- Any backslash line continuation escape symbol is removed and the line following it is joined with the current line. For example:

  >     #def\
  >     ine \
  >     NMAX 2000

  is processed as:

  >     #define NMAX 2000

- Any predefined macro name is replaced with its expression. In Mac OS X, there are both standard ANSI C predefined macros, as well as several predefined macros specific to Mac OS X. For example, `_ _APPLE_CC_ _` is replaced by an integer that represents the compiler's version number.

The following rules must be kept in mind:

- The preprocessor does not recognize comments or macros placed between the `<` and `>` in an `#include` directive.

- Comments placed within string constants are regarded as part of the string constant and are not recognized as C comments.

- If ANSI trigraph preprocessing is enabled with cc -trigraph, you must not use a backslash continuation escape symbol within a trigraph sequence, or the trigraph will not be interpreted correctly. ANSI trigraphs are three-character sequences that represent characters that may not be available on older terminals. For example, `??<` translates to `{`. ANSI trigraphs are a rare occurrence these days.

### 5.1.1. Precompiled Header Files

Mac OS X's Developer Tools support and provide extensive documentation on building and using precompiled header files. This section highlights a few of the issues that may be of interest to Unix developers new to Mac OS X when it comes to working with precompiled headers.

Precompiled header files are binary files that have been generated from ordinary C header files and that have been preprocessed and parsed using cpp-precomp. When such a precompiled header is created, both macros and declarations present in the corresponding ordinary header file are sorted, resulting in a faster compile time, a reduced symbol table size, and consequently, faster lookup. Precompiled header files are given a .p extension and are produced from ordinary header files that end with a .h extension. There is no risk that a precompiled header file will get out of sync with the .h file, because the compiler checks the timestamp of the actual header file.

When using precompiled header files, you should not refer to the .p version of the name, but rather to the .h version in the `#include` directive. If a precompiled version of the header file is available, it will be used automatically; otherwise, the real header file (.h) will be used. So, to include foo.p, you would specify foo.h. The fact that cc is using a precompiled header is totally hidden from you.

In addition to checking the timestamp, the preprocessor also checks whether or not the current context is the same as the context in which the precompilation was performed. For the precompiled header to be used, the timestamp would need to indicate that the modification time of the .p version is more recent than the .h version, and therefore, that the contexts must be equivalent. The context is the amalgamation of all defines (`#define`) in place at the time you compile a program. If the defines are different the next time you include the .h file, cpp-precomp will regenerate the .p file based on the current set of defines.

Mac OS X system headers are precompiled. For example, AppKit.p, Cocoa.p, mach.p, and other precompiled header files are stored in /System/Library/Frameworks. You can create your own precompiled header files using the cc -precomp compile driver flag. For example, the following command illustrates this process in its simplest, context-independent form:

>     cc -precomp header.h -o header.p

If there is context dependence--for example, some conditional compilation--the -Dsymbol flag is used. In this case, the command to build a precompiled header file (with the FOO symbol defined) would be:

>     cc -precomp -DFOO header.h -o header.p

For more details on building and using precompiled header files, as well as using the cpp-precomp preprocessor, read the documentation stored in /Developer/Documentation/DeveloperTools/Preprocessor/.

> WARNING: Although the cpp-precomp and the standard GNU cpp preprocessors are similar in function, there are several incompatibilities. For this reason, you will find it is often necessary to use the -no-cpp-precomp switch when porting Unix-based software to Mac OS X.

A complete list of precompiled headers can be found in the phase1.precompList and phase2.precompList files, located in /System/Library/SystemResources/PrecompLists. Table 5-1 lists the contents of the files.

#### Table 5-1. Precompiled header files as listed in phase1.precompList and phase2.precompList

Precompiled headers | Filesystem location
--- | ---
phase1.precompList
libc.p | /usr/include
unistd.p | /usr/include
mach.p | /usr/include/mach
phase2.precompList
CoreServices.p | /System/Library/Frameworks/CoreServices.framework/Versions/A/Headers
CoreServices.pp | /System/Library/Frameworks/CoreServices.framework/Versions/A/Headers
ApplicationServices.p | /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Headers
ApplicationServices.pp | /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Headers
Carbon.p | /System/Library/Frameworks/Carbon.framework/Versions/A/Headers
Carbon.pp | /System/Library/Frameworks/Carbon.framework/Versions/A/Headers
Foundation.p | /System/Library/Frameworks/Foundation.framework/Versions/C/Headers
Foundation.pp | /System/Library/Frameworks/Foundation.framework/Versions/C/Headers
AppKit.p | /System/Library/Frameworks/AppKit.framework/Versions/C/Headers
AppKit.pp | /System/Library/Frameworks/AppKit.framework/Versions/C/Headers
Cocoa.p | /System/Library/Frameworks/Cocoa.framework/Versions/A/Headers
Cocoa.pp | /System/Library/Frameworks/Cocoa.framework/Versions/A/Headers

Although the filenames in phase1.precompList and phase2.precompList are listed as filename.p (for example, libc.p), the actual file used depends on the compiler version. For example, gcc3 will use libc-gcc3.p. (Mac OS X 10.2 does not ship with precompiled heaeder files for gcc2.)

> TIP: The .pp files referred to in phase2.precompList are not present on the system, but the gcc3 versions can be generated by running sudo fixPrecomps -gcc3all.

### 5.1.1.1. PFE precompilation

The gcc3 compiler supports an alternative precompilation mechanism called Persistent Front End (PFE). This mechanism offers the same performance benefits as cpp-precomp, but supports C++ and Objective-C++. (cpp-precomp does not support either language.) To precompile a header file with PFE, compile the header, specifying the -- dump-pch switch with the name of the output file. You'll also need to supply the language with the -x switch (see Section 4.2.3):

>     gcc -x c --dump-pch header.pfe header.h

Then, you can compile main.c using the -- load-pch switch, supplying the name of the precompiled file:

>     gcc --load-pch header.pfe main.c -o main

Example 5-1 shows header.h, and Example 5-2 shows main.c.

#### Example 5-1. The header.h file

>     /* header.h: a trivial header file. */

>     #define x 100

#### Example 5-2. The main.c application

>     /* main.c: a simple program that includes header.h. */

>     #include <stdio.h>
>     #include "header.h"

>     int main( )
>     {
>       printf("%d\n", x);
>       return 0;
>     }

### 5.1.2. malloc.h

make may fail in compiling some types of Unix software if it cannot find malloc.h. Software designed for older Unix systems may expect to find this header file in /usr/include; however, malloc.h is not present in this directory. The set of `malloc( )` function prototypes is actually found in stdlib.h. For portability, your programs should include stdlib.h instead of malloc.h. (This is the norm; systems that require you to use malloc.h are the rare exception these days.) GNU autoconf will detect systems that require malloc.h and define the `HAVE_MALLOC_H` macro. If you do not use GNU autoconf, you will need to detect this case on your own and set the macro accordingly. You can handle such cases with this code:

>     #include <stdlib.h>
>     #ifdef HAVE_MALLOC_H
>     #include <malloc.h>
>     #endif

For a list of libraries that come with Mac OS X, see Section 5.7, later in this chapter.

Copyright © 2003 O'Reilly & Associates. All rights reserved.