We now have a project file that fully describes our environment, and can be used to build the application with a simple gnatmake command as seen in the previous section. In fact, the empty project we showed immediately at the beginning (with no attribute at all) could already fulfill that need if it was put in the common directory.
Of course, we always want more control. This section will show you how to specify the compilation switches that the various tools involved in the building of the executable should use.
Since source names and locations are described into the project file, it is not necessary to use switches on the command line for this purpose (switches such as -I for gcc). This removes a major source of command line length overflow. Clearly, the builders will have to communicate this information one way or another to the underlying compilers and tools they call but they usually use response files for this and thus should not be subject to command line overflows.
Several tools are participating to the creation of an executable: the compiler produces object files from the source files; the binder (in the Ada case) creates an source file that takes care, among other things, of elaboration issues and global variables initialization; and the linker gathers everything into a single executable that users can execute. All these tools are known by the project manager and will be called with user defined switches from the project files. However, we need to introduce a new project file concept to express which switches to be used for any of the tools involved in the build.
A project file is subdivided into zero or more packages, each of which contains the attributes specific to one tool (or one set of tools). Project files use an Ada-like syntax for packages. Package names permitted in project files are restricted to a predefined set (see Packages), and the contents of packages are limited to a small set of constructs and attributes (see Attributes).
Our example project file can be extended with the following empty packages. At this stage, they could all be omitted since they are empty, but they show which packages would be involved in the build process.
project Build is for Source_Dirs use ("common"); for Object_Dir use "obj"; for Exec_Dir use "."; for Main use ("proc.adb"); end Build; package Builder is --<<< for gnatmake and gprbuild end Builder; package Compiler is --<<< for the compiler end Compiler; package Binder is --<<< for the binder end Binder; package Linker is --<<< for the linker end Linker;
Let's first examine the compiler switches. As stated in the initial description of the example, we want to compile all files with -O2. This is a compiler switch, although it is usual, on the command line, to pass it to the builder which then passes it to the compiler. It is recommended to use directly the right package, which will make the setup easier to understand for other people.
Several attributes can be used to specify the switches:
In this example, we want to compile all Ada source files with the
-O2 switch, and the resulting project file is as follows
(only the Compiler
package is shown):
package Compiler is for Default_Switches ("Ada") use ("-O2"); end Compiler;
package Compiler is for Default_Switches ("Ada") use ("-O2"); for Switches ("proc.adb") use ("-O0"); end Compiler;
Switches
may take a pattern as an index, such as in:
package Compiler is for Default_Switches ("Ada") use ("-O2"); for Switches ("pkg*") use ("-O0"); end Compiler;
Sources pkg.adb and pkg-child.adb would be compiled with -O0, not -O2.
Switches
can also be given a language name as index instead of a file
name in which case it has the same semantics as Default_Switches.
However, indexes with wild cards are never valid for language name.
pragma Restrictions (No_Tasking)
. These pragmas will be
used for all the sources of the project.
The switches for the other tools are defined in a similar manner through the Default_Switches and Switches attributes, respectively in the Builder package (for gnatmake and gprbuild), the Binder package (binding Ada executables) and the Linker package (for linking executables).