When the builder detects that a project file is a library project file, it recompiles all sources of the project that need recompilation and rebuild the library if any of the sources have been recompiled. It then groups all object files into a single file, which is a shared or a static library. This library can later on be linked with multiple executables. Note that the use of shard libraries reduces the size of the final executable and can also reduce the memory footprint at execution time when the library is shared among several executables.
`gprbuild also allows to build **multi-language libraries*' when specifying sources from multiple languages.
A non-library project can import a library project. When the builder is invoked
on the former, the library of the latter is only rebuilt when absolutely
necessary. For instance, if a unit of the library is not up-to-date but none of
the executables need this unit, then the unit is not recompiled and the library
is not reassembled. For instance, let's assume in our example that logging has
the following sources:
log1.adb has been modified, then the library
liblogging will be rebuilt when compiling all the sources of
Build only if
include a "with Log1".
To ensure that all the sources in the Logging library are up to date, and that all the sources of Build are also up to date, the following two commands need to be used:
gprbuild -Plogging.gpr gprbuild -Pbuild.gpr
ALI files will also be copied from the object directory to the
library directory. To build executables, `gprbuild' will use the
library rather than the individual object files.
Library projects can also be useful to describe a library that needs to be used but, for some reason, cannot be rebuilt. For instance, it is the case when some of the library sources are not available. Such library projects need to use the Externally_Built attribute as in the example below:
library project Extern_Lib is for Languages use ("Ada", "C"); for Source_Dirs use ("lib_src"); for Library_Dir use "lib2"; for Library_Kind use "dynamic"; for Library_Name use "l2"; for Externally_Built use "true"; -- <<<< end Extern_Lib;
In the case of externally built libraries, the Object_Dir attribute does not need to be specified because it will never be used.
The main effect of using such an externally built library project is mostly to affect the linker command in order to reference the desired library. It can also be achieved by using Linker.Linker_Options or Linker.Switches in the project corresponding to the subsystem needing this external library. This latter method is more straightforward in simple cases but when several subsystems depend upon the same external library, finding the proper place for the Linker.Linker_Options might not be easy and if it is not placed properly, the final link command is likely to present ordering issues. In such a situation, it is better to use the externally built library project so that all other subsystems depending on it can declare this dependency thanks to a project `with' clause, which in turn will trigger the builder to find the proper order of libraries in the final link command.