Next: , Previous: Main Subprograms, Up: Building With Projects


11.2.4 Tools Options in Project Files

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:

Default_Switches:
This is the first mention in this manual of an indexed attribute. When this attribute is defined, one must supply an index in the form of a literal string. In the case of Default_Switches, the index is the name of the language to which the switches apply (since a different compiler will likely be used for each language, and each compiler has its own set of switches). The value of the attribute is a list of 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;

Switches:
in some cases, we might want to use specific switches for one or more files. For instance, compiling proc.adb might not be possible at high level of optimization because of a compiler issue. In such a case, the Switches attribute (indexed on the file name) can be used and will override the switches defined by Default_Switches. Our project file would become:
            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.

Local_Configuration_Pragmas:
this attribute may specify the path of a file containing configuration pragmas for use by the Ada compiler, such as 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).