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.
A number of specific attributes needs to be defined: at least Library_Name
and Library_Dir
; in addition, a number of 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.
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 exists 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:
"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 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 which uses scenarios to indicate the various kinds of library to be built and their corresponding object_dir.
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.
"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.
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.