Next: , Up: Library Projects


5.5.1 Building Libraries

Let's enhance our example and transform the logging subsystem into a library. In order to do so, a few changes need to be made to logging.gpr. Some attributes need to be defined: at least Library_Name and Library_Dir; in addition, some other attributes can be used to specify specific aspects of the library. For readability, it is also recommended (although not mandatory), to use the qualifier library in front of the project keyword.

`Library_Name':

This attribute is the name of the library to be built. There is no restriction on the name of a library imposed by the project manager, except for stand-alone libraries whose names must follow the syntax of Ada identifiers; however, there may be system-specific restrictions on the name. In general, it is recommended to stick to alphanumeric characters (and possibly single underscores) to help portability.

`Library_Dir':

This attribute is the path (absolute or relative) of the directory where the library is to be installed. In the process of building a library, the sources are compiled, the object files end up in the explicit or implicit Object_Dir directory. When all sources of a library are compiled, some of the compilation artifacts, including the library itself, are copied to the library_dir directory. This directory must exist and be writable. It must also be different from the object directory so that cleanup activities in the Library_Dir do not affect recompilation needs.

Here is the new version of logging.gpr that makes it a library:

    library project Logging is          --  "library" is optional
       for Library_Name use "logging";  --  will create "liblogging.a" on Unix
       for Object_Dir   use "obj";
       for Library_Dir  use "lib";      --  different from object_dir
    end Logging;

Once the above two attributes are defined, the library project is valid and is enough for building a library with default characteristics. Other library-related attributes can be used to change the defaults:

`Library_Kind':

The value of this attribute must be either "static", "dynamic" or "relocatable" (the latter is a synonym for dynamic). It indicates which kind of library should be built (the default is to build a static library, that is an archive of object files that can potentially be linked into a static executable). When the library is set to be dynamic, a separate image is created that will be loaded independently, usually at the start of the main program execution. Support for dynamic libraries is very platform specific, for instance on Windows it takes the form of a DLL while on GNU/Linux, it is a dynamic elf image whose suffix is usually .so. Library project files, on the other hand, can be written in a platform independent way so that the same project file can be used to build a library on different operating systems.

If you need to build both a static and a dynamic library, it is recommended to use two different object directories, since in some cases some extra code needs to be generated for the latter. For such cases, one can either define two different project files, or a single one that uses scenarios to indicate the various kinds of library to be built and their corresponding object_dir.

`Library_ALI_Dir':

This attribute may be specified to indicate the directory where the ALI files of the library are installed. By default, they are copied into the Library_Dir directory, but as for the executables where we have a separate Exec_Dir attribute, you might want to put them in a separate directory since there can be hundreds of them. The same restrictions as for the Library_Dir attribute apply.

`Library_Version':

This attribute is platform dependent, and has no effect on Windows. On Unix, it is used only for dynamic libraries as the internal name of the library (the "soname"). If the library file name (built from the Library_Name) is different from the Library_Version, then the library file will be a symbolic link to the actual file whose name will be Library_Version. This follows the usual installation schemes for dynamic libraries on many Unix systems.

    project Logging is
       Version := "1";
       for Library_Dir use "lib";
       for Library_Name use "logging";
       for Library_Kind use "dynamic";
       for Library_Version use "liblogging.so." & Version;
    end Logging;

After the compilation, the directory lib will contain both a libdummy.so.1 library and a symbolic link to it called libdummy.so.

`Library_GCC':

This attribute is the name of the tool to use instead of "gcc" to link shared libraries. A common use of this attribute is to define a wrapper script that accomplishes specific actions before calling gcc (which itself calls the linker to build the library image).

`Library_Options':

This attribute may be used to specify additional switches (last switches) when linking a shared library.

It may also be used to add foreign object files to a static library. Each string in Library_Options is an absolute or relative path of an object file. When a relative path, it is relative to the object directory.

`Leading_Library_Options':

This attribute, that is taken into account only by `gprbuild', may be used to specified leading options (first switches) when linking a shared library.

`Linker.Linker_Options':

This attribute specifies additional switches to be given to the linker when linking an executable. It is ignored when defined in the main project and taken into account in all other projects that are imported directly or indirectly. These switches complement the Linker.Switches defined in the main project. This is useful when a particular subsystem depends on an external library: adding this dependency as a Linker_Options in the project of the subsystem is more convenient than adding it to all the Linker.Switches of the main projects that depend upon this subsystem.