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.
It is also possible to build multi-language libraries. When using gprbuild as a builder, multi-language library projects allow naturally the creation of multi-language libraries . gnatmake, does not try to compile non Ada sources. However, when the project is multi-language, it will automatically link all object files found in the object directory, whether or not they were compiled from an Ada source file. This specific behavior does not apply to Ada-only projects which only take into account the objects corresponding to the sources of the project.
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 non 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.ads, log1.adb, log2.ads and
log2.adb. If log1.adb has been modified, then the library
liblogging will be rebuilt when compiling all the sources of
Build only if proc.ads, pack.ads or pack.adb
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 needs to be used:
gnatmake -Plogging.gpr gnatmake -Pbuild.gpr
All ALI files will also be copied from the object directory to the library directory. To build executables, gnatmake will use the library rather than the individual object files.
Library projects can also be useful to describe a library that need 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 simply to
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
attribute does not need to be specified because it will never be
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
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
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.