# FreeType 2.0 Build System

### © 2000 David Turner (david@freetype.org)
© 2000 The FreeType Development Team (devel@freetype.org)

## Introduction:

This document describes the new build system that was introduced with FreeType 2.

## I. Features and Background:

The FreeType 2 build system is a set of Makefiles and sub-Makefiles that are used to build the library on a very large variety of systems. To understand it properly, it must be noticed that:

- The build system is made of a single Makefile, dispatched over several directories with the help of the `include` directive. Technically speaking, it is composed of the top-level "`freetype2/Makefile`" which includes several other sub-Makefiles, whose extension is always "`.mk`". Examples are:

  `freetype2/config/freetype.mk`
  `freetype2/config/system/detect.mk`
  `freetype2/src/module/rules.mk`
  etc..

  We strongly recommend the following article:

  Recursive Make Considered Dangerous

  To understand why such a layout was chosen.

- The build system works exclusively with GNU Make. Reason is that it is the only make utility that has all the features required to implement the build system as described below. Moreover, it is already ported to hundreds of various distinct platforms and is widely and freely available.

  You don't need a Unix-like shell on your platform. For example, FreeType 2 already compiles on Unix, Dos, Windows and OS/2 right "out of the box" (assuming you have GNU Make installed).

  Note that we have no plans to support a different make tool, as you'll rapidly understand by reading this document or looking at the Makefiles themselves.

The build system features some important points, which are all detailed in the following sections:

- Automatic host platform detection
  The first time the top `Makefile` is invoked, it will run a series of rules to detect your platform. It will then create a system-specific configuration sub-Makefile in the current directory, called `config.mk`. You can now invoke the top `Makefile` a second time to compile the library directly.

  The configuration sub-makefile can be regenerated any time by invoking "`make setup`", which will re-run the detection rules even if a `config.mk` is already present.

- User-selectable builds
  The system-specific `config.mk` created when running `make` for the first time contains various definitions, including compiler, compiler flags, object files directories, etc.. However, a given platform has often several compilers available, each with a different name and flags to be used. Rather than trying to detect the compiler in the build system, users can also specify which compiler they use when running `make`.

  For example, on Win32 platforms:

  `make setup` | Will generate a `config.mk` that can be used to compile the library with `gcc` (which is the default compiler for most supported platforms).
  `make setup visualc` | Will generate a different `config.mk` that can be used to compile the library with the Visual C++ command-line compiler.
  `make setup lcc` | Will generate a different `config.mk` that can be used to compile the library with the Win32-LCC compiler.

- Automatic detection of font drivers
  FreeType is made of a "base" layer that invokes several separately-compiled modules. Each module is a given font driver, in charge of supporting a given font format.

  The list of font drivers is located in the file "`freetype2/config/system/ftmodule.h`", however it can be regenerated on-demand. Adding a new module to the FreeType source tree is thus as easy as:

  - create a new directory in "`freetype2/src`" and put the new driver's source code and sub-makefiles there.

  - invoke the top `Makefile` with target "`modules`" (as in "`make modules`"), as this will automatically regenerate the list of available drivers by detecting the new directory and its content.

## II. Host Platform Detection

When the top-level `Makefile` is invoked, it looks for a file named `config.mk` in the current directory. If this file is found, it is used to build the library (see Section III).

Otherwise, the file `freetype2/config/detect.mk` is included and parsed. Its purpose is to:

- Define the `PLATFORM` variable, which indicates what is the currently detected platform. It is initially set to the default value "`ansi`".

- It searches for a `detect.mk` file in all subdirectories of `freetype2/config`. Each such file is included and parsed. Each of these files must try to detect if the host platform is a system it knows about. If so, it changes the value of the `PLATFORM` accordingly.

This is illustrated by the following graphics :

Note that each system-specific `detect.mk` is in charge of copying a valid configuration makefile to the current directory (i.e. the one where `make` was invoked), depending on the current targets. For example, the Win32 `detect.mk` will be able to detect a "`visualc`" or "`lcc`" target, as described in section I. Similarly, the OS/2 `detect.mk` can detect targets like "`borlandc`", "`watcom`" or "`visualage`", etc..

## III. Building the library

When the top-level `Makefile` is invoked and that it finds a `config.mk` file in the current directory, it defines the variable `BUILD_FREETYPE`, then includes and parses the configuration sub-makefile.

The latter defines a number of important variables that describe the compilation process to the build system. Among other things:

- the extension to be used for object files and library files (i.e. `.o` and `.a` on Unix, `.obj` and `.lib` on Dos-Windows-OS/2, etc..).

- the directory where all object files will be stored (usually `freetype2/obj`), as well as the one containing the library file (usually the same as for objects).

- the command line compiler, and its compilation flags for indicating a new include path (usually "`-I`"), a new macro declaration (usually "`-D`") or the target object file (usually "`-o` ")

Once these variable are defined, `config.mk` test for the definition of the `BUILD_FREETYPE` variable. If it exists, the makefile then includes "`freetype2/config/freetype.mk`" which contains the rules required to compile the library.

Note that `freetype.mk` also scans the subdirectories of "`freetype2/src`" for a file called "`rules.mk`". Each `rules.mk` contains, as it names suggests, the rules required to compile a given font driver or module.

Once all this parsing is done, the library can be compiled. Usually, each font driver is compiled as a standalone object file (e.g. `sfnt.o`, `truetype.o` and `type1.o`).

This process can be illustrated by the following graphics:

## IIV. Managing the list of modules

The makefile `freetype.mk` only determines how to compile each one of the modules that are located in the sub-directories of `freetype2/src`.

However, when the function `FT_Init_FreeType` is invoked at the start of an application, it must create a new `FT_Library` object, and registers all known font drivers to it by repeatly calling `FT_Add_Driver`.

The list of known drivers is located in the file "`freetype2/config/system/ftmodule.h`", and is used exclusively by the internal function `FT_Default_Drivers`. The list in `ftmodule.h` must be re-generated each time you add or remove a module from `freetype2/src`.

This is normally performed by invoking the top-level `Makefile` with the `modules` target, as in:

`make modules`

This will trigger a special rule that will re-generate `ftmodule.h`. To do so, the Makefile will parse all module directories for a file called "`module.mk`". Each `module.mk` is a tiny sub-Makefile used to add a single module to the driver list.

This is illustrated by the following graphics:

Note that the new list of modules is displayed in a very human-friendly way after a "`make modules`". Here's an example with the current source tree (on 11 Jan 2000):

    Regenerating the font drivers list in ./config/unix/ftmodule.h
    * driver:  sfnt      ( pseudo-driver for TrueType & OpenType formats )
    * driver:  truetype  ( Windows/Mac font files with extension *.ttf or *.ttc )
    * driver:  type1     ( Postscript font files with extension *.pfa or *.pfb )
    -- done --

## V. Building the demonstration programs

Several demonstration programs are located in the "`freetype2/demos`" directory hierarchy. This directory also includes a tiny graphics sub-system that is able to blit glyphs to a great variety of surfaces, as well as display these in various graphics libraries or windowed environments.

This section describes how the demonstration programs are compiled, using the configuration `freetype2/config.mk` and their own `freetype2/demos/Makefile`.

To compile the demonstration programs, after the library, simply go to `freetype2/demos` then invoke GNU make with no arguments.

The top-level Makefile will detect the `config.mk` in the upper directory and include it. Because it doesn't define the `BUILD_FREETYPE` variable, this will not force the inclusion of `freetype2/config/freetype.mk` as described in the previous section.

the `Makefile` will then include the makefile called "`freetype2/demos/graph/rules.mk`". The graphics `rules.mk` defines the rules required to compile the graphics sub-system.

Because the graphics syb-system is also designed modularly, it is able to use any number of "modules" to display surfaces on the screen. The graphics modules are located in the subdirectories of `freetype2/demos/config`. Each such directory contains a file named `rules.mk` which is in charge of:

- detecting wether the corresponding graphics library is available at the time of compilation.

- if it is, alter the compilation rules to include the graphics module in the build of the `graph` library.

When the `graph` library is built in `demos/obj`, the demonstration programs executables are generated by the top-level Makefile.

This is illustrated by the following graphics: