FreeType 2 Internals - I/O Frames

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 currentdirectory, 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: