[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11. GNAT Project Manager

11.1 Introduction  
11.2 Examples of Project Files  
11.3 Project File Syntax  
11.4 Objects and Sources in Project Files  
11.5 Importing Projects  
11.6 Project Extension  
11.7 Project Hierarchy Extension  
11.8 External References in Project Files  
11.9 Packages in Project Files  
11.10 Variables from Imported Projects  
11.11 Naming Schemes  
11.12 Library Projects  
11.13 Stand-alone Library Projects  
11.14 Switches Related to Project Files  
11.15 Tools Supporting Project Files  
11.16 An Extended Example  
11.17 Project File Complete Syntax  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.1 Introduction

This chapter describes GNAT's Project Manager, a facility that allows you to manage complex builds involving a number of source files, directories, and compilation options for different system configurations. In particular, project files allow you to specify:

11.1.1 Project Files  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.1.1 Project Files

Project files are written in a syntax close to that of Ada, using familiar notions such as packages, context clauses, declarations, default values, assignments, and inheritance. Finally, project files can be built hierarchically from other project files, simplifying complex system integration and project reuse.

A project is a specific set of values for various compilation properties. The settings for a given project are described by means of a project file, which is a text file written in an Ada-like syntax. Property values in project files are either strings or lists of strings. Properties that are not explicitly set receive default values. A project file may interrogate the values of external variables (user-defined command-line switches or environment variables), and it may specify property settings conditionally, based on the value of such variables.

In simple cases, a project's source files depend only on other source files in the same project, or on the predefined libraries. (Dependence is used in the Ada technical sense; as in one Ada unit withing another.) However, the Project Manager also allows more sophisticated arrangements, where the source files in one project depend on source files in other projects:

More generally, the Project Manager lets you structure large development efforts into hierarchical subsystems, where build decisions are delegated to the subsystem level, and thus different compilation environments (switch settings) used for different subsystems.

The Project Manager is invoked through the `-Pprojectfile' switch to gnatmake or to the gnat front driver. There may be zero, one or more spaces between `-P' and `projectfile'. If you want to define (on the command line) an external variable that is queried by the project file, you must use the `-Xvbl=value' switch. The Project Manager parses and interprets the project file, and drives the invoked tool based on the project settings.

The Project Manager supports a wide range of development strategies, for systems of all sizes. Here are some typical practices that are easily handled:

The destination of an executable can be controlled inside a project file using the `-o' switch. In the absence of such a switch either inside the project file or on the command line, any executable files generated by gnatmake are placed in the directory Exec_Dir specified in the project file. If no Exec_Dir is specified, they will be placed in the object directory of the project.

You can use project files to achieve some of the effects of a source versioning system (for example, defining separate projects for the different sets of sources that comprise different releases) but the Project Manager is independent of any source configuration management tools that might be used by the developers.

The next section introduces the main features of GNAT's project facility through a sequence of examples; subsequent sections will present the syntax and semantics in more detail. A more formal description of the project facility appears in the GNAT Reference Manual.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2 Examples of Project Files

This section illustrates some of the typical uses of project files and explains their basic structure and behavior.

11.2.1 Common Sources with Different Switches and Directories  
11.2.2 Using External Variables  
11.2.3 Importing Other Projects  
11.2.4 Extending a Project  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2.1 Common Sources with Different Switches and Directories

Source Files  
Specifying the Object Directory  
Specifying the Exec Directory  
Project File Packages  
Specifying Switch Settings  
Main Subprograms  
Executable File Names  
Source File Naming Conventions  
Source Language(s)  

Suppose that the Ada source files `pack.ads', `pack.adb', and `proc.adb' are in the `/common' directory. The file `proc.adb' contains an Ada main subprogram Proc that withs package Pack. We want to compile these source files under two sets of switches:

The GNAT project files shown below, respectively `debug.gpr' and `release.gpr' in the `/common' directory, achieve these effects.

Schematically:
 
/common
  debug.gpr
  release.gpr
  pack.ads
  pack.adb
  proc.adb
/common/debug
  proc.ali, proc.o
  pack.ali, pack.o
/common/release
  proc.ali, proc.o
  pack.ali, pack.o
Here are the corresponding project files:

 
project Debug is
  for Object_Dir use "debug";
  for Main use ("proc");

  package Builder is
    for Default_Switches ("Ada")
        use ("-g");
    for Executable ("proc.adb") use "proc1";
  end Builder;

  package Compiler is
    for Default_Switches ("Ada")
       use ("-fstack-check",
            "-gnata",
            "-gnato",
            "-gnatE");
  end Compiler;
end Debug;

 
project Release is
  for Object_Dir use "release";
  for Exec_Dir use ".";
  for Main use ("proc");

  package Compiler is
    for Default_Switches ("Ada")
        use ("-O2");
  end Compiler;
end Release;

The name of the project defined by `debug.gpr' is "Debug" (case insensitive), and analogously the project defined by `release.gpr' is "Release". For consistency the file should have the same name as the project, and the project file's extension should be "gpr". These conventions are not required, but a warning is issued if they are not followed.

If the current directory is `/temp', then the command
 
gnatmake -P/common/debug.gpr

generates object and ALI files in `/common/debug', as well as the proc1 executable, using the switch settings defined in the project file.

Likewise, the command
 
gnatmake -P/common/release.gpr

generates object and ALI files in `/common/release', and the proc executable in `/common', using the switch settings from the project file.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Source Files

If a project file does not explicitly specify a set of source directories or a set of source files, then by default the project's source files are the Ada source files in the project file directory. Thus `pack.ads', `pack.adb', and `proc.adb' are the source files for both projects.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Specifying the Object Directory

Several project properties are modeled by Ada-style attributes; a property is defined by supplying the equivalent of an Ada attribute definition clause in the project file. A project's object directory is another such a property; the corresponding attribute is Object_Dir, and its value is also a string expression, specified either as absolute or relative. In the later case, it is relative to the project file directory. Thus the compiler's output is directed to `/common/debug' (for the Debug project) and to `/common/release' (for the Release project). If Object_Dir is not specified, then the default is the project file directory itself.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Specifying the Exec Directory

A project's exec directory is another property; the corresponding attribute is Exec_Dir, and its value is also a string expression, either specified as relative or absolute. If Exec_Dir is not specified, then the default is the object directory (which may also be the project file directory if attribute Object_Dir is not specified). Thus the executable is placed in `/common/debug' for the Debug project (attribute Exec_Dir not specified) and in `/common' for the Release project.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Project File Packages

A GNAT tool that is integrated with the Project Manager is modeled by a corresponding package in the project file. In the example above, The Debug project defines the packages Builder (for gnatmake) and Compiler; the Release project defines only the Compiler package.

The Ada-like package syntax is not to be taken literally. Although packages in project files bear a surface resemblance to packages in Ada source code, the notation is simply a way to convey a grouping of properties for a named entity. Indeed, the package names permitted in project files are restricted to a predefined set, corresponding to the project-aware tools, and the contents of packages are limited to a small set of constructs. The packages in the example above contain attribute definitions.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Specifying Switch Settings

Switch settings for a project-aware tool can be specified through attributes in the package that corresponds to the tool. The example above illustrates one of the relevant attributes, Default_Switches, which is defined in packages in both project files. Unlike simple attributes like Source_Dirs, Default_Switches is known as an associative array. When you define this attribute, you must supply an "index" (a literal string), and the effect of the attribute definition is to set the value of the array at the specified index. For the Default_Switches attribute, the index is a programming language (in our case, Ada), and the value specified (after use) must be a list of string expressions.

The attributes permitted in project files are restricted to a predefined set. Some may appear at project level, others in packages. For any attribute that is an associative array, the index must always be a literal string, but the restrictions on this string (e.g., a file name or a language name) depend on the individual attribute. Also depending on the attribute, its specified value will need to be either a string or a string list.

In the Debug project, we set the switches for two tools, gnatmake and the compiler, and thus we include the two corresponding packages; each package defines the Default_Switches attribute with index "Ada". Note that the package corresponding to gnatmake is named Builder. The Release project is similar, but only includes the Compiler package.

In project Debug above, the switches starting with `-gnat' that are specified in package Compiler could have been placed in package Builder, since gnatmake transmits all such switches to the compiler.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Main Subprograms

One of the specifiable properties of a project is a list of files that contain main subprograms. This property is captured in the Main attribute, whose value is a list of strings. If a project defines the Main attribute, it is not necessary to identify the main subprogram(s) when invoking gnatmake (see section 11.15.1 gnatmake and Project Files).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Executable File Names

By default, the executable file name corresponding to a main source is deduced from the main source file name. Through the attributes Executable and Executable_Suffix of package Builder, it is possible to change this default. In project Debug above, the executable file name for main source `proc.adb' is `proc1'. Attribute Executable_Suffix, when specified, may change the suffix of the the executable files, when no attribute Executable applies: its value replace the platform-specific executable suffix. Attributes Executable and Executable_Suffix are the only ways to specify a non default executable file name when several mains are built at once in a single gnatmake command.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Source File Naming Conventions

Since the project files above do not specify any source file naming conventions, the GNAT defaults are used. The mechanism for defining source file naming conventions -- a package named Naming -- is described below (see section 11.11 Naming Schemes).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Source Language(s)

Since the project files do not specify a Languages attribute, by default the GNAT tools assume that the language of the project file is Ada. More generally, a project can comprise source files in Ada, C, and/or other languages.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2.2 Using External Variables

Instead of supplying different project files for debug and release, we can define a single project file that queries an external variable (set either on the command line or via an environment variable) in order to conditionally define the appropriate settings. Again, assume that the source files `pack.ads', `pack.adb', and `proc.adb' are located in directory `/common'. The following project file, `build.gpr', queries the external variable named STYLE and defines an object directory and switch settings based on whether the value is "deb" (debug) or "rel" (release), and where the default is "deb".

 
project Build is
  for Main use ("proc");

  type Style_Type is ("deb", "rel");
  Style : Style_Type := external ("STYLE", "deb");

  case Style is
    when "deb" =>
      for Object_Dir use "debug";

    when "rel" =>
      for Object_Dir use "release";
      for Exec_Dir use ".";
  end case;

  package Builder is

    case Style is
      when "deb" =>
        for Default_Switches ("Ada")
            use ("-g");
        for Executable ("proc") use "proc1";
      when others =>
        null;
    end case;

  end Builder;

  package Compiler is

    case Style is
      when "deb" =>
        for Default_Switches ("Ada")
            use ("-gnata",
                 "-gnato",
                 "-gnatE");

      when "rel" =>
        for Default_Switches ("Ada")
            use ("-O2");
    end case;

  end Compiler;

end Build;

Style_Type is an example of a string type, which is the project file analog of an Ada enumeration type but whose components are string literals rather than identifiers. Style is declared as a variable of this type.

The form external("STYLE", "deb") is known as an external reference; its first argument is the name of an external variable, and the second argument is a default value to be used if the external variable doesn't exist. You can define an external variable on the command line via the `-X' switch, or you can use an environment variable as an external variable.

Each case construct is expanded by the Project Manager based on the value of Style. Thus the command
 
gnatmake -P/common/build.gpr -XSTYLE=deb

is equivalent to the gnatmake invocation using the project file `debug.gpr' in the earlier example. So is the command
 
gnatmake -P/common/build.gpr

since "deb" is the default for STYLE.

Analogously,

 
gnatmake -P/common/build.gpr -XSTYLE=rel

is equivalent to the gnatmake invocation using the project file `release.gpr' in the earlier example.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2.3 Importing Other Projects

A compilation unit in a source file in one project may depend on compilation units in source files in other projects. To compile this unit under control of a project file, the dependent project must import the projects containing the needed source files. This effect is obtained using syntax similar to an Ada with clause, but where withed entities are strings that denote project files.

As an example, suppose that the two projects GUI_Proj and Comm_Proj are defined in the project files `gui_proj.gpr' and `comm_proj.gpr' in directories `/gui' and `/comm', respectively. Suppose that the source files for GUI_Proj are `gui.ads' and `gui.adb', and that the source files for Comm_Proj are `comm.ads' and `comm.adb', where each set of files is located in its respective project file directory. Schematically:

 
/gui
  gui_proj.gpr
  gui.ads
  gui.adb

/comm
  comm_proj.gpr
  comm.ads
  comm.adb

We want to develop an application in directory `/app' that with the packages GUI and Comm, using the properties of the corresponding project files (e.g. the switch settings and object directory). Skeletal code for a main procedure might be something like the following:

 
with GUI, Comm;
procedure App_Main is
   ...
begin
   ...
end App_Main;

Here is a project file, `app_proj.gpr', that achieves the desired effect:

 
with "/gui/gui_proj", "/comm/comm_proj";
project App_Proj is
   for Main use ("app_main");
end App_Proj;

Building an executable is achieved through the command:
 
gnatmake -P/app/app_proj
which will generate the app_main executable in the directory where `app_proj.gpr' resides.

If an imported project file uses the standard extension (gpr) then (as illustrated above) the with clause can omit the extension.

Our example specified an absolute path for each imported project file. Alternatively, the directory name of an imported object can be omitted if either

Thus, if we define ADA_PROJECT_PATH to include `/gui' and `/comm', then our project file `app_proj.gpr' can be written as follows:

 
with "gui_proj", "comm_proj";
project App_Proj is
   for Main use ("app_main");
end App_Proj;

Importing other projects can create ambiguities. For example, the same unit might be present in different imported projects, or it might be present in both the importing project and in an imported project. Both of these conditions are errors. Note that in the current version of the Project Manager, it is illegal to have an ambiguous unit even if the unit is never referenced by the importing project. This restriction may be relaxed in a future release.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2.4 Extending a Project

In large software systems it is common to have multiple implementations of a common interface; in Ada terms, multiple versions of a package body for the same specification. For example, one implementation might be safe for use in tasking programs, while another might only be used in sequential applications. This can be modeled in GNAT using the concept of project extension. If one project (the "child") extends another project (the "parent") then by default all source files of the parent project are inherited by the child, but the child project can override any of the parent's source files with new versions, and can also add new files. This facility is the project analog of a type extension in Object-Oriented Programming. Project hierarchies are permitted (a child project may be the parent of yet another project), and a project that inherits one project can also import other projects.

As an example, suppose that directory `/seq' contains the project file `seq_proj.gpr' as well as the source files `pack.ads', `pack.adb', and `proc.adb':

 
/seq
  pack.ads
  pack.adb
  proc.adb
  seq_proj.gpr

Note that the project file can simply be empty (that is, no attribute or package is defined):

 
project Seq_Proj is
end Seq_Proj;

implying that its source files are all the Ada source files in the project directory.

Suppose we want to supply an alternate version of `pack.adb', in directory `/tasking', but use the existing versions of `pack.ads' and `proc.adb'. We can define a project Tasking_Proj that inherits Seq_Proj:

 
/tasking
  pack.adb
  tasking_proj.gpr

project Tasking_Proj extends "/seq/seq_proj" is
end Tasking_Proj;

The version of `pack.adb' used in a build depends on which project file is specified.

Note that we could have obtained the desired behavior using project import rather than project inheritance; a base project would contain the sources for `pack.ads' and `proc.adb', a sequential project would import base and add `pack.adb', and likewise a tasking project would import base and add a different version of `pack.adb'. The choice depends on whether other sources in the original project need to be overridden. If they do, then project extension is necessary, otherwise, importing is sufficient.

In a project file that extends another project file, it is possible to indicate that an inherited source is not part of the sources of the extending project. This is necessary sometimes when a package spec has been overloaded and no longer requires a body: in this case, it is necessary to indicate that the inherited body is not part of the sources of the project, otherwise there will be a compilation error when compiling the spec.

For that purpose, the attribute Locally_Removed_Files is used. Its value is a string list: a list of file names.

 
project B extends "a" is
   for Source_Files use ("pkg.ads");
   --  New spec of Pkg does not need a completion
   for Locally_Removed_Files use ("pkg.adb");
end B;

Attribute Locally_Removed_Files may also be used to check if a source is still needed: if it is possible to build using gnatmake when such a source is put in attribute Locally_Removed_Files of a project P, then it is possible to remove the source completely from a system that includes project P.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3 Project File Syntax

11.3.1 Basic Syntax  
11.3.2 Packages  
11.3.3 Expressions  
11.3.4 String Types  
11.3.5 Variables  
11.3.6 Attributes  
11.3.7 Associative Array Attributes  
11.3.8 case Constructions  

This section describes the structure of project files.

A project may be an independent project, entirely defined by a single project file. Any Ada source file in an independent project depends only on the predefined library and other Ada source files in the same project.

A project may also depend on other projects, in either or both of the following ways:

The dependence relation is a directed acyclic graph (the subgraph reflecting the "extends" relation is a tree).

A project's immediate sources are the source files directly defined by that project, either implicitly by residing in the project file's directory, or explicitly through any of the source-related attributes described below. More generally, a project proj's sources are the immediate sources of proj together with the immediate sources (unless overridden) of any project on which proj depends (either directly or indirectly).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.1 Basic Syntax

As seen in the earlier examples, project files have an Ada-like syntax. The minimal project file is:
 
project Empty is

end Empty;

The identifier Empty is the name of the project. This project name must be present after the reserved word end at the end of the project file, followed by a semi-colon.

Any name in a project file, such as the project name or a variable name, has the same syntax as an Ada identifier.

The reserved words of project files are the Ada reserved words plus extends, external, and project. Note that the only Ada reserved words currently used in project file syntax are:

Comments in project files have the same syntax as in Ada, two consecutives hyphens through the end of the line.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.2 Packages

A project file may contain packages. The name of a package must be one of the identifiers from the following list. A package with a given name may only appear once in a project file. Package names are case insensitive. The following package names are legal:

In its simplest form, a package may be empty:

 
project Simple is
  package Builder is
  end Builder;
end Simple;

A package may contain attribute declarations, variable declarations and case constructions, as will be described below.

When there is ambiguity between a project name and a package name, the name always designates the project. To avoid possible confusion, it is always a good idea to avoid naming a project with one of the names allowed for packages or any name that starts with gnat.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.3 Expressions

An expression is either a string expression or a string list expression.

A string expression is either a simple string expression or a compound string expression.

A simple string expression is one of the following:

A compound string expression is a concatenation of string expressions, using the operator "&"
 
       Path & "/" & File_Name & ".ads"

A string list expression is either a simple string list expression or a compound string list expression.

A simple string list expression is one of the following:

A compound string list expression is the concatenation (using "&") of a simple string list expression and an expression. Note that each term in a compound string list expression, except the first, may be either a string expression or a string list expression.

 
   File_Name_List := () & File_Name; --  One string in this list
   Extended_File_Name_List := File_Name_List & (File_Name & ".orig");
   --  Two strings
   Big_List := File_Name_List & Extended_File_Name_List;
   --  Concatenation of two string lists: three strings
   Illegal_List := "gnat.adc" & Extended_File_Name_List;
   --  Illegal: must start with a string list


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.4 String Types

A string type declaration introduces a discrete set of string literals. If a string variable is declared to have this type, its value is restricted to the given set of literals.

Here is an example of a string type declaration:

 
   type OS is ("NT", "nt", "Unix", "GNU/Linux", "other OS");

Variables of a string type are called typed variables; all other variables are called untyped variables. Typed variables are particularly useful in case constructions, to support conditional attribute declarations. (see section 11.3.8 case Constructions).

The string literals in the list are case sensitive and must all be different. They may include any graphic characters allowed in Ada, including spaces.

A string type may only be declared at the project level, not inside a package.

A string type may be referenced by its name if it has been declared in the same project file, or by an expanded name whose prefix is the name of the project in which it is declared.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.5 Variables

A variable may be declared at the project file level, or within a package. Here are some examples of variable declarations:

 
   This_OS : OS := external ("OS"); --  a typed variable declaration
   That_OS := "GNU/Linux";          --  an untyped variable declaration

The syntax of a typed variable declaration is identical to the Ada syntax for an object declaration. By contrast, the syntax of an untyped variable declaration is identical to an Ada assignment statement. In fact, variable declarations in project files have some of the characteristics of an assignment, in that successive declarations for the same variable are allowed. Untyped variable declarations do establish the expected kind of the variable (string or string list), and successive declarations for it must respect the initial kind.

A string variable declaration (typed or untyped) declares a variable whose value is a string. This variable may be used as a string expression.
 
   File_Name       := "readme.txt";
   Saved_File_Name := File_Name & ".saved";

A string list variable declaration declares a variable whose value is a list of strings. The list may contain any number (zero or more) of strings.

 
   Empty_List := ();
   List_With_One_Element := ("-gnaty");
   List_With_Two_Elements := List_With_One_Element & "-gnatg";
   Long_List := ("main.ada", "pack1_.ada", "pack1.ada", "pack2_.ada"
                 "pack2.ada", "util_.ada", "util.ada");

The same typed variable may not be declared more than once at project level, and it may not be declared more than once in any package; it is in effect a constant.

The same untyped variable may be declared several times. Declarations are elaborated in the order in which they appear, so the new value replaces the old one, and any subsequent reference to the variable uses the new value. However, as noted above, if a variable has been declared as a string, all subsequent declarations must give it a string value. Similarly, if a variable has been declared as a string list, all subsequent declarations must give it a string list value.

A variable reference may take several forms:

A context may be one of the following:

A variable reference may be used in an expression.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.6 Attributes

A project (and its packages) may have attributes that define the project's properties. Some attributes have values that are strings; others have values that are string lists.

There are two categories of attributes: simple attributes and associative arrays (see section 11.3.7 Associative Array Attributes).

Legal project attribute names, and attribute names for each legal package are listed below. Attributes names are case-insensitive.

The following attributes are defined on projects (all are simple attributes):

Attribute Name Value
Source_Files string list
Source_Dirs string list
Source_List_File string
Object_Dir string
Exec_Dir string
Locally_Removed_Files string list
Main string list
Languages string list
Main_Language string
Library_Dir string
Library_Name string
Library_Kind string
Library_Version string
Library_Interface string
Library_Auto_Init string
Library_Options string list
Library_GCC string

The following attributes are defined for package Naming (see section 11.11 Naming Schemes):

Attribute Name Category Index Value
Spec_Suffix associative array language name string
Body_Suffix associative array language name string
Separate_Suffix simple attribute n/a string
Casing simple attribute n/a string
Dot_Replacement simple attribute n/a string
Spec associative array Ada unit name string
Body associative array Ada unit name string
Specification_Exceptions associative array language name string list
Implementation_Exceptions associative array language name string list

The following attributes are defined for packages Builder, Compiler, Binder, Linker, Cross_Reference, and Finder (see section 11.15.1.1 Switches and Project Files).

Attribute Name Category Index Value
Default_Switches associative array language name string list
Switches associative array file name string list

In addition, package Compiler has a single string attribute Local_Configuration_Pragmas and package Builder has a single string attribute Global_Configuration_Pragmas.

Each simple attribute has a default value: the empty string (for string-valued attributes) and the empty list (for string list-valued attributes).

An attribute declaration defines a new value for an attribute.

Examples of simple attribute declarations:

 
   for Object_Dir use "objects";
   for Source_Dirs use ("units", "test/drivers");

The syntax of a simple attribute declaration is similar to that of an attribute definition clause in Ada.

Attributes references may be appear in expressions. The general form for such a reference is <entity>'<attribute>: Associative array attributes are functions. Associative array attribute references must have an argument that is a string literal.

Examples are:

 
  project'Object_Dir
  Naming'Dot_Replacement
  Imported_Project'Source_Dirs
  Imported_Project.Naming'Casing
  Builder'Default_Switches("Ada")

The prefix of an attribute may be:

Example:
 
   project Prj is
     for Source_Dirs use project'Source_Dirs & "units";
     for Source_Dirs use project'Source_Dirs & "test/drivers"
   end Prj;

In the first attribute declaration, initially the attribute Source_Dirs has the default value: an empty string list. After this declaration, Source_Dirs is a string list of one element: "units". After the second attribute declaration Source_Dirs is a string list of two elements: "units" and "test/drivers".

Note: this example is for illustration only. In practice, the project file would contain only one attribute declaration:

 
   for Source_Dirs use ("units", "test/drivers");


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.7 Associative Array Attributes

Some attributes are defined as associative arrays. An associative array may be regarded as a function that takes a string as a parameter and delivers a string or string list value as its result.

Here are some examples of single associative array attribute associations:

 
   for Body ("main") use "Main.ada";
   for Switches ("main.ada")
       use ("-v",
            "-gnatv");
   for Switches ("main.ada")
            use Builder'Switches ("main.ada")
              & "-g";

Like untyped variables and simple attributes, associative array attributes may be declared several times. Each declaration supplies a new value for the attribute, and replaces the previous setting.

An associative array attribute may be declared as a full associative array declaration, with the value of the same attribute in an imported or extended project.

 
   package Builder is
      for Default_Switches use Default.Builder'Default_Switches;
   end Builder;

In this example, Default must be either an project imported by the current project, or the project that the current project extends. If the attribute is in a package (in this case, in package Builder), the same package needs to be specified.

A full associative array declaration replaces any other declaration for the attribute, including other full associative array declaration. Single associative array associations may be declare after a full associative declaration, modifying the value for a single association of the attribute.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3.8 case Constructions

A case construction is used in a project file to effect conditional behavior. Here is a typical example:

 
project MyProj is
   type OS_Type is ("GNU/Linux", "Unix", "NT", "VMS");

   OS : OS_Type := external ("OS", "GNU/Linux");

   package Compiler is
     case OS is
       when "GNU/Linux" | "Unix" =>
         for Default_Switches ("Ada")
             use ("-gnath");
       when "NT" =>
         for Default_Switches ("Ada")
             use ("-gnatP");
       when others =>
     end case;
   end Compiler;
end MyProj;

The syntax of a case construction is based on the Ada case statement (although there is no null construction for empty alternatives).

The case expression must a typed string variable. Each alternative comprises the reserved word when, either a list of literal strings separated by the "|" character or the reserved word others, and the "=>" token. Each literal string must belong to the string type that is the type of the case variable. An others alternative, if present, must occur last.

After each =>, there are zero or more constructions. The only constructions allowed in a case construction are other case constructions and attribute declarations. String type declarations, variable declarations and package declarations are not allowed.

The value of the case variable is often given by an external reference (see section 11.8 External References in Project Files).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.4 Objects and Sources in Project Files

11.4.1 Object Directory  
11.4.2 Exec Directory  
11.4.3 Source Directories  
11.4.4 Source File Names  

Each project has exactly one object directory and one or more source directories. The source directories must contain at least one source file, unless the project file explicitly specifies that no source files are present (see section 11.4.4 Source File Names).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.4.1 Object Directory

The object directory for a project is the directory containing the compiler's output (such as `ALI' files and object files) for the project's immediate sources.

The object directory is given by the value of the attribute Object_Dir in the project file.

 
   for Object_Dir use "objects";

The attribute Object_Dir has a string value, the path name of the object directory. The path name may be absolute or relative to the directory of the project file. This directory must already exist, and be readable and writable.

By default, when the attribute Object_Dir is not given an explicit value or when its value is the empty string, the object directory is the same as the directory containing the project file.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.4.2 Exec Directory

The exec directory for a project is the directory containing the executables for the project's main subprograms.

The exec directory is given by the value of the attribute Exec_Dir in the project file.

 
   for Exec_Dir use "executables";

The attribute Exec_Dir has a string value, the path name of the exec directory. The path name may be absolute or relative to the directory of the project file. This directory must already exist, and be writable.

By default, when the attribute Exec_Dir is not given an explicit value or when its value is the empty string, the exec directory is the same as the object directory of the project file.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.4.3 Source Directories

The source directories of a project are specified by the project file attribute Source_Dirs.

This attribute's value is a string list. If the attribute is not given an explicit value, then there is only one source directory, the one where the project file resides.

A Source_Dirs attribute that is explicitly defined to be the empty list, as in

 
    for Source_Dirs use ();

indicates that the project contains no source files.

Otherwise, each string in the string list designates one or more source directories.

 
   for Source_Dirs use ("sources", "test/drivers");

If a string in the list ends with "/**", then the directory whose path name precedes the two asterisks, as well as all its subdirectories (recursively), are source directories.

 
   for Source_Dirs use ("/system/sources/**");

Here the directory /system/sources and all of its subdirectories (recursively) are source directories.

To specify that the source directories are the directory of the project file and all of its subdirectories, you can declare Source_Dirs as follows:
 
   for Source_Dirs use ("./**");

Each of the source directories must exist and be readable.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.4.4 Source File Names

In a project that contains source files, their names may be specified by the attributes Source_Files (a string list) or Source_List_File (a string). Source file names never include any directory information.

If the attribute Source_Files is given an explicit value, then each element of the list is a source file name.

 
   for Source_Files use ("main.adb");
   for Source_Files use ("main.adb", "pack1.ads", "pack2.adb");

If the attribute Source_Files is not given an explicit value, but the attribute Source_List_File is given a string value, then the source file names are contained in the text file whose path name (absolute or relative to the directory of the project file) is the value of the attribute Source_List_File.

Each line in the file that is not empty or is not a comment contains a source file name.

 
   for Source_List_File use "source_list.txt";

By default, if neither the attribute Source_Files nor the attribute Source_List_File is given an explicit value, then each file in the source directories that conforms to the project's naming scheme (see section 11.11 Naming Schemes) is an immediate source of the project.

A warning is issued if both attributes Source_Files and Source_List_File are given explicit values. In this case, the attribute Source_Files prevails.

Each source file name must be the name of one existing source file in one of the source directories.

A Source_Files attribute whose value is an empty list indicates that there are no source files in the project.

If the order of the source directories is known statically, that is if "/**" is not used in the string list Source_Dirs, then there may be several files with the same source file name. In this case, only the file in the first directory is considered as an immediate source of the project file. If the order of the source directories is not known statically, it is an error to have several files with the same source file name.

Projects can be specified to have no Ada source files: the value of (Source_Dirs or Source_Files may be an empty list, or the "Ada" may be absent from Languages:

 
   for Source_Dirs use ();
   for Source_Files use ();
   for Languages use ("C", "C++");

Otherwise, a project must contain at least one immediate source.

Projects with no source files are useful as template packages (see section 11.9 Packages in Project Files) for other projects; in particular to define a package Naming (see section 11.11 Naming Schemes).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.5 Importing Projects

An immediate source of a project P may depend on source files that are neither immediate sources of P nor in the predefined library. To get this effect, P must import the projects that contain the needed source files.

 
  with "project1", "utilities.gpr";
  with "/namings/apex.gpr";
  project Main is
    ...

As can be seen in this example, the syntax for importing projects is similar to the syntax for importing compilation units in Ada. However, project files use literal strings instead of names, and the with clause identifies project files rather than packages.

Each literal string is the file name or path name (absolute or relative) of a project file. If a string is simply a file name, with no path, then its location is determined by the project path:

If a relative pathname is used, as in

 
  with "tests/proj";

then the path is relative to the directory where the importing project file is located. Any symbolic link will be fully resolved in the directory of the importing project file before the imported project file is examined.

If the with'ed project file name does not have an extension, the default is `.gpr'. If a file with this extension is not found, then the file name as specified in the with clause (no extension) will be used. In the above example, if a file project1.gpr is found, then it will be used; otherwise, if a file project1 exists then it will be used; if neither file exists, this is an error.

A warning is issued if the name of the project file does not match the name of the project; this check is case insensitive.

Any source file that is an immediate source of the imported project can be used by the immediate sources of the importing project, transitively. Thus if A imports B, and B imports C, the immediate sources of A may depend on the immediate sources of C, even if A does not import C explicitly. However, this is not recommended, because if and when B ceases to import C, some sources in A will no longer compile.

A side effect of this capability is that normally cyclic dependencies are not permitted: if A imports B (directly or indirectly) then B is not allowed to import A. However, there are cases when cyclic dependencies would be beneficial. For these cases, another form of import between projects exists, the limited with: a project A that imports a project B with a straigh with may also be imported, directly or indirectly, by B on the condition that imports from B to A include at least one limited with.

 
with "../b/b.gpr";
with "../c/c.gpr";
project A is
end A;

limited with "../a/a.gpr";
project B is
end B;

with "../d/d.gpr";
project C is
end C;

limited with "../a/a.gpr";
project D is
end D;

In the above legal example, there are two project cycles:

In each of these cycle there is one limited with: import of A from B and import of A from D.

The difference between straight with and limited with is that the name of a project imported with a limited with cannot be used in the project that imports it. In particular, its packages cannot be renamed and its variables cannot be referred to.

An exception to the above rules for limited with is that for the main project specified to gnatmake or to the GNAT driver a limited with is equivalent to a straight with. For example, in the example above, projects B and D could not be main projects for gnatmake or to the GNAT driver, because they each have a limited with that is the only one in a cycle of importing projects.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.6 Project Extension

During development of a large system, it is sometimes necessary to use modified versions of some of the source files, without changing the original sources. This can be achieved through the project extension facility.

 
   project Modified_Utilities extends "/baseline/utilities.gpr" is ...

A project extension declaration introduces an extending project (the child) and a project being extended (the parent).

By default, a child project inherits all the sources of its parent. However, inherited sources can be overridden: a unit in a parent is hidden by a unit of the same name in the child.

Inherited sources are considered to be sources (but not immediate sources) of the child project; see 11.3 Project File Syntax.

An inherited source file retains any switches specified in the parent project.

For example if the project Utilities contains the specification and the body of an Ada package Util_IO, then the project Modified_Utilities can contain a new body for package Util_IO. The original body of Util_IO will not be considered in program builds. However, the package specification will still be found in the project Utilities.

A child project can have only one parent but it may import any number of other projects.

A project is not allowed to import directly or indirectly at the same time a child project and any of its ancestors.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.7 Project Hierarchy Extension

When extending a large system spanning multiple projects, it is often inconvenient to extend every project in the hierarchy that is impacted by a small change introduced. In such cases, it is possible to create a virtual extension of entire hierarchy using extends all relationship.

When the project is extended using extends all inheritance, all projects that are imported by it, both directly and indirectly, are considered virtually extended. That is, the Project Manager creates "virtual projects" that extend every project in the hierarchy; all these virtual projects have no sources of their own and have as object directory the object directory of the root of "extending all" project.

It is possible to explicitly extend one or more projects in the hierarchy in order to modify the sources. These extending projects must be imported by the "extending all" project, which will replace the corresponding virtual projects with the explicit ones.

When building such a project hierarchy extension, the Project Manager will ensure that both modified sources and sources in virtual extending projects that depend on them, are recompiled.

By means of example, consider the following hierarchy of projects.

  1. project A, containing package P1
  2. project B importing A and containing package P2 which depends on P1
  3. project C importing B and containing package P3 which depends on P2

We want to modify packages P1 and P3.

This project hierarchy will need to be extended as follows:

  1. Create project A1 that extends A, placing modified P1 there:

     
    project A1 extends "(...)/A" is
    end A1;
    

  2. Create project C1 that "extends all" C and imports A1, placing modified P3 there:

     
    with "(...)/A1";
    project C1 extends all "(...)/C" is
    end C1;
    

When you build project C1, your entire modified project space will be recompiled, including the virtual project B1 that has been impacted by the "extending all" inheritance of project C.

Note that if a Library Project in the hierarchy is virtually extended, the virtual project that extends the Library Project is not a Library Project.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.8 External References in Project Files

A project file may contain references to external variables; such references are called external references.

An external variable is either defined as part of the environment (an environment variable in Unix, for example) or else specified on the command line via the `-Xvbl=value' switch. If both, then the command line value is used.

The value of an external reference is obtained by means of the built-in function external, which returns a string value. This function has two forms:

Each parameter must be a string literal. For example:

 
   external ("USER")
   external ("OS", "GNU/Linux")

In the form with one parameter, the function returns the value of the external variable given as parameter. If this name is not present in the environment, the function returns an empty string.

In the form with two string parameters, the second argument is the value returned when the variable given as the first argument is not present in the environment. In the example above, if "OS" is not the name of an environment variable and is not passed on the command line, then the returned value is "GNU/Linux".

An external reference may be part of a string expression or of a string list expression, and can therefore appear in a variable declaration or an attribute declaration.

 
   type Mode_Type is ("Debug", "Release");
   Mode : Mode_Type := external ("MODE");
   case Mode is
     when "Debug" =>
        ...


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.9 Packages in Project Files

A package defines the settings for project-aware tools within a project. For each such tool one can declare a package; the names for these packages are preset (see section 11.3.2 Packages). A package may contain variable declarations, attribute declarations, and case constructions.

 
   project Proj is
      package Builder is  -- used by gnatmake
         for Default_Switches ("Ada")
             use ("-v",
                  "-g");
      end Builder;
   end Proj;

The syntax of package declarations mimics that of package in Ada.

Most of the packages have an attribute Default_Switches. This attribute is an associative array, and its value is a string list. The index of the associative array is the name of a programming language (case insensitive). This attribute indicates the switch or switches to be used with the corresponding tool.

Some packages also have another attribute, Switches, an associative array whose value is a string list. The index is the name of a source file. This attribute indicates the switch or switches to be used by the corresponding tool when dealing with this specific file.

Further information on these switch-related attributes is found in 11.15.1.1 Switches and Project Files.

A package may be declared as a renaming of another package; e.g., from the project file for an imported project.

 
  with "/global/apex.gpr";
  project Example is
    package Naming renames Apex.Naming;
    ...
  end Example;

Packages that are renamed in other project files often come from project files that have no sources: they are just used as templates. Any modification in the template will be reflected automatically in all the project files that rename a package from the template.

In addition to the tool-oriented packages, you can also declare a package named Naming to establish specialized source file naming conventions (see section 11.11 Naming Schemes).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.10 Variables from Imported Projects

An attribute or variable defined in an imported or parent project can be used in expressions in the importing / extending project. Such an attribute or variable is denoted by an expanded name whose prefix is either the name of the project or the expanded name of a package within a project.

 
  with "imported";
  project Main extends "base" is
     Var1 := Imported.Var;
     Var2 := Base.Var & ".new";

     package Builder is
        for Default_Switches ("Ada")
            use Imported.Builder.Ada_Switches &
                "-gnatg" &
                "-v";
     end Builder;

     package Compiler is
        for Default_Switches ("Ada")
            use Base.Compiler.Ada_Switches;
     end Compiler;
  end Main;

In this example:


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.11 Naming Schemes

Sometimes an Ada software system is ported from a foreign compilation environment to GNAT, and the file names do not use the default GNAT conventions. Instead of changing all the file names (which for a variety of reasons might not be possible), you can define the relevant file naming scheme in the Naming package in your project file.

Note that the use of pragmas described in 2.5 Alternative File Naming Schemes by mean of a configuration pragmas file is not supported when using project files. You must use the features described in this paragraph. You can however use specify other configuration pragmas (see section 11.15.1.2 Specifying Configuration Pragmas).

For example, the following package models the Apex file naming rules:

 
  package Naming is
    for Casing               use "lowercase";
    for Dot_Replacement      use ".";
    for Spec_Suffix ("Ada")  use ".1.ada";
    for Body_Suffix ("Ada")  use ".2.ada";
  end Naming;

You can define the following attributes in package Naming:

Casing
This must be a string with one of the three values "lowercase", "uppercase" or "mixedcase"; these strings are case insensitive.

If Casing is not specified, then the default is "lowercase".

Dot_Replacement
This must be a string whose value satisfies the following conditions:

If Dot_Replacement is not specified, then the default is "-".

Spec_Suffix
This is an associative array (indexed by the programming language name, case insensitive) whose value is a string that must satisfy the following conditions:

If Spec_Suffix ("Ada") is not specified, then the default is ".ads".

Body_Suffix
This is an associative array (indexed by the programming language name, case insensitive) whose value is a string that must satisfy the following conditions:

If Body_Suffix ("Ada") is not specified, then the default is ".adb".

Separate_Suffix
This must be a string whose value satisfies the same conditions as Body_Suffix.

If Separate_Suffix ("Ada") is not specified, then it defaults to same value as Body_Suffix ("Ada").

Spec
You can use the associative array attribute Spec to define the source file name for an individual Ada compilation unit's spec. The array index must be a string literal that identifies the Ada unit (case insensitive). The value of this attribute must be a string that identifies the file that contains this unit's spec (case sensitive or insensitive depending on the operating system).

 
   for Spec ("MyPack.MyChild") use "mypack.mychild.spec";

Body

You can use the associative array attribute Body to define the source file name for an individual Ada compilation unit's body (possibly a subunit). The array index must be a string literal that identifies the Ada unit (case insensitive). The value of this attribute must be a string that identifies the file that contains this unit's body or subunit (case sensitive or insensitive depending on the operating system).

 
   for Body ("MyPack.MyChild") use "mypack.mychild.body";


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.12 Library Projects

Library projects are projects whose object code is placed in a library. (Note that this facility is not yet supported on all platforms)

To create a library project, you need to define in its project file two project-level attributes: Library_Name and Library_Dir. Additionally, you may define the library-related attributes Library_Kind, Library_Version, Library_Interface, Library_Auto_Init, Library_Options and Library_GCC.

The Library_Name attribute has a string value. There is no restriction on the name of a library. It is the responsability of the developer to choose a name that will be accepted by the platform. It is recommanded to choose names that could be Ada identifiers; such names are almost guaranteed to be acceptable on all platforms.

The Library_Dir attribute has a string value that designates the path (absolute or relative) of the directory where the library will reside. It must designate an existing directory, and this directory must be different from the project's object directory. It also needs to be writable. The directory should only be used for one library; the reason is that all files contained in this directory may be deleted by the Project Manager.

If both Library_Name and Library_Dir are specified and are legal, then the project file defines a library project. The optional library-related attributes are checked only for such project files.

The Library_Kind attribute has a string value that must be one of the following (case insensitive): "static", "dynamic" or "relocatable" (which is a synonym for "dynamic"). If this attribute is not specified, the library is a static library, that is an archive of object files that can be potentially linked into an static executable. Otherwise, the library may be dynamic or relocatable, that is a library that is loaded only at the start of execution.

If you need to build both a static and a dynamic library, you should use two different object directories, since in some cases some extra code needs to be generated for the latter. For such cases, it is recommended to either use two different project files, or a single one which uses external variables to indicate what kind of library should be build.

The Library_Version attribute has a string value whose interpretation is platform dependent. It has no effect on VMS and Windows. On Unix, it is used only for dynamic/relocatable libraries as the internal name of the library (the "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.

Example (on Unix):

 
project Plib is

   Version := "1";

   for Library_Dir use "lib_dir";
   for Library_Name use "dummy";
   for Library_Kind use "relocatable";
   for Library_Version use "libdummy.so." & Version;

end Plib;

Directory `lib_dir' will contain the internal library file whose name will be `libdummy.so.1', and `libdummy.so' will be a symbolic link to `libdummy.so.1'.

When gnatmake detects that a project file is a library project file, it will check all immediate sources of the project and rebuild the library if any of the sources have been recompiled.

Standard project files can import library project files. In such cases, the libraries will only be rebuild if some of its sources are recompiled because they are in the closure of some other source in an importing project. Sources of the library project files that are not in such a closure will not be checked, unless the full library is checked, because one of its sources needs to be recompiled.

For instance, assume the project file A imports the library project file L. The immediate sources of A are `a1.adb', `a2.ads' and `a2.adb'. The immediate sources of L are `l1.ads', `l1.adb', `l2.ads', `l2.adb'.

If `l1.adb' has been modified, then the library associated with L will be rebuild when compiling all the immediate sources of A only if `a1.ads', `a2.ads' or `a2.adb' includes a statement "with L1;".

To be sure that all the sources in the library associated with L are up to date, and that all the sources of parject A are also up to date, the following two commands needs to be used:

 
gnatmake -Pl.gpr
gnatmake -Pa.gpr

When a library is built or rebuilt, an attempt is made first to delete all files in the library directory. 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.

It is also possible to create library project files for third-party libraries that are precompiled and cannot be compiled locally thanks to the externally_built attribute. (See 19.2.2 Installing a library).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.13 Stand-alone Library Projects

A Stand-alone Library is a library that contains the necessary code to elaborate the Ada units that are included in the library. A Stand-alone Library is suitable to be used in an executable when the main is not in Ada. However, Stand-alone Libraries may also be used with an Ada main subprogram.

A Stand-alone Library Project is a Library Project where the library is a Stand-alone Library.

To be a Stand-alone Library Project, in addition to the two attributes that make a project a Library Project (Library_Name and Library_Dir, see 11.12 Library Projects), the attribute Library_Interface must be defined.

 
   for Library_Dir use "lib_dir";
   for Library_Name use "dummy";
   for Library_Interface use ("int1", "int1.child");

Attribute Library_Interface has a non empty string list value, each string in the list designating a unit contained in an immediate source of the project file.

When a Stand-alone Library is built, first the binder is invoked to build a package whose name depends on the library name (b~dummy.ads/b in the example above). This binder-generated package includes initialization and finalization procedures whose names depend on the library name (dummyinit and dummyfinal in the example above). The object corresponding to this package is included in the library.

A dynamic or relocatable Stand-alone Library is automatically initialized if automatic initialization of Stand-alone Libraries is supported on the platform and if attribute Library_Auto_Init is not specified or is specified with the value "true". A static Stand-alone Library is never automatically initialized.

Single string attribute Library_Auto_Init may be specified with only two possible values: "false" or "true" (case-insensitive). Specifying "false" for attribute Library_Auto_Init will prevent automatic initialization of dynamic or relocatable libraries.

When a non automatically initialized Stand-alone Library is used in an executable, its initialization procedure must be called before any service of the library is used. When the main subprogram is in Ada, it may mean that the initialization procedure has to be called during elaboration of another package.

For a Stand-Alone Library, only the `ALI' files of the Interface Units (those that are listed in attribute Library_Interface) are copied to the Library Directory. As a consequence, only the Interface Units may be imported from Ada units outside of the library. If other units are imported, the binding phase will fail.

When a Stand-Alone Library is bound, the switches that are specified in the attribute Default_Switches ("Ada") in package Binder are used in the call to gnatbind.

The string list attribute Library_Options may be used to specified additional switches to the call to gcc to link the library.

The attribute Library_Src_Dir, may be specified for a Stand-Alone Library. Library_Src_Dir is a simple attribute that has a single string value. Its value must be the path (absolute or relative to the project directory) of an existing directory. This directory cannot be the object directory or one of the source directories, but it can be the same as the library directory. The sources of the Interface Units of the library, necessary to an Ada client of the library, will be copied to the designated directory, called Interface Copy directory. These sources includes the specs of the Interface Units, but they may also include bodies and subunits, when pragmas Inline or Inline_Always are used, or when there is a generic units in the spec. Before the sources are copied to the Interface Copy directory, an attempt is made to delete all files in the Interface Copy directory.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.14 Switches Related to Project Files

The following switches are used by GNAT tools that support project files:

`-Pproject'
Indicates the name of a project file. This project file will be parsed with the verbosity indicated by `-vPx', if any, and using the external references indicated by `-X' switches, if any. There may zero, one or more spaces between `-P' and project.

There must be only one `-P' switch on the command line.

Since the Project Manager parses the project file only after all the switches on the command line are checked, the order of the switches `-P', `-vPx' or `-X' is not significant.

`-Xname=value'
Indicates that external variable name has the value value. The Project Manager will use this value for occurrences of external(name) when parsing the project file.

If name or value includes a space, then name=value should be put between quotes.
 
  -XOS=NT
  -X"user=John Doe"

Several `-X' switches can be used simultaneously. If several `-X' switches specify the same name, only the last one is used.

An external variable specified with a `-X' switch takes precedence over the value of the same name in the environment.

`-vPx'
Indicates the verbosity of the parsing of GNAT project files.

`-vP0' means Default; `-vP1' means Medium; `-vP2' means High.

The default is Default: no output for syntactically correct project files. If several `-vPx' switches are present, only the last one is used.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.15 Tools Supporting Project Files

11.15.1 gnatmake and Project Files  
11.15.2 The GNAT Driver and Project Files  
11.15.3 Glide and Project Files  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.15.1 gnatmake and Project Files

This section covers several topics related to gnatmake and project files: defining switches for gnatmake and for the tools that it invokes; specifying configuration pragmas; the use of the Main attribute; building and rebuilding library project files.

11.15.1.1 Switches and Project Files  
11.15.1.2 Specifying Configuration Pragmas  
11.15.1.3 Project Files and Main Subprograms  
11.15.1.4 Library Project Files  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.15.1.1 Switches and Project Files

For each of the packages Builder, Compiler, Binder, and Linker, you can specify a Default_Switches attribute, a Switches attribute, or both; as their names imply, these switch-related attributes affect the switches that are used for each of these GNAT components when gnatmake is invoked. As will be explained below, these component-specific switches precede the switches provided on the gnatmake command line.

The Default_Switches attribute is an associative array indexed by language name (case insensitive) whose value is a string list. For example:

 
package Compiler is
  for Default_Switches ("Ada")
      use ("-gnaty",
           "-v");
end Compiler;

The Switches attribute is also an associative array, indexed by a file name (which may or may not be case sensitive, depending on the operating system) whose value is a string list. For example:

 
package Builder is
   for Switches ("main1.adb")
       use ("-O2");
   for Switches ("main2.adb")
       use ("-g");
end Builder;

For the Builder package, the file names must designate source files for main subprograms. For the Binder and Linker packages, the file names must designate `ALI' or source files for main subprograms. In each case just the file name without an explicit extension is acceptable.

For each tool used in a program build (gnatmake, the compiler, the binder, and the linker), the corresponding package contributes a set of switches for each file on which the tool is invoked, based on the switch-related attributes defined in the package. In particular, the switches that each of these packages contributes for a given file f comprise:

If neither of these attributes is defined in the package, then the package does not contribute any switches for the given file.

When gnatmake is invoked on a file, the switches comprise two sets, in the following order: those contributed for the file by the Builder package; and the switches passed on the command line.

When gnatmake invokes a tool (compiler, binder, linker) on a file, the switches passed to the tool comprise three sets, in the following order:

  1. the applicable switches contributed for the file by the Builder package in the project file supplied on the command line;

  2. those contributed for the file by the package (in the relevant project file -- see below) corresponding to the tool; and

  3. the applicable switches passed on the command line.

The term applicable switches reflects the fact that gnatmake switches may or may not be passed to individual tools, depending on the individual switch.

gnatmake may invoke the compiler on source files from different projects. The Project Manager will use the appropriate project file to determine the Compiler package for each source file being compiled. Likewise for the Binder and Linker packages.

As an example, consider the following package in a project file:

 
project Proj1 is
   package Compiler is
      for Default_Switches ("Ada")
          use ("-g");
      for Switches ("a.adb")
          use ("-O1");
      for Switches ("b.adb")
          use ("-O2",
               "-gnaty");
   end Compiler;
end Proj1;

If gnatmake is invoked with this project file, and it needs to compile, say, the files `a.adb', `b.adb', and `c.adb', then `a.adb' will be compiled with the switch `-O1', `b.adb' with switches `-O2' and `-gnaty', and `c.adb' with `-g'.

The following example illustrates the ordering of the switches contributed by different packages:

 
project Proj2 is
   package Builder is
      for Switches ("main.adb")
          use ("-g",
               "-O1",
               "-f");
   end Builder;

   package Compiler is
      for Switches ("main.adb")
          use ("-O2");
   end Compiler;
end Proj2;

If you issue the command:

 
    gnatmake -Pproj2 -O0 main

then the compiler will be invoked on `main.adb' with the following sequence of switches

 
   -g -O1 -O2 -O0

with the last `-O' switch having precedence over the earlier ones; several other switches (such as `-c') are added implicitly.

The switches `-g' and `-O1' are contributed by package Builder, `-O2' is contributed by the package Compiler and `-O0' comes from the command line.

The `-g' switch will also be passed in the invocation of Gnatlink.

A final example illustrates switch contributions from packages in different project files:

 
project Proj3 is
   for Source_Files use ("pack.ads", "pack.adb");
   package Compiler is
      for Default_Switches ("Ada")
          use ("-gnata");
   end Compiler;
end Proj3;

with "Proj3";
project Proj4 is
   for Source_Files use ("foo_main.adb", "bar_main.adb");
   package Builder is
      for Switches ("foo_main.adb")
          use ("-s",
               "-g");
   end Builder;
end Proj4;

-- Ada source file:
with Pack;
procedure Foo_Main is
   ...
end Foo_Main;

If the command is
 
gnatmake -PProj4 foo_main.adb -cargs -gnato

then the switches passed to the compiler for `foo_main.adb' are `-g' (contributed by the package Proj4.Builder) and `-gnato' (passed on the command line). When the imported package Pack is compiled, the switches used are `-g' from Proj4.Builder, `-gnata' (contributed from package Proj3.Compiler, and `-gnato' from the command line.

When using gnatmake with project files, some switches or arguments may be expressed as relative paths. As the working directory where compilation occurs may change, these relative paths are converted to absolute paths. For the switches found in a project file, the relative paths are relative to the project file directory, for the switches on the command line, they are relative to the directory where gnatmake is invoked. The switches for which this occurs are: -I, -A, -L, -aO, -aL, -aI, as well as all arguments that are not switches (arguments to switch -o, object files specified in package Linker or after -largs on the command line). The exception to this rule is the switch --RTS= for which a relative path argument is never converted.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.15.1.2 Specifying Configuration Pragmas

When using gnatmake with project files, if there exists a file `gnat.adc' that contains configuration pragmas, this file will be ignored.

Configuration pragmas can be defined by means of the following attributes in project files: Global_Configuration_Pragmas in package Builder and Local_Configuration_Pragmas in package Compiler.

Both these attributes are single string attributes. Their values is the path name of a file containing configuration pragmas. If a path name is relative, then it is relative to the project directory of the project file where the attribute is defined.

When compiling a source, the configuration pragmas used are, in order, those listed in the file designated by attribute Global_Configuration_Pragmas in package Builder of the main project file, if it is specified, and those listed in the file designated by attribute Local_Configuration_Pragmas in package Compiler of the project file of the source, if it exists.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.15.1.3 Project Files and Main Subprograms

When using a project file, you can invoke gnatmake with one or several main subprograms, by specifying their source files on the command line.

 
    gnatmake -Pprj main1 main2 main3

Each of these needs to be a source file of the same project, except when the switch -u is used.

When -u is not used, all the mains need to be sources of the same project, one of the project in the tree rooted at the project specified on the command line. The package Builder of this common project, the "main project" is the one that is considered by gnatmake.

When -u is used, the specified source files may be in projects imported directly or indirectly by the project specified on the command line. Note that if such a source file is not part of the project specified on the command line, the switches found in package Builder of the project specified on the command line, if any, that are transmitted to the compiler will still be used, not those found in the project file of the source file.

When using a project file, you can also invoke gnatmake without explicitly specifying any main, and the effect depends on whether you have defined the Main attribute. This attribute has a string list value, where each element in the list is the name of a source file (the file extension is optional) that contains a unit that can be a main subprogram.

If the Main attribute is defined in a project file as a non-empty string list and the switch `-u' is not used on the command line, then invoking gnatmake with this project file but without any main on the command line is equivalent to invoking gnatmake with all the file names in the Main attribute on the command line.

Example:
 
   project Prj is
      for Main use ("main1", "main2", "main3");
   end Prj;

With this project file, "gnatmake -Pprj" is equivalent to "gnatmake -Pprj main1 main2 main3".

When the project attribute Main is not specified, or is specified as an empty string list, or when the switch `-u' is used on the command line, then invoking gnatmake with no main on the command line will result in all immediate sources of the project file being checked, and potentially recompiled. Depending on the presence of the switch `-u', sources from other project files on which the immediate sources of the main project file depend are also checked and potentially recompiled. In other words, the `-u' switch is applied to all of the immediate sources of the main project file.

When no main is specified on the command line and attribute Main exists and includes several mains, or when several mains are specified on the command line, the default switches in package Builder will be used for all mains, even if there are specific switches specified for one or several mains.

But the switches from package Binder or Linker will be the specific switches for each main, if they are specified.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.15.1.4 Library Project Files

When gnatmake is invoked with a main project file that is a library project file, it is not allowed to specify one or more mains on the command line.

When a library project file is specified, switches -b and -l have special meanings.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.15.2 The GNAT Driver and Project Files

A number of GNAT tools, other than gnatmake are project-aware: gnatbind, gnatfind, gnatlink, gnatls, gnatelim, gnatpp, gnatmetric, gnatstub, and gnatxref. However, none of these tools can be invoked directly with a project file switch (`-P'). They must be invoked through the gnat driver.

The gnat driver is a front-end that accepts a number of commands and call the corresponding tool. It has been designed initially for VMS to convert VMS style qualifiers to Unix style switches, but it is now available to all the GNAT supported platforms.

On non VMS platforms, the gnat driver accepts the following commands (case insensitive):

(note that the compiler is invoked using the command gnatmake -f -u -c).

On non VMS platforms, between gnat and the command, two special switches may be used:

The command may be followed by switches and arguments for the invoked tool.

 
  gnat bind -C main.ali
  gnat ls -a main
  gnat chop foo.txt

Switches may also be put in text files, one switch per line, and the text files may be specified with their path name preceded by '@'.

 
   gnat bind @args.txt main.ali

In addition, for commands BIND, COMP or COMPILE, FIND, ELIM, LS or LIST, LINK, METRIC, PP or PRETTY, STUB and XREF, the project file related switches (`-P', `-X' and `-vPx') may be used in addition to the switches of the invoking tool.

When GNAT PP or GNAT PRETTY is used with a project file, but with no source specified on the command line, it invokes gnatpp with all the immediate sources of the specified project file.

When GNAT METRIC is used with a project file, but with no source specified on the command line, it invokes gnatmetric with all the immediate sources of the specified project file and with `-d' with the parameter pointing to the object directory of the project.

In addition, when GNAT PP, GNAT PRETTY or GNAT METRIC is used with a project file, no source is specified on the command line and switch -U is specified on the command line, then the underlying tool (gnatpp or gnatmetric) is invoked for all sources of all projects, not only for the immediate sources of the main project. (-U stands for Universal or Union of the project files of the project tree)

For each of the following commands, there is optionally a corresponding package in the main project.

Package Gnatls has a unique attribute Switches, a simple variable with a string list value. It contains switches for the invocation of gnatls.

 
project Proj1 is
   package gnatls is
      for Switches
          use ("-a",
               "-v");
   end gnatls;
end Proj1;

All other packages have two attribute Switches and Default_Switches.

Switches is an associated array attribute, indexed by the source file name, that has a string list value: the switches to be used when the tool corresponding to the package is invoked for the specific source file.

Default_Switches is an associative array attribute, indexed by the programming language that has a string list value. Default_Switches ("Ada") contains the switches for the invocation of the tool corresponding to the package, except if a specific Switches attribute is specified for the source file.

 
project Proj is

   for Source_Dirs use ("./**");

   package gnatls is
      for Switches use
          ("-a",
           "-v");
   end gnatls;

   package Compiler is
      for Default_Switches ("Ada")
          use ("-gnatv",
               "-gnatwa");
   end Binder;

   package Binder is
      for Default_Switches ("Ada")
          use ("-C",
               "-e");
   end Binder;

   package Linker is
      for Default_Switches ("Ada")
          use ("-C");
      for Switches ("main.adb")
          use ("-C",
               "-v",
               "-v");
   end Linker;

   package Finder is
      for Default_Switches ("Ada")
           use ("-a",
                "-f");
   end Finder;

   package Cross_Reference is
      for Default_Switches ("Ada")
          use ("-a",
               "-f",
               "-d",
               "-u");
   end Cross_Reference;
end Proj;

With the above project file, commands such as

 
   gnat comp -Pproj main
   gnat ls -Pproj main
   gnat xref -Pproj main
   gnat bind -Pproj main.ali
   gnat link -Pproj main.ali

will set up the environment properly and invoke the tool with the switches found in the package corresponding to the tool: Default_Switches ("Ada") for all tools, except Switches ("main.adb") for gnatlink.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.15.3 Glide and Project Files

Glide will automatically recognize the `.gpr' extension for project files, and will convert them to its own internal format automatically. However, it doesn't provide a syntax-oriented editor for modifying these files. The project file will be loaded as text when you select the menu item Ada => Project => Edit. You can edit this text and save the `gpr' file; when you next select this project file in Glide it will be automatically reloaded.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.16 An Extended Example

Suppose that we have two programs, prog1 and prog2, whose sources are in corresponding directories. We would like to build them with a single gnatmake command, and we want to place their object files into `build' subdirectories of the source directories. Furthermore, we want to have to have two separate subdirectories in `build' -- `release' and `debug' -- which will contain the object files compiled with different set of compilation flags.

In other words, we have the following structure:

 
   main
     |- prog1
     |    |- build
     |         | debug
     |         | release
     |- prog2
          |- build
               | debug
               | release

Here are the project files that we must place in a directory `main' to maintain this structure:

  1. We create a Common project with a package Compiler that specifies the compilation switches:

     
    File "common.gpr":
    project Common is
    
       for Source_Dirs use (); -- No source files
    
       type Build_Type is ("release", "debug");
       Build : Build_Type := External ("BUILD", "debug");
       package Compiler is
          case Build is
             when "release" =>
               for Default_Switches ("Ada")
                       use ("-O2");
             when "debug"   =>
               for Default_Switches ("Ada")
                       use ("-g");
          end case;
       end Compiler;
    
    end Common;
    

  2. We create separate projects for the two programs:

     
    File "prog1.gpr":
    
    with "common";
    project Prog1 is
    
        for Source_Dirs use ("prog1");
        for Object_Dir  use "prog1/build/" & Common.Build;
    
        package Compiler renames Common.Compiler;
    
    end Prog1;
    

     
    File "prog2.gpr":
    
    with "common";
    project Prog2 is
    
        for Source_Dirs use ("prog2");
        for Object_Dir  use "prog2/build/" & Common.Build;
    
        package Compiler renames Common.Compiler;
    
    end Prog2;
    

  3. We create a wrapping project Main:

     
    File "main.gpr":
    
    with "common";
    with "prog1";
    with "prog2";
    project Main is
    
       package Compiler renames Common.Compiler;
    
    end Main;
    

  4. Finally we need to create a dummy procedure that withs (either explicitly or implicitly) all the sources of our two programs.

Now we can build the programs using the command

 
   gnatmake -Pmain dummy

for the Debug mode, or

 
   gnatmake -Pmain -XBUILD=release

for the Release mode.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.17 Project File Complete Syntax

 
project ::=
  context_clause project_declaration

context_clause ::=
  {with_clause}

with_clause ::=
  with path_name { , path_name } ;

path_name ::=
   string_literal

project_declaration ::=
  simple_project_declaration | project_extension

simple_project_declaration ::=
  project <project_>simple_name is
    {declarative_item}
  end <project_>simple_name;

project_extension ::=
  project <project_>simple_name  extends path_name is
    {declarative_item}
  end <project_>simple_name;

declarative_item ::=
  package_declaration |
  typed_string_declaration |
  other_declarative_item

package_declaration ::=
  package_specification | package_renaming

package_specification ::=
  package package_identifier is
    {simple_declarative_item}
  end package_identifier ;

package_identifier ::=
  Naming | Builder | Compiler | Binder |
  Linker | Finder  | Cross_Reference |
  gnatls | IDE     | Pretty_Printer

package_renaming ::==
  package package_identifier renames
       <project_>simple_name.package_identifier ;

typed_string_declaration ::=
  type <typed_string_>_simple_name is
   ( string_literal {, string_literal} );

other_declarative_item ::=
  attribute_declaration |
  typed_variable_declaration |
  variable_declaration |
  case_construction

attribute_declaration ::=
  full_associative_array_declaration |
  for attribute_designator use expression ;

full_associative_array_declaration ::=
  for <associative_array_attribute_>simple_name use
  <project_>simple_name [ . <package_>simple_Name ] ' <attribute_>simple_name ;

attribute_designator ::=
  <simple_attribute_>simple_name |
  <associative_array_attribute_>simple_name ( string_literal )

typed_variable_declaration ::=
  <typed_variable_>simple_name : <typed_string_>name :=  string_expression ;

variable_declaration ::=
  <variable_>simple_name := expression;

expression ::=
  term {& term}

term ::=
  literal_string |
  string_list |
  <variable_>name |
  external_value |
  attribute_reference

string_literal ::=
  (same as Ada)

string_list ::=
  ( <string_>expression { , <string_>expression } )

external_value ::=
  external ( string_literal [, string_literal] )

attribute_reference ::=
  attribute_prefix ' <simple_attribute_>simple_name [ ( literal_string ) ]

attribute_prefix ::=
  project |
  <project_>simple_name | package_identifier |
  <project_>simple_name . package_identifier

case_construction ::=
  case <typed_variable_>name is
    {case_item}
  end case ;

case_item ::=
  when discrete_choice_list =>
      {case_construction | attribute_declaration}

discrete_choice_list ::=
  string_literal {| string_literal} |
  others

name ::=
  simple_name {. simple_name}

simple_name ::=
  identifier (same as Ada)


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Mail Server on June, 15 2005 using texi2html