GNAT User's Guide

GNAT, The GNU Ada 95 Compiler

Version 3.07 (DRAFT)

Novemeber 6, 1996

Ada Core Technologies, Inc.

Table of Contents

(C) Copyright 1995-1996, Ada Core Technologies, Inc.

GNAT is free software; you can redistribute it and/or modify it under terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNAT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNAT; see file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

About This Guide

This guide describes the language itself, as well as the various utilities that allow you to manipulate GNAT code.

What This Guide Contains

This guide contains the following chapters:

What You Should Know Before Reading This Guide

This user's guide assumes that you are familiar with Ada 95 language, as described in the International Standard ANSI/ISO/IEC-8652:1995, Jan 1995.

Related Information

For further information about related tools, refer to the following documents:


Following are examples of the typographical and graphic conventions used in this guide:

Getting Started With GNAT

This chapter describes the usual ways of using GNAT to compile Ada programs.

Running GNAT

Three steps are needed to create an executable file from an Ada source file:

  1. The source file must first be compiled.
  2. The source file then must be bound using the GNAT binder.
  3. All appropriate object files must be linked to produce an executable.

Running a Simple Ada Program

Any editor may be used to prepare an Ada program. If emacs is used, the optional Ada mode may be helpful in laying out the program. The program text is a normal text file. We will suppose in our initial example that you have used your editor to prepare the following file:

with Text_IO; use Text_IO; 
procedure Hello is
   Put_Line ("Hello WORLD!"); 
end Hello;

This file should be named `hello.adb'. GNAT requires each file contain a single unit whose file name corresponds to the unit name with periods replaced by hyphens and whose extension is `.ads' for a spec and `.adb' for a body.

You can compiler the program using one of the following commands:

gcc -c hello.adb
gnatmake -c hello
gnatmake -c hello.adb

gcc is the command used to access the compiler. This compiler is capable of compiling programs in several languages including Ada 95 and C. It determines you have given it an Ada program by the extension (`.ads' or `.adb'), and will call the GNAT compiler to compile the specified file.

The `-c' switch is required. It tells gcc to do a compilation. (For C programs, gcc can also do linking, but this capability is not used directly for Ada programs, so the `-c' switch must always be present.)

This compile command generates a file `hello.o' which is the object file corresponding to your Ada program. It also generates a file `hello.ali' which contains additional information used to check that an Ada program is consistent. To get an executable file, either use gnatmake or use gnatbind followed by gnatlink.

gnatmake is a master program which invokes all of the required gcc tools in the correct order and compiles all necessary Ada units when requested to do so.

gnatmake hello


gnatbind -x hello.ali
gnatlink -o hello hello.ali

The result is an executable program called `hello', which can be run using the normal UNIX command


and, if all has gone well, you will see

Hello WORLD!

appear in response to this command.

Running a Program With Multiple Units

Consider a slightly more complicated example that has three files, a main program, and the spec and body of a package:

package Greetings is 
   procedure Hello; 
   procedure Goodbye; 
end Greetings;

with Text_IO; use Text_IO; 
package body Greetings is 
   procedure Hello is 
      Put_Line ("Hello WORLD!"); 
   end Hello; 
   procedure Goodbye is 
      Put_Line ("Goodbye WORLD!"); 
   end Goodbye; 
end Greetings; 

with Greetings; 
procedure Gmain is 
end Gmain;

Following the one-unit-per-file rule, prepare this program in the following three separate files:

spec of package Greetings
body of package Greetings
body of main program

Compile the program in steps: one for the package, and one for the main program. Unlike the case in some other Ada compilers, there is no required order of compilation and, in particular, it is fine to compile the main program first:

gcc -c gmain.adb 
gcc -c greetings.adb

Notice you do not need to compile `'. GNAT does not require that you compile library specs or library generic packages. If you want, you can submit these units to the compiler to be checked for correctness, using the `-gnatc' switch:

gcc -gnatc -c

Once all the necessary units have been compiled, you bind and link them as previously, using gnatbind and gnatlink as follows:

gnatbind gmain.ali
gnatlink -o gmain gmain.ali

A better approach is to simply use gnatmake as described in the following section.

Using the gnatmake Utility

As you work on a program, you keep track of which units you modify and make sure you not only recompile these units, but also any units that depend on units you have modified. For example, in the preceeding case, if you edit `gmain.adb', you only need recompile that file. But if you edit `', you must recompile both `greetings.adb' and `gmain.adb', since both files contain units that depend on `'.

gnatbind will warn you if you forget one of these compilation steps, so it is never possible to generate an inconsistent program as a result of forgetting to do a compilation, but it can be annoying to keep track of the dependencies. One approach would be to use a `Makefile', but the trouble with make files is that the dependencies may change as you change the program, and you must make sure that the `Makefile' is kept up to date.

The gnatmake utility takes care of these details automatically. Invoke it as follows:

gnatmake gmain.adb

The argument is the file containing the main program. gnatmake examines the environment, automatically recompiles any files that need recompiling, and binds and links the resulting set of object files, generating the executable file, `gmain'.

The GNAT Compilation Model

This chapter describes the compilation model used by GNAT. Although similar to that used by other languages, such as C and C++, this model is substantially different from the traditional Ada compilation models, which are based on a library. The model is initially described without reference to this traditional model. If you have not previously used an Ada compiler, you need only read the first part of this chapter. The last section describes and discusses the differences between the GNAT model and the traditional Ada compiler models. If you have used other Ada compilers, you may find this section helps you to understand those differences.

Source Representation

Ada source programs are represented in standard text files, using Latin-1 coding. Latin-1 is ASCII with the additional characters used for representing foreign languages (see section Foreign Language Representation for support of non-USA character sets). The format effector characters are represented using their standard ASCII encodings, as follows:

Vertical tab, 16#0B#
Horizontal tab, 16#09#
Carriage return, 16#0D#
Line feed, 16#0A#
Form feed, 16#0C#

The end of physical lines is marked by any of the following sequences: LF, CR, CR-LF, or LF-CR. Standard UNIX files simply use LF to terminate physical lines. The other combinations are recognized to provide convenient processing for files imported from other operating systems. For example, files imported from MS-DOS on a PC are likely to have lines ended by CR-LF.

The end of a source file is normally represented by the physical end of file. However the control character 16#1A# (SUB) is also represented as signalling the end of the source file. Again, this is provided for compatibility with imported MS-DOS files where this control code is used to represent the end of file.

Each file contains a single Ada compilation unit, including any pragmas associated with the unit. For example, this means you must place a package declaration (a package spec) and the corresponding body in separate files. An Ada compilation (which is a sequence of compilation units) is represented using a sequence of files. Similarly, you will place each subunit or child unit in a separate file.

Foreign Language Representation

GNAT supports the standard character sets defined in Ada 95:


The basic character set is Latin-1. This character set is defined by ISO standard 8859, part 1. The lower half (character codes 16#00# ... 16#7F#) is identical to standard ASCII coding, but the upper half is used to represent additional characters. This includes extended letters used by European languages, such as the umlaut used in German.

For a complete list of Latin-1 codes and their encodings, see the source file of library unit Ada.Characters.Latin_1 in file `'.

You may use any of these extended characters freely in character or string literals. In addition, the extended characters that represent letters can be used in identifiers.

Other 8-Bit Codes

GNAT also supports several other 8-bit coding schemes:

Latin-2 letters allowed in identifiers, with uppercase and lowercase equivalence.
Latin-3 letters allowed in identifiers, with uppercase and lower case equivalence.
Latin-4 letters allowed in identifiers, with uppercase and lower case equivalence.
IBM PC (code page 437)
This code page is the normal default for PCs in the U.S. It corresponds to the original IBM PC character set. This set has some, but not all, of the extended Latin-1 letters, but these letters do not have the same encoding as Latin-1. In this mode, these letters are allowed in identifiers with uppercase and lowercase equivalence.
IBM PC (code page 850)
This code page is a modification of 437 extended to include all the Latin-1 letters, but still not with the usual Latin-1 encoding. In this mode, all these letters are allowed in identifiers with uppercase and lower case equivalence.
Full Upper 8-bit
Any character in the range 80-FF allowed in identifiers, and all are considered distinct. In other words, there are no uppercase and lower case equivalences in this range.
No Upper-Half
No upper-half characters in the range 80-FF are allowed in identifiers. This gives Ada 95 compatibility for identifier names. For precise data on the encodings permitted, and the uppercase and lower case equivalences that are recognized, see the file `csets.adb' in the GNAT compiler sources.
Wide Character Coding
GNAT allows wide character codes to appear in character and string literals, and also optionally in identifiers, using the following possible encoding schemes:
Hex Coding
In this encoding, a wide character is represented by the following five character sequence:
ESC a b c d
Where a, b, c, d are the four hexadecimal characters (using uppercase letters) of the wide character code. For example, ESC A345 is used to represent the wide character with code 16#A345#. This scheme is compatible with use of the full Wide_Character set.
Upper-Half Coding
The wide character with encoding 16#abcd# where the upper bit is on (in other words, "a" is in the range 8-F) is represented as two bytes, 16#ab# and 16#cd#. The second byte may never be a format control character, but is not required to be in the upper half. This method can be also used for shift-JIS or EUC, where the internal coding matches the external coding.
Shift JIS Coding
A wide character is represented by a two-character sequence, 16#ab# and 16#cd#, with the restrictions described for upper-half encoding as described above. The internal character code is the corresponding JIS character according to the standard algorithm for Shift-JIS conversion. Only characters defined in the JIS code set table can be used with this encoding method.
EUC Coding
A wide character is represented by a two-character sequence 16#ab# and 16#cd#, with both characters being in the upper half. The internal character code is the corresponding JIS character according to the EUC encoding algorithm. Only characters defined in the JIS code set table can be used with this encoding method.
Note: These coding schemes do not permit simultaneous use of the upper half of the Latin-1 character set.

File Naming Rules

The file name is determined by the name of the unit the file contains. The name is formed by taking the full expanded name of the unit and replacing the separating dots with hyphens and using lower case for all letters except that a hyphen in the second character position is replaced by a plus sign. The extension is `.ads' for a spec and `.adb' for a body as shown in the following table.

Main (spec)
Main (body)
Arith_Functions (package spec)
Arith_Functions (package body)
Func.Spec (child package spec)
Func.Spec (child package body)
Sub (subunit of Main)

Following these rules can result in very long file names if corresponding unit names are very long (for example, if child units or subunits are heavily nested). An option is available to shorten such long file names (called file name "krunching"). This may be particularly useful when programs being developed with GNAT are to be used on operating systems such as MS-DOS with limited file name lengths. See section Using gnatk8.

Of course, no file shortening algorithm can guarantee uniqueness over all possible unit names; if file name krunching is used it is your responsibility to ensure no name clashes occur.

Naming of GNAT Source Files

If you want to examine the workings of the GNAT system, the following brief description of its organization may be helpful:

Generating Object Files

An Ada program consists of a set of source files, and the first step in compiling the program is to generate the corresponding object files. These are generated by compiling a subset of these source files. The files you need to compile are the following:

The preceeding rules describe the set of files that must be compiled to generate the object files for a program. Each object file has the same name as the corresponding source file, except that the extension is `.o' as usual.

You may wish to compile other files for the purpose of checking syntactic and semantic correctness. For example, in the case where a package has a separate spec and body, you would not normally compile the spec. However, it is convenient in practice to compile the spec to make sure it is correct before compiling clients ofthis spec, since such compilations will fail if there is an error in the spec.

GNAT provides the option for compiling such files purely for the purposes of checking correctness; such compilations are not required as part of the process of building a program.

Source Dependencies

A given object file clearly depends on the source file which is compiled to produce it. Here we are using depends in the sense of the UNIX make utility; in other words, an object file depends on a source file if changes to the source file require the object file to be recompiled.

In addition to this basic dependency, a given object may depend on additional source files as follows:

The object file for a parent unit depends on the body files for all subunits of the parent unit.

These rules are applied transitively: if unit A with's unit B, whose elaboration calls an inlined procedure in package C, the object file for unit A will depend on the body of C, in file `c.adb'.

The set of dependent files described by these rules includes all the files on which the unit is semantically dependent, as described in the Ada 95 Language Reference Manual. However it is larger because of the inclusion of generic, inline, and subunit dependencies.

An object file must be recreated by recompiling the corresponding source file if any of the source files on which it depends are modified. For example, if the make utility is used to control compilation, the rule for an Ada object file must mention all the source files on which the object file depends.

The Ada Library Information Files

Each compilation actually generates two output files. The first of these is the normal object file with a `.o' extension. The second is a text file containing the dependency information file. It has the same name but with an `.ali' extension. This file is known as the Ada Library Information (ALI) file.

You normally need not be concerned with the contents of this file, but this section is included in case you want to understand how these files are being used. Each ALI file consists of a series of lines of the form:

Key_Character parameter parameter ...

The first two lines in the file identify the library output version and Standard version. These are required to be consistent across the entire set of compilation units in your program.

V "xxxxxxxxxxxxxxxx"

This line indicates the library output version, as defined in `'. It ensures that separate object modules of a program are consistent. It must be changed if anything changes that would affect successful binding of modules compiled separately.

Examples of such changes are modifications in the format of the library information described in this package, modifications to calling sequences, or to the way data is represented.

S "xxxxxxxxxxxxxxxx"

This line contains information regarding types declared in packages Standard as stored in Gnatvsn.Standard_Version.

The purpose (on systems where, for example, the size of Integer can be set by command line switches) is to ensure that all units in a program are compiled with a consistent set of options.

The following line is present only for a unit that can be a main program. It has the form:

M type [priority]

type is either P for a parameterless procedure or F for a function returning a value of integral type. The latter is for writing a main program that returns an exit status. priority is present only if there was a valid pragma Priority in the corresponding unit to set the main task priority. It is an unsigned decimal integer.

Following these header lines, a set of information lines appears for each compilation unit that appears in the corresponding object file. In particular, when a package body or subprogram body is compiled there will be two sets of information, one for the spec and one for the body, with the entry for the body appearing first. This is the only case in which a single ALI file contains more than one unit. Note that subunits do not count as compilation units for this purpose, and generate no library information, since they are inlined.

The lines for each compilation unit have the following form:

U unit-name source-name version [attributes]

This line identifies the unit to which this section of the library information file applies. unit-name is the unit name in internal format, as described in package Uname, and source-file is the name of the source file containing the unit.

version is the version given as eight hexadecimal characters with lower case letters. This value is a hash code that includes contributions from the time stamps of this unit and all its semantically dependent units.

The optional attributes are a series of two-letter codes indicating information about the unit:

Unit has pragma Elaborate_Body.
Unit has no elaboration routine. All subprogram specs are in this category, as are subprogram bodies if access before elaboration checks are being generated. Package bodies and specs may or may not have NE set, depending on whether or not elaboration code is required.
Unit is a package, rather than a subprogram.
Unit has pragma Pure.
Unit has pragma Preelaborate.
Unit has pragma Remote_Call_Interface.
Unit has pragma Remote_Types.
Unit has pragma Shared_Passive.
Unit is a subprogram, rather than a package.

The attributes may appear in any order, separated by spaces. Another line in the ALI file has the following form:

W unit-name [source-name lib-name [E] [EA]]

One of these lines is present for each unit mentioned in an explicit with clause by the current unit. unit-name is the unit name in internal format. source-name is the file name of the file that must be compiled to compile that unit (usually the file for the body, except for packages that have no body). lib-name is the file name of the library information file that contains the results of compiling the unit. The E and EA parameters are present if pragma Elaborate or pragma Elaborate_All, respectively, apply to this unit. In the case of generic units, only unit-name is present, since generic units do not need to be compiled, and generate no library information. Note that the elaborate pragmas can be given for generic units, but GNAT ignores them.

Following the unit information is an optional series of lines that indicate the usage of pragma Library_Unit. For each appearance of pragma Library_Unit in any of the units for which unit lines are present, a line of the form

L string

appears where string is the string from the pragma enclosed in quotes. Within the quotes, the following can occur:

For further details, see Stringt.Write_String_Table_Entry in the file `'. Note that wide characters in the form {hhhh} cannot be produced, since pragma Linker_Option accepts only String, not Wide_String.

Finally, at the end of the ALI file is a series of lines that indicate the source files on which the compiled units depend. This is used by the binder for consistency checking and look like:

D source-name time-stamp [comments]

comments, if present, must be separated from the time stamp by at least one blank. Currently this field is unused.

Blank lines are ignored when the library information is read, and separate sections of the file are separated by blank lines to ease readability. Extra blanks between fields are also ignored.

Representation of Time Stamps

All compiled units are marked with a time stamp, which is derived from The source file. The binder uses these time stamps to ensure consistency of the set of units that constitutes a single program. Time stamps are twelve-character strings of the form YYMMDDHHMMSS. Each two-character field has the following meaning:

year (2 low order digits)
month (2 digits 01-12)
day (2 digits 01-31)
hour (2 digits 00-23)
minutes (2 digits 00-59)
seconds (2 digits 00-59)

Time stamps may be compared lexicographically (in other words, the order of Ada comparison operations on strings) to determine which is later or earlier. However, in normal mode, only equality comparisons have any effect on the semantics of the library. Later/earlier comparisons are used only for determining the most informative error messages to be issued by the binder.

The time stamp is the actual stamp stored with the file without any adjustment resulting from time zone comparisons. This avoids problems in using libraries across networks with clients spread across multiple time zones, but may mean the time stamp will differ from that displayed in a directory listing. For example, in UNIX systems, file time stamps are stored in Greenwich Mean Time (GMT), but the ls command displays local times.

Binding an Ada Program

When using languages such as C and C++, the only remaining step in building an executable program once the source files have been compiled is linking the object modules together. This means it is possible to link an inconsistent version of a program in which two units have included different versions of the same header.

The rules in Ada do not permit such an inconsistent program to be built. For example, if two clients have different versions of the same package, it is not possible to build a program containing these two clients. These rules are enforced by the GNAT binder, which also determines an elaboration order consistent with the Ada rules.

The GNAT binder is run after all the object files for a program have been compiled. It is given the name of the main program unit, and from this it determines the set of units required by the program, reading the corresponding ALI files. It generates error messages if the program is inconsistent or if no valid order of elaboration exists.

If no errors are detected, the binder produces a main program, in C, that contains calls to the required elaboration procedures, followed by a call to the main program. This C program is compiled using the C compiler to generate the object file for the main program. The name of the C file is b_xxx.c where xxx is the name of the main program unit.

Finally, the linker is used to build the resulting executable program, using the object from the main program from the bind step as well as the object files for the Ada units of the program.

Mixed Language Programming

You build a program that contains some Ada files and some other language files in one of two ways, depending on whether the main program is in Ada or not.

If the main program is in Ada, you proceed as follows:

  1. Compile the Ada units to produce a set of object files and ALI files.
  2. Compile the other language files to generate object files.
  3. Run the Ada binder on the Ada main program.
  4. Compile the Ada main program.
  5. Link the Ada main program, Ada objects and other language objects.

If the main program is in some language other than Ada, you use a special option of the binder to generate callable routines to initialize and finalize the Ada units. You must insert calls to these routines in the main program, or some other appropriate point. The call to initialize the Ada units must occur before the first Ada subprogram is called, and the call to finalize the Ada units must occur after the last Ada subprogram returns. You use the same procedure for building the program as described previously. In this case, however, the binder places the initialization and finalization subprograms into file `b_xxx.c' instead of the main program.

Comparison of GNAT Model With C/C++ Compilation Model

The GNAT model of compilation is close to the C and C++ models. You can think of Ada specs as corresponding to header files in C. As in C, you don't need to compile specs; they are compiled when they are used. The Ada with is similar in effect to the #include of a C header.

One notable difference is that, in Ada, you may compile specs separately to check them for semantic and syntactic accuracy. This is not always possible with C headers because they are fragments of programs that have no specific syntactic or semantic rules.

The other major difference is the requirement for running the binder, which performs two important functions. First, it checks for consistency. In C or C++, the only defense against putting together inconsistent programs is outside the compiler, in a make file, for example. The binder satisfies the Ada requirement that it be impossible to construct an inconsistent program when the compiler is used in normal mode.

The other important function of the binder is to deal with elaboration issues. There are also elaboration issues in C++ that are handled automatically. This automatic handling has the advantage of being simpler to use, but the C++ programmer has no control over elaboration. Where gnatbind might complain there was no valid order of elaboration, a C++ compiler would simply construct a program that malfunctioned at runtime.

Comparison of GNAT Model With Traditional Ada Library Model

This section is intended to be useful to Ada programmers who have previously used an Ada compiler implementing the traditional Ada library model, as described in the Ada 95 Languages Reference Manual. If you have not used such a system, please go on to the next section.

In GNAT, there no library in the normal sense. Instead, the set of source files themselves acts as the library. Compiling Ada programs does not generate any centralized information, but rather an object file and a ALI file, which are of interest only to the binder and linker.

In a traditional system, the compiler reads information not only from the source file being compiled, but also from the centralized library. This means that the effect of a compilation depends on what has been previously compiled. In particular:

In GNAT, compiling one unit never affects the compilation of any other units since the compiler reads only source files. Only changes to source files can affect the results of a compilation. In particular:

The important result of these differences are that order of compilation is never significant in GNAT. There is no situation in which you are required to do one compilation before another. What shows up as order of compilation requirements in the traditional Ada library becomes, in GNAT, simple source dependencies; in other words, it shows up as a set of rules saying what source files must be present when a file is compiled.

Compiling Ada Programs With gcc

This chapter discusses how to compile Ada programs and the switches passed to the compiler.

Compiling Programs

The first step in creating an executable program is to compile the units of the program using the gcc command. You must compile the following files:

You need not compile the following files

because they are compiled as part of compiling related units. GNAT compiles generic units when a client instantiates the generic, specs when the corresponding body is compiled, and subunits when the parent is compiled.

If you attempt to compile any of these files, you will get this error message:

No code generated for unit xxx in file yyy

The basic command for compiling a file containing an Ada unit is

gcc -c [switches] file name

where file name is the name of the Ada file (having an extension `.ads' for a spec or `.adb' for a body). You specify the `-c' switch to tell gcc to compile, but not link, the file. The result of a successful compilation is an object file, which has the same name as the source file but an extension of `.o' and an Ada Library Information (ALI) file, which also has the same name as the source file, but with `.ali' as the extension. GNAT creates these two output files in the current directory, but you may specify a source file in any directory using an absolute or relative path specification containing the directory information.

switches consist of standard gcc switches, as documented in for the GNU C compiler, as well as GNAT specific switches, which always start with `-gnat'. You may specify these switches in any order, and, in particular, may mix gcc and GNAT switches freely.

gcc is actually a driver program that looks at the extensions of the file arguments and loads the appropriate compiler. For example, the GNU C compiler is `cc1', and the Ada compiler is `gnat1'. These programs are in directories known to the driver program (in some configurations via environment variables you set), but need not be in your path. The gcc driver also calls the assembler and any other utilities needed to complete the generation of the required object files.

It is possible to supply several file names on the same gcc command. This causes gcc to call the appropriate compiler for each file. For example, the command

gcc -c x.adb y.adb z.c

calls gnat1 (the Ada compiler) twice to compile `x.adb' and `y.adb', and cc1 (the C compiler) once to compile `z.c'. The compiler generates three object files `x.o', `y.o' and `z.o' and the two ALI files `x.ali' and `y.ali' from the Ada compilations. Any switches apply to all the files, except for `-gnatx' switches, which apply only to Ada compilations.

Switches for gcc

The gcc command accepts numerous switches. The following are the ones you wil most likely need. Note that these switches are case sensitive.

`-b target'
Compile your program to run on target, which is the name of a system configuration. You must have a GNAT cross-compiler built if target is not the same as your host system.
Load compiler executables (for example, gnat1, the Ada compiler) from dir instead of the default location. Only use this switch when multiple versions of the GNAT compiler are available. See the gcc manual page for further details. You would normally use the `-b' or `-V' switch instead.
Compile. Always use this switch when compiling Ada programs. Note that you may not use gcc without a `-c' switch to compile and link in one step. This is because the binder must be run, and currently gcc cannot be used to run the GNAT binder.
Generate debugging information. This information is stored in the object file and copied from there to the final executable file by the linker, where it can be read by the debugger. You must use the `-g' switch if you plan on using the debugger. options are used to choose the debugging format if more than one is available; see the gcc manual for more details.
Direct GNAT to search the dir directory for source files needed by the current compilation (see section Search Paths and the Run-Time Library (RTL)).
`-o file'
This switch is used in gcc to redirect the generated object file. Do not use it with GNAT, because it causes the object file and ALI file to have different names and locations. These files should always be kept together.
n controls the optimization level.
n = 0
No optimization, the default setting if no `-O' appears
n = 1
Normal optimization, the default if you specify `-O' without an operand.
n = 2
Extensive optimization
n = 3
Extensive optimization with automatic inlining. This applies only to inlining within a unit. See section Subprogram Inlining Control for details on control of inter-unit inlining.
Use in place of `-c' to cause the assembler source file to be generated, using `.s' as the extension, instead of the object file. This may be useful if you need to examine the generated assembly code.
Show commands generated by the gcc driver. Normally used only for debugging purposes or if you need to be sure what version of the compiler you are executing.
`-V ver'
Execute ver version of the compiler. This is the gcc version, not the GNAT version.
Generate warnings for uninitialized variables. You must also specify the `-O' switch (in other words, `-Wuninitialized' works only if optimization is turned on).

Many additional gcc switches are relevant. They are fully described in the gcc manual.

Switches for GNAT

Below is a brief summary of the switches accepted by the gcc command when compiling GNAT programs. It is followed by a more complete description of these switches, which has been organized functionally.

Assertions enabled. Pragma Assert and pragma Debug to be activated.
Generate brief messages to stderr even if verbose mode set.
Check syntax and semantics only (no code generation attempted).
Error messages generated immediately, not saved up till end.
Full errors. Multiple errors per line, all undefined references.
GNAT style checks enabled.
Identifier char set (c=1/2/3/4/8/p/f/n/w).
Wide character encoding method (e=n/h/u/s/e).
Limit file names to n (1-999) characters (`k' = krunch).
Output full source listing with embedded error messages.
Limit number of detected errors to n (1-999).
Activate inlining across unit boundaries.
Enable other checks, not normally enabled by default, including numeric overflow checking, and access before elaboration checks.
Suppress all checks.
Don't quit; try semantics, even if parse errors.
Reference manual column layout required.
Syntax check only.
Tree output file to be generated.
List units for this compilation.
Verbose mode. Full error output with source lines to stdout.
Warning mode. (m=s/e for suppress/treat as error).
Distribution stub generation (m=r/s for receiver/sender stubs).
Enforce Ada 83 restrictions.

You may combine a sequence of GNAT switches into a single switch. For example, the specifying the switch


is equivalent to specifying the following sequence of switches:

-gnatc -gnatf -gnati3

Error Message Control

The standard default format for error messages is called "brief format." Brief format messages are written to stdout (the standard output file) and have the following form:

e.adb:3:04: Incorrect spelling of keyword "function"
e.adb:4:20: ";" should be "is"

The first integer after the file name is the line number and the second integer is the column number. emacs can parse the error messages and point to the referenced character.

The following `-gnat' switches allow control over the error message format:

The v stands for verbose. The effect is to write long-format error messages to stdout. The same program compiled with the `-gnatv' switch would generate:
3. funcion X (Q : Integer)
>>> Incorrect spelling of keyword "function"
4. return Integer;
>>> ";" should be "is"
The vertical bar indicates the location of the error, and the `>>>' prefix can be used to search for error messages. When this switch is used the only source lines output are those with errors.
The `l' stands for list. `-gnatl' causes a full listing of the file to be generated. The output is as follows:
 1. procedure E is
 2.    V : Integer;
 3.    function X (Q : Integer)
    >>> Incorrect spelling of keyword "function"
 4.     return Integer;
    >>> ";" should be "is"
 5.    begin
 6.       return Q + Q;
 7.    end;
 8. begin
 9.    V := X + X;
10.end E;
When you specify the `-gnatv' or `-gnatl' switches and standard output is redirected, a brief summary is written to stderr (standard error) giving the number of error messages and warning messages generated.
The `b' stands for brief. This switch causes GNAT to generate the brief format error messages to stdout as well as the verbose format message or full listing.
The `m' stands for maximum. n is a decimal integer in the range of 1 to 999 and limits the number of error messages to be generated. For example, using `-gnatm2' might yield
e.adb:3:04: Incorrect spelling of keyword "function"
e.adb:5:35: missing ".."
fatal error: maximum errors reached
compilation abandoned
Normally, the compiler suppresses error messages that are likely to be redundant. This switch, where `f' stands for full, causes all error messages to be generated. One particular effect is for the case of references to undefined variables. If a given variable is referenced several times, the normal format of messages is
e.adb:7:07: "V" is undefined (more references follow)
where the parenthetical comment warns that there are additional references to the variable V. Compiling the same program with the `-gnatf' switch yields
e.adb:7:07: "V" is undefined
e.adb:8:07: "V" is undefined
e.adb:8:12: "V" is undefined
e.adb:8:16: "V" is undefined
e.adb:9:07: "V" is undefined
e.adb:9:12: "V" is undefined
In normal operation mode the compiler first parses the program and determines if there are any syntax errors. If there are, appropriate error messages are generated and compilation is immediately terminated. Here `q' is for quit (really "don't quit") and this switch tells GNAT to continue with semantic analysis even if syntax errors have been found. This may enable the detection of more errors in a single run. On the other hand, the semantic analyzer is more likely to encounter some internal fatal error when given a syntactically invalid tree.
Normally, the compiler saves up error messages and generates them at the end of compilation in proper sequence. This switch (the `e' stands for error) causes error messages to be generated as soon as they are detected. The use of `-gnate' usually causes error messages to be generated out of sequence. Use it when the compiler blows up due to an internal error. In this case, the error messages may be lost. Sometimes blowups are the result of mishandled error messages, so you may want to run with the `-gnate' switch to determine whether any error messages were generated (see section GNAT Crashes).

In addition to error messages, corresponding to illegalities as defined in the reference manual, the compiler detects two kinds of warning situations.

First, the compiler considers some constructs suspicious and generates a warning message to alert you to a possible error. Second, if the compiler detects a situation that is sure to raise an exception at runtime, it generates a warning message. The following shows an example of warning messages:

e.adb:4:24: warning: creation of object of this type may raise Storage_Error
e.adb:10:17: warning: static value out of range
e.adb:10:17: warning: "Constraint_Error" will be raised at runtime

Two switches are available to control the handling of warning messages:

The `w' stands for warning and the `e' stands for error. The `-gnatwe' switch causes warning messages to be treated as errors. The warning string still appears, but the warning messages are counted as errors, and prevent the generation of an object file.
The `s' stands for suppress. This switch completely suppresses the output of all warning messages.

Debugging and Assertion Control

The pragmas Assert and Debug normally have no effect and are ignored. This switch, where `a' stands for assert, causes Assert and Debug pragmas to be activated. The pragmas have the form:
pragma Assert (Boolean-expression [, static-string-expression])
pragma Debug (procedure)
The Assert pragma causes Boolean-expression to be tested. If the result is True, the pragma has no effect (other than possible side effects from evaluating the expression). If the result is False, the exception System.Assertions.Assert_Error is raised (passing static-string-expression, if present, as the message associated with the exception). The Debug pragma causes procedure to be called. Note that pragma Debug may appear within a declaration sequence, allowing debugging procedures to be called between declarations.

Runtime Checks

If you compile with the default options, GNAT will insert many runtime checks into the compiled code, including code that performs range checking against constraints, but not arithmetic overflow checking for integer operations (including division by zero) or checks for access before elaboration on subprogram calls. All other runtime checks, as required by the Ada 95 Reference Manual, are generated by default.

The following two gcc switches refine this default behavior:

Suppress all runtime checks as though you have pragma Suppress (all_checks) in your source. Use this switch to improve the performance of the code at the expense of safety in the presence of invalid data or program bugs.
Enables overflow checking for integer operations and checks for access before elaboration on subprogram calls (`o' stands for "other checks"). This causes GNAT to generate slower and larger executable programs by adding code to check for both overflow and division by zero (resulting in raising Constraint_Error as required by Ada semantics). Similarly, GNAT does not generate elaboration checks by default, and you must specify the `-gnato' switch to enable them. Note that the `-gnato' switch does not affect the code generated for any floating-point operations; it applies only to integer operations. For floating-point, GNAT has the Machine_Overflows attribute set to False and the normal mode of operation is to generate IEEE NaN and infinite values on overflow or invalid operations (such as dividing 0.0 by 0.0).

The setting of these switches only controls the default setting of the checks. You may modify them using either Suppress (to remove checks) or Unsuppress (to add back suppressed checks) pragmas in the program source.

Using gcc for Syntax Checking

Run GNAT in syntax checking only mode (`s' stands for syntax). For example, the command
gcc -c -gnats x.adb
compiles file `x.adb' in syntax-check-only mode. You can check a series of files in a single command, and can use wild cards to specify such a group of files. Note that you must specify the `-c' (compile only) flag in addition to the `-gnats' flag. You may use other switches in conjunction with `-gnats'. In particular, `-gnatl' and `-gnatv' are useful to control the format of any generated error messages. The output is simply the error messages, if any. No object file or ALI file is generated by a syntax-only compilation. Also, no units other than the one specified are accessed. For example, if a unit X with's a unit Y, compiling unit X in syntax check only mode does not access the source file containing unit Y. Normally, GNAT allows only a single unit in a source file. However, this restriction does not apply in syntax-check-only mode, and it is possible to check a file containing multiple compilation units concatenated together. This is primarily used by the gnatchop utility (see section Handling Files With Multiple Units With gnatchop).

Using gcc for Semantic Checking

Cause the compiler to operate in semantic check mode (`c' stands for check), with full checking for all illegalities specified in the reference manual, but without generation of any source code (no object or ALI file generated). Since dependent files must be accessed, you must follow the GNAT semantic restrictions on file structuring to operate in this mode: The output consists of error messages as appropriate. No object file or ALI file is generated. The checking corresponds exactly to the notion of legality in the Ada reference manual. Any unit can be compiled in semantics-checking-only mode, including units that would not normally be compiled (generic library units, subunits, and specifications where a separate body is present).

Compiling Ada 83 Programs

Although GNAT is primarily an Ada 95 compiler, it accepts this switch to specify that an Ada 83 mode program is being compiled. If you specify this switch, GNAT rejects Ada 95 extensions and applies Ada 83 semantics. It is not possible to guarantee this switch does a perfect job; for example, some subtle tests of pathological cases, such as are found in ACVC tests that have been removed from the ACVC suite for Ada 95, may not compile correctly. However for practical purposes, using this switch should ensure that programs that compile correctly under the `-gnat83' switch can be ported reasonably easily to an Ada 83 compiler. This is the main use of the switch. With few exceptions (most notably the need to use <> on unconstrained generic formal parameters), it is not necessary to use the `-gnat83' switch when compiling Ada 83 programs, because, with rare and obscure exceptions, Ada 95 is upwardly compatible with Ada 83. This means that a correct Ada 83 program is usually also a correct Ada 95 program.

Style Checking

Normally, GNAT permits any code layout consistent with the reference manual requirements. This switch (`r' is for "reference manual") enforces the layout conventions suggested by the examples and syntax rules of the Ada Language Reference Manual. For example, an else must line up with an if and code in the then and else parts must be indented. The compile considers violations of the layout rules a syntax error if you specify this switch.
Enforces a set of style conventions that correspond to the style used in the GNAT source code. All compiler units are always compile with the `-gnatg' switch specified. You can find the full documentation for the style conventions imposed by `-gnatg' in the body of the package Style in the compiler sources (in the file `style.adb'). You should not normally use the `-gnatg' switch. However, you must use `-gnatg' for compiling any language-defined unit, or for adding children to any language-defined unit other than Standard.

Character Set Control

Normally GNAT recognizes the Latin-1 character set in source program identifiers, as described in the reference manual. This switch causes GNAT to recognize alternate character sets in identifiers. c is a single character indicating the character set, as follows:
Latin-1 identifiers
Latin-2 letters allowed in identifiers
Latin-3 letters allowed in identifiers
Latin-4 letters allowed in identifiers
IBM PC letters (code page 437) allowed in identifiers
IBM PC letters (code page 850) allowed in identifiers
Full upper-half codes allowed in identifiers
No upper-half codes allowed in identifiers
Wide-character codes allowed in identifiers
See section Foreign Language Representation, for full details on the implementation of these character sets.
Specify the method of encoding for wide characters. e is one of the following:
No wide characters allowed (default setting)
Hex encoding
Upper half encoding
Shift/JIS encoding
EUC encoding

File Naming Control

Activates file name "krunching". n, a decimal integer in the range 1-999, indicates the maximum allowable length of a file name (not including the `.ads' or `.adb' extension). The default is not to enable file name krunching. For the source file naming rules, see section File Naming Rules.

Subprogram Inlining Control

GNAT recognizes and processes Inline pragmas. However, for the inlining to actually occur, optimization must be enabled. To enable inlining across unit boundaries, this is, inlining a call in one unit of a subprogram declared in a with'ed unit, you must also specify this switch (`n' suggests the first syllable of the word "inline"). In the absence of the `-gnatn' switch, GNAT does not attempt inlining across units and does not need to access the bodies of subprograms for which pragma Inline is specified if they are not in the current unit. If you specify `-gnatn', the compiler will access these bodies, creating an extra source dependency for the resulting object file, and where possible, the call will be inlined. See section Inlining of Subprograms for further details on when inlining is possible.

Auxiliary Output Control

Cause GNAT to write the internal tree for a unit to a file (with the extension `.atb' for a body or `.ats' for a spec). This is not normally required, but is used by separate analysis tools. Typically these tools do the necessary compilations automatically, so you should never have to specify this switch in normal operation.
Print a list of units required by this compilation on stdout. The listing includes all units on which the unit being compiled depends either directly or indirectly.

Debugging Control

Activate internal debugging switches. x is a letter or digit, or string of letters or digits, which specifies the type of debugging outputs desired. Normally these are used only for internal development or system debugging purposes. You can find full documentation for these switches in the body of the Debug unit in the compiler source file `debug.adb'. One switch you may wish to use is `-gnatdg', which causes a listing of the generated code in Ada source form. For example, all tasking constructs are reduced to appropriate runtime library calls. The syntax of this listing is close to normal Ada with the following additions:
new xxx [storage_pool = yyy]
Shows the storage pool being used for an allocator.
at end procedure-name;
Shows the finalization (cleanup) procedure for a scope.
(if expr then expr else expr)
Conditional expression equivalent to the x?y:z construction in C.
A conversion with floating-point truncation instead of rounding.
A conversion that bypasses normal Ada semantic checking. In particular enumeration types and fixed-point types are treated simply as integers.
Combines the above two cases.
x #/ y
x #mod y
x #* y
x #rem y
A division or multiplication of fixed-point values which are treated as integers without any kind of scaling.
free expr [storage_pool = xxx]
Shows the storage pool associated with a free statement.
freeze typename [actions]
Shows the point at which typename is frozen, with possible associated actions to be performed at the freeze point.
reference itype
Reference (and hence definition) to internal type itype.
function-name! (arg, arg, arg)
Intrinsic function call.
labelname : label
Declaration of label labelname.
expr && expr && expr ... && expr
A multiple concatenation (same effect as expr & expr & expr, but handled more efficiently).
Raise the Constraint_Error exception.
A pointer to the result of evaluating expression.
An unchecked conversion of source-expression to target-type.
Used to represent internal real literals (that) have no exact representation in base 2-16 (for example, the result of compile time evaluation of the expression 1.0/27.0).

Search Paths and the Run-Time Library (RTL)

With the GNAT source-based library system, the compiler must be able to find source files for units that are needed by the unit being compiled. Search paths are used to guide this process.

The compiler compiles one source file whose name must be given explicitly on the command line. In other words, no searching is done for this file. To find all other source files that are needed (the most common being the specs of units), the compiler looks in the following directories, in the following order:

  1. The directory containing the source file of the main unit being compiled (the file name on the command line).
  2. Each directory named by an `-I' switch given on the gcc command line, in the order given.
  3. Each of the directories listed in the value of the ADA_INCLUDE_PATH environment variable. Construct this value exactly as the PATH environment variable: a list of directory names separated by colons.
  4. The default location for the GNAT Run Time Library (RTL) source files. This is determined at the time GNAT is built and installed on your system.

The compiler outputs its object files and ALI files in the current working directory

Caution: The object file can be redirected with the `-o' switch; however, gcc and gnat1 have not been coordinated on this so the ALI file will not go to the right place. Therefore, you should avoid using the `-o' switch.

The packages Ada, System, and Interfaces and their children make up the GNAT RTL, together with the simple System.IO package used in the "Hello World" example. The sources for these units are needed by the compiler and are kept together in one directory. Not all of the bodies are needed, but all of the sources are kept together anyway. In a normal installation, you need not specify these directory names when compiling or binding. Either the environment variables or the built-in defaults cause these files to be found.

Besides the assistance in using the RTL, a major use of search paths is in compiling sources from multiple directories. This can make development environments much more flexible.

Order of Compilation Issues

If, in our earlier example, there was a spec for the hello procedure, it would be contained in the file `'; yet this file would not need to be explicitly compiled. This is the result of the model we chose to implement library management. Details of the model can be found in file `gnote1.doc' in the GNAT sources. Some of the unexpected consequences of the model (unexpected from the point of view of existing Ada compiler systems) are the following:

Note: The above may seem surprising. However, we are not violating the strict Ada consistency rules; these rules are enforced instead by the binder.


The following are some typical Ada compilation command line examples:

gcc -c xyz.adb
Compile body in file `xyz.adb' with all default options.
gcc -c -O2 -gnata xyz-def.adb
Compile the child unit package in file `xyz-def.adb' with extensive optimizations, and pragma Assert/Debug statements enabled.
gcc -c -gnatc abc-def.adb
Compile the subunit in file `abc-def.adb' in semantic-checking-only mode.

Binding Ada Programs With gnatbind

This chapter describes the GNAT binder, gnatbind, which is used to bind compiled GNAT objects. The gnatbind program performs four separate functions:

  1. Checks that a program is consistent, in accordance with the rules in chapter 10 of the Ada Language Reference Manual. In particular, error messages are generated if a program uses inconsistent versions of a given unit.
  2. Checks that an acceptable order of elaboration exists for the program and issues an error message if it cannot find an order of elaboration satisfying the rules in Chapter 10 of the Ada Language Reference Manual.
  3. Generates a main program incorporating the given elaboration order. This program is a small C source file that must be subsequently compiled using the C compiler. The two most important functions of this program are to call the elaboration routines of units in an appropriate order and to call the main program.
  4. Determines the set of object files required by the given main program. This information is output as comments in the generated C program, to be read by the gnatlink utility used to link the Ada application.

Running gnatbind

The form of the gnatbind command is

gnatbind [switches] mainprog.ali [switches]

where mainprog.adb is the Ada file containing the main program unit body. If no switches are specified, gnatbind constructs a C file whose name is `b_mainprog.c'. For example, if given the parameter `hello.ali', for a main program contained in file `hello.adb', the binder output file would be `b_hello.c'.

When doing consistency checking, the binder takes any source files it can locate into consideration. For example, if the binder determines that the given main program requires the package Pack, whose ALI file is `pack.ali' and whose corresponding source spec file is `', it attempts to locate the source file `' (using the same search path conventions as previously described for the gcc command). If it can located this source file, the time stamps must match. In other words, any ALI files mentioning this spec must have resulted from compiling this version of the source file.

The effect of this consistency checking, which includes source files, is that the binder ensures that the program is consistent with the latest version of the source files that can be located at bind time. Editing a source file without compiling files that depend on the source file cause error messages to be generated from the binder.

For example, suppose you have a main program `hello.adb' and a package p, from file `' and you perform the following steps:

  1. Enter gcc -c hello.adb to compile the main program.
  2. Enter gcc -c to compile package p.
  3. Edit file `'.
  4. Enter gnatbind hello.ali.

At this point, the file `p.ali' contains an out-of-date time stamp since the file `' has been edited. The attempt at binding fails, and the binder generates the following error messages:

error: "hello.adb" must be recompiled ("" has been modified)
error: "" has been modified and must be recompiled

Now both files must be recompiled as indicated, and then the bind can succeed, generating a main program. You need not normally be concerned with the contents of this file, but it is similar to the following:

__main_priority ()
  return -1;
extern int gnat_argc;
extern char **gnat_argv;
extern int gnat_exit_status;
void main (argc, argv)
int argc;
char **argv;
  gnat_argc = argc;
  gnat_argv = argv;

  system__task_specific_data___elabb ();
  p___elabs ();

  _ada_hello ();
  exit (gnat_exit_status);
unsigned helloB = 0x86c26330;
unsigned system__standard_libraryS = 0x06371136;
unsigned pS = 0x4361339a;
unsigned systemS = 0x430ca9a6;
unsigned system__storage_elementsB = 0xc925fce2;
unsigned system__storage_elementsS = 0x86195344;
unsigned system__task_specific_dataB = 0x924bf9bc;
unsigned system__task_specific_dataS = 0x86195344;
unsigned system__tasking_soft_linksB = 0x0c32a681;
unsigned system__tasking_soft_linksS = 0x86195344;
/* BEGIN Object file/option list
END Object file/option list */

The __main_priority function records the environment task priority. A value of -1 indicates that the main program has no pragma Priority, the normal case.

Next there is code to save the argc and argv values for later access by the Ada.Command_Line package. The variable gnat_exit_status saves the exit status set by calls to Ada.Command_Line.Set_Exit_Status and is used to return an exit status to the system.

The call to __gnat_initialize and the corresponding call at the end of execution to __gnat_finalize allow any specialized initialization and finalization code to be hooked in. The default versions of these routines do nothing.

The calls to system__task_specific_data___elabb and p___elabs perform necessary elaboration of units in the program. In our example, only the library routine System.Task_Specific_Data (body) and P (spec) required elaboration; the main program `hello.adb' did not require any elaboration.

The call to _ada_hello is the call to the main program.

The list of unsigned constants gives the version number information. Version numbers are computed by combining time stamps of a unit and all units on which it depends. These values are used for implementation of the Version and Body_Version attributes.

Finally, a set of comments gives full names of all the object files required to be linked for the Ada component of the program. As seen in the previous example, this list includes the files explicitly supplied and referenced by the user as well as implicitly referenced runtime unit files. The directory names for the runtime units depend on the system configuration.

Consistency-Checking Modes

As described in the previous section, by default gnatbind checks that object files are consistent with one another and are consistent with any source files it can locate. The following switches can be used to modify this behavior:

Require source files to be present. In this mode, the binder insists on being able to locate all source files that are referenced and checks their consistency. In normal mode, if a source file cannot be located it is simply ignored. If you specify the `-s' switch, a missing source file is an error.
Exclude source files. In this mode, the binder only checks that ALI files are consistent with one another. Source files are not accessed. The binder runs faster in this mode, and there is still a guarantee that the resulting program is self-consistent. If a source file has been edited since it was last compiled and you specify the `-x' switch, the binder will not detect that the object file is out of date with the source file.

For most purposes the default mode is appropriate, and this is the mode that is normally used when gnatmake or gnatbind is used to do the bind operation.

Error-Message Control

The following switches provide control over the generation of error messages from the binder:

Verbose mode. In the normal mode, brief error messages are generated to stderr. If the `-v' switch is present, a header is written to stdout and any error messages are directed to stdout. All that is written to stderr is a brief summary message.
Generate brief error messages to stderr even if verbose mode is specified. This is relevant only when used together with the `-v' switch.
Limits the number of error messages to n, a decimal integer in the range 1-999. The binder terminates immediately if this limit is reached.
Suppress all warning messages.
Treat any warning messages as fatal errors.
Ignore time stamp errors. Any time stamp error messages are treated as warning messages. This switch essentially disconnects the normal consistency checking, and the resulting program may have undefined semantics if inconsistent units are present. This means that `-t' should be used only in unusual situations, with extreme care.

Output Control

The following switches allow additional control over the output generated by the binder.

Output complete list of elaboration-order dependencies, showing the reason for each dependency. This output can be rather extensive but may be useful in diagnosing problems with elaboration order. The output is written to stdout.
Output chosen elaboration order. The output is written to stdout.
`-o file'
Set name of output file to file instead of the normal `b_prog.c' default. You would normally give file an extension of `.c' since it will be a C source program.
Check only. Do not generate the binder output file. In this mode the binder performs all error checks but does not generate an output file.

Binding for Non-Ada Main Programs

In our description in this chapter so far we have assumed the main program is in Ada and the task of the binder is to generate a corresponding function main to pass control to this Ada main program. GNAT also supports the building of executable programs where the main program is not in Ada, but some of the called routines are written in Ada and compiled using GNAT. The following switch is used in this situation:

No main program. The main program is not in Ada.

In this case, most of the functions of the binder are still required, but instead of generating a main program, the binder generates a file containing the following callable routines:

You must call this routine to initialize the Ada part of the program by calling the necessary elaboration routines. A call to adainit is required before the first call to an Ada subprogram.
You must call this routine to perform any library-level finalization required by the Ada subprograms. A call to adafinal is required after the last call to an Ada subprogram, and before the program terminates.

If the `-n' switch is given, more than one ALI file may appear on the command line for gnatbind. The normal closure calculation is performed for each of the specified units. Calculating the closure means finding out the set of units involved by tracing with references. The reason it is necessary to be able to specify more than one ALI file is that a given program may invoke two or more quite separate groups of Ada subprograms.

The binder takes the name of its output file from the first specified ALI file, unless overridden by the use of the `-o' switch. It will be a C source file, which must be compiled using the C compiler.

Summary of Binder Switches

The following are the switches available with gnatbind:

Generate brief messages to stderr even if verbose mode set.
Check only, no generation of binder output file.
Output complete list of elaboration-order dependencies.
Specify directory to be searched for source and ALI files.
Output-chosen elaboration order.
Limit number of detected errors to n (1-999).
No main program.
`-o file'
Name the output file file (default is `b_xxx.c').
Require all source files to be present.
Ignore time-stamp errors.
Verbose mode. Write error messages, header, summary output to stdout.
Warning mode (x=s/e for suppress/treat as error)
Exclude source files (check object consistency only

You may obtain this listing by running the program gnatbind with no arguments.

Command-Line Access

The package Ada.Command_Line provides access to the command-line arguments and program name. In order for this interface to operate correctly, the two variables

int gnat_argc;
char **gnat_argv;

are declared in one of the GNAT library routines. These variables must be set from the actual argc and argv values passed to the main program. With no `-n' switch present, gnatbind generates the C main program to automatically set these variables. If the `-n' switch is used, there is no automatic way to set these variables. If they are not set, the procedures in Ada.Command_Line will not be available, and any attempt to use them will raise Constraint_Error. If command line access is required, your main program must set gnat_argc and gnat_argv from the argc and argv values passed to it.

Search Paths for gnatbind

The binder must be able to find both the ALI files and the source files. For source files, it follows exactly the same search rules as gcc (see section Search Paths and the Run-Time Library (RTL)). Search paths are used for finding the ALI files.

The binder takes the name of an ALI file as its argument and needs to locate other ALI files in its recursive processing. These are found in the following directories in the following order:

  1. The current working directory.
  2. All directories specified by `-I' switches on the gnatbind command line, in the order given.
  3. Each of the directories listed in the value of the ADA_OBJECTS_PATH environment variable. Construct this value the same as the PATH environment variable: a list of directory names separated by colons.
  4. The default location for the GNAT Run-Time Library (RTL) files, determined when GNAT was built and installed on your system.

For source files accessed by the binder, the search procedure is as described above for object files, except that in step 3 the environment variable ADA_INCLUDE_PATH is used. The binder generates the bind file (a C language source file) in the current working directory.

The packages Ada, System, and Interfaces and their children make up the GNAT Run-Time Library, together with the package GNAT and its children which contain a set of useful additional library functions provided by GNAT. The sources for these units are needed by the compiler and are kept together in one directory. The ALI files and object files generated by compiling the RTL are needed by the binder and the linker and are kept together in one directory, typically different from the directory containing the sources. In a normal installation, you need not specify these directory names when compiling or binding. Either the environment variables or the built-in defaults cause these files to be found.

Besides the assistance in using the RTL, a major use of search paths is in compiling sources from multiple directories. This can make development environments much more flexible.

Examples of gnatbind Usage

This section contains a number of examples of using the GNAT binding utility gnatbind.

gnatbind hello.ali
The main program Hello (source program in `hello.adb') is bound using the standard switch settings. The generated main program is `b_hello.c'. This is the normal, default use of the binder.
gnatbind main_program.ali -o mainprog.c -x -e
The main program Main_Program (source program in `main_program.adb') is bound, excluding source files from the consistency checking. A full list of elaboration dependencies is output to stdout, and the file `mainprog.c' is generated.
gnatbind -xe main_program.ali -o mainprog.c
This command is exactly the same as the previous example. Switches may appear anywhere in the command line, and single letter switches may be combined into a single switch.
gnatbind -n math.ali dbase.ali -o ada-control.c
The main program is in a language other than Ada, but calls to subprograms in packages Math and Dbase appear. This call to gnatbind generates the file `ada-control.c' containing the adainit and adafinal routines to be called before and after accessing the Ada subprograms.

Linking Ada Programs Using gnatlink

This chapter discusses gnatlink, a utility program used to link Ada programs and build an executable file. This program is basically a simple process which invokes the UNIX linker (via the gcc command) with a correct list of object files and library references. gnatlink automatically determines the list of files and references for the Ada part of a program. It uses the binder file generated by the binder to determine this list.

Running gnatlink

The form of the gnatlink command is

gnatlink [switches] mainprog[.ali] [non-Ada objects] [linker options]

`mainprog.ali' references the ALI file of the main program. The `.ali' extension of this file can be omitted. From this reference, gnatlink locates the corresponding binder file `b_mainprog.c' and, using the information in this file along with the list of non-Ada objects and linker options, constructs a UNIX linker command file to create the executable.

The arguments following `mainprog.ali' are passed to the linker uninterpreted. They typically include the names of object files for units written in other languages than Ada and any library references required to resolve references in any of these foreign language units, or in pragma Import statements in any Ada units. This list may also include linker switches.

gnatlink determines the list of objects required by the Ada program and prepends them to the list of objects passed to the linker. gnatlink also gathers any arguments set by the use of pragma Linker_Options and adds them to the list of arguments presented to the linker.

Switches for gnatlink

The following switches are available with the gnatlink utility:

`-o exec-name'
exec-name specifies an alternative name for the generated executable program. If the `-o' switch is omitted, the executable is called the name of the main unit. So gnatlink try.ali creates an executable called `try'.
Causes additional information to be output, including a full list of the included object files. This switch option is most useful when you want to see what set of object files are being used in the link step.
The option to include debugging information causes the C bind file (in other words, `b_mainprog.c') to be compiled with `-g'. In addition, the binder does not delete the `b_mainprog.c' and `b_mainprog.o' files. Without `-g', the binder removes these files by default.
`-gnatlink name'
name is the name of the linker to be invoked. You normally omit this switch, in which case the default name for the linker is (`gcc').

The GNAT Make Program gnatmake

A typical development cycle when working on an Ada program consists of the following steps:

  1. Edit some sources to fix bugs.
  2. Add enhancements.
  3. Compile all sources affected.
  4. Rebind and relink.
  5. Test.

The third step can be tricky, because not only do the modified files have to be compiled, but any files depending on these files must also be recompiled. The dependency rules in Ada can be quite complex, especially in the presence of overloading, use clauses, generics and inlined subprograms.

gnatmake automatically takes care of the third and fourth steps of this process. It determines which sources need to be compiled, compiles them, and binds and links the resulting object files.

Unlike some other Ada make programs, the dependencies are always accurately recomputed from the new sources. The source based approach of the GNAT compilation model makes this possible. This means that if changes to the source program cause corresponding changes in dependencies, they will always be tracked exactly correctly by gnatmake.

Running gnatmake

The gnatmake command has the form

gnatmake [-a] [-c] [-f] [-g] [-jn] [-k] [-M] [-o exec-name] [-n] [-q] [-v] 
         {-Adir} {-aOdir} {-aIdir} {-Idir} {-I-} {-Ldir}
         {-cargs options} {-bargs options} {-largs options}

Here square brackets indicate optional components in the command, and curly brackets indicate a construction that can occur zero or more times.

The only required argument is unit_or_file_name, which specifies the compilation unit that is the main program. There are two ways to specify this:

All gnatmake output (except when you specifiy `-M') is to stderr. The output produced by the `-M' switch is send to stdout.

Switches for gnatmake

You may specify any of the following switches to gnatmake:

Consider all files in the make process, even the GNAT internal system files (for example, the predefined Ada library files). By default, gnatmake does not check these files (however, if there is an installation problem, it will be caught when gnatmake binds your program). You may have to specify this switch if you are working on GNAT itself. The vast majority of gnatmake users never need to specify this switch. By default gnatmake -a compiles all GNAT internal files with gcc -c -gnatg rather than gcc -c.
Compile only. Do not perform binding and linking. If the root unit specified by unit_or_file_name is not a main unit, this is the default. Otherwise gnatmake will attempt binding and linking unless all objects are up to date and the executable is more recent than the objects.
Force recompilations. Recompile all sources, even though some object files may be up to date, but don't recompile predefined or GNAT internal files unless the `-a' switch is also specified.
Compile with debugging information. Same effect as -cargs -g.
Use n processes to carry out the (re)complations. If you have a multiprocessor machine, compilations will occur in parallel. In the event of compilation errors, messages from various compilations might get interspersed (but gnatmake will give you the full ordered list of failing compiles at the end). This can at times be annoying. To get a clean list of error messages don't use `-j'.
Keep going. Continue as much as possible after a compilation error. To ease the programmer's task in case of compilation errors, the list of sources for which the compile fails is given when gnatmake terminates.
Check if all objects are up to date. If they are output the object dependences to stdout in a form that can be directly exploited in a `Makefile'. By default, each source file is prefixed with its (relative or absolute) directory name. This name is whatever you specified in the various `-aI' and `-I' switches. If you use gnatmake -M -q (see `-q' below), only the source file names, without relative paths, are output. If you just specify the `-M' switch, dependencies of the GNAT internal system files are omitted. This is typically what you want. If you also specify the `-a' switch, dependencies of the GNAT internal files are also listed. Note that dependencies of the objects in external Ada libraries (see switch `-aLdir' in the following list) are never reported.
Don't compile, bind, or link. Output a single command that will recompile an out of date unit, if any. Repeated use of this option, followed by carrying out the indicated compilation, will eventually result in recompiling all required units. If any ALI is missing during the process, gnatmake halts and displays an error message.
`-o exec_name'
Output executable name. The name of the final executable program will be exec_name. If the `-o' switch is omitted the default name for the executable will be the name of the input file without the suffix (UNIX systems) or the name of the input file with an `.exe' extension (DOS and OS/2). You may prefix exec_name with a relative or absolute directory path.
Quiet. When this flag is not set, the commands carried out by gnatmake are displayed.
Verbose. Displays the reason for all recompilations gnatmake decides are necessary.
`gcc switches'
The switch `-g' or any upper case switch (other than `-A', or `-L') or switch that is more than one character is passed to gcc (e.g. `-O', `-gnato,' etc.)

Source and library search path switches:

Equivalent to `-aLdir -aIdir'.
When looking for library and object files look also in directory dir. The order in which library files search is undertaken is described in section Search Paths and the Run-Time Library (RTL).
When looking for source files also look in directory dir.
Equivalent to `-aOdir -aIdir'.
Do not look for source, library or object files in the default directory.
Add directory dir to the list of directories in which the linker will search for libraries. This is equivalent to `-largs -Ldir'.

General compiler, binder or linker switches:

`-cargs options'
Compiler arguments. Without `-cargs', gnatmake uses gcc -c to perform compilations. Otherwise, gnatmake uses gcc -c c_opts, where c_opts is a list of parameters including all the options encountered in the set of `-cargs' switches present on the gnatmake command line. A given sublist of `-cargs' options is terminated upon encountering another `-cargs', `-bargs' or `-largs'. By default, gnatmake -a compiles all GNAT internal files with gcc -c -gnatg rather than gcc -c.
`-bargs options'
Binder arguments. Without `-bargs', gnatmake uses gnatbind unit.ali to bind. Otherwise, gnatmake uses gnatbind b_opts unit.ali. b_opts is akin to c_opts, but is obtained from `-bargs' switches.
`-largs options'
Similar to `-bargs', but specifies the options for gnatlink. Note that you are not allowed to use the `-o' switch within a `-largs'. Use the `-o' switch directly to gnatmake to give a specific name to your executable.

Notes on the Command Line

Please note the following with regard to gnatmake:

How gnatmake Works

Generally gnatmake automatically performs all necessary recompilations and you don't need to worry about how it works. However, it may be useful to have some basic understanding of the gnatmake approach and in particular to understand how it uses the results of previous compilations without incorrectly depending on them.

First a definition: an object file is considered up to date if the corresponding ALI file exists and if all the source files listed in the dependency section of this ALI file have time stamps matching those in the ALI file. This means that neither the source file itself nor any files that it depends on have been modified, and hence there is no need to recompile this file.

gnatmake works by first checking if the specified main program is up to date. If so, it is done, and no compilations are required. If not, it compiles the main program to build a new ALI file that reflects the latest sources. It examines this ALI file to find all the source files on which the main program depends, and recursively applies the up-to-date test on all these files.

This process ensures that gnatmake only trusts the dependencies in an existing ALI file if they are known to be correct. Otherwise it always recompiles to determine a new, guaranteed accurate set of dependencies. Thus the program is compiled "upside down" from what may be more familiar as the required order of compilation in some other Ada systems. In particular, clients are compiled before the units on which they depend. The ability of GNAT to compile in any order is critical in allowing an order of compilation to be chosen that guarantees that gnatmake will recompute a correct set of new dependencies if necessary.

Examples of gnatmake Usage

gnatmake hello.adb
Compile all files necessary to bind and link the main program `hello.adb' (containing unit Hello) and bind and link the resulting object files to generate an executable file `hello'.
gnatmake -q Main_Unit -cargs -O2 -bargs -l
Compile all files necessary to bind and link the main program unit Main_Unit (from file `main_unit.adb'). All compilations will be done with optimization level 2 and the order of elaboration will be listed by the binder. gnatmake will operate in quiet mode, not displaying commands it is executing.

Handling Files With Multiple Units With gnatchop

This chapter discusses how to handle files with multiple units by using the gnatchop utility.

Handling Files With Multiple Units

The basic compilation model of GNAT requires a file submitted to the compiler have only one unit and there must be a strict correspondence between the file name and the unit name.

The gnatchop utility allows both of these rules to be relaxed, allowing GNAT to process files which contain multiple compilation units and files with arbitrary file names. The approach used by gnatchop is to read the specified file and generate one or more output files, containing one unit per file and with proper file names as required by GNAT.

If you want to permanently restructure a set of "foreign" files so that they match the GNAT rules and do the remaining development using the GNAT structure, you can simply use gnatchop once, generate the new set of files and work with them from that point on.

Alternatively, if you want to keep your files in the "foreign" format, perhaps to maintain compatibility with some other Ada compilation system, you can set up a procedure where you use gnatchop each time you compile, regarding the source files that it writes as temporary files that you throw away.

Command Line for gnatchop

The gnatchop command has the form:

gnatchop [-k] [-r] [-s] [-w] file name [directory]

The only required argument is the file name of the file to be chopped. There are no restrictions on the form of this file name. The file itself contains one or more Ada files, in normal GNAT format, concatenated together.

When run in default mode, gnatchop generates one output file in the current directory for each unit in the file. For example, given a file called `hellofiles' containing

procedure hello; 
with Text_IO; use Text_IO; 
procedure hello is 
   Put_Line ("Hello"); 
end hello;

the command

gnatchop hellofiles

generates two files in the current directory, one called `' containing the single line that is the procedure spec, and the other called `hello.adb' containing the remaining text. The original file is not affected. The generated files can be compiled in the normal manner.

Switches for gnatchop

gnachop recognizes the following switches:

Limit generated file names to eight characters. This is useful if the resulting set of files is required to be interoperable with systems like MS-DOS which limit the length of file names.
Generate Source_Reference pragmas. Use this switch if the output files are regarded as temporary and development is to be done in terms of the original unchopped file. The `-r' switch causes Source_Reference pragmas to be inserted into each of the generated files to refers back to the original file name and line number. The result is that all error messages refer back to the original unchopped file. In addition, the debugging information placed into the object file (when the `-g' switch of gcc or gnatmake is specified) also refers back to this original file so that tools like profilers and debuggers will give information in terms of the original unchopped file.
Write a compilation script to standard output containing gcc commands to compile the generated files.
Overwrite existing file names. Normally gnatchop regards it as a fatal error situation if there is already a file with the same name as a file it would otherwise output. The `-w' switch bypasses this check, and any such existing files will be silently overwritten.

directory, if specified, gives the name of the directory to which the output files will be written. If it is not specified, all files are written to the current directory.

Examples of gnatchop Usage

gnatchop -w hello_s.ada ~gnat/ichibiah/files
Chops the source file `hello_s.ada'. The output files will be placed in the directory `~gnat/ichbiah/files', overwriting any files with matching names in that directory (no files in the current directory are modified).
gnatchop -s -r collect
Chops the source file `collect' into the current directory. A compilation script is also generated, and all output files have Source_Reference pragmas, so error messages will refer back to the file `collect' with proper line numbers.
gnatchop archive
Chops the source file `archive' into the current directory. One useful application of gnatchop is in sending sets of sources around, for example in email messages. The required sources are simply concatenated (for example, using a UNIX cat command), and then gnatchop is used at the other end to reconstitute the original file names.

The Front-end/Cross-Reference Utility gnatf

This chapter discusses gnatf, a stripped-down version of the GNAT compiler containing only the front end. gnatf can preform full syntax and semantic checking and also has a cross-reference analyzer built in that can perform a variety of functions.

Overview of gnatf

The GNAT system provides a stand-alone tool, gnatf, which allows for syntax and semantics checking without any code generation. This is somewhat faster than using gcc -gnatc.

The standard GNAT switches that do not concern code generation are still available in gnatf. However, they should not be proceeded by `-gnat', so to do syntax only checking with gnatf, use gnatf -s ile.adb, not gnatf -gnats file.adb.

The real point of gnatf is that it contains a cross reference tool, whose goals are:

Command Line of gnatf

The gnatf command line is of the following form:

gnatf [switches] files

The effect is similar to a gcc command specifying the `-gnatc' (no code generation) switch, although it is somewhat faster, especially if several files are processed at the same type

Compilation Switches

The following compilation switches are similar to the corresponding switches in gcc, except that the names are not preceded by `-gnat'. For example, the gnatf switch for syntax-only checking is `-s' instead of -gnats. For full details on these switches, see section Switches for gcc.

Generate brief messages to stderr even if verbose mode set
Error messages generated immediately, not saved up till end
Full errors. Multiple errors/line, all undefined references
GNAT style checks enabled
Identifier char set (c=1/2/3/4/8/p/f/n/w)
Wide character encoding method (e=n/h/u/s/e)
Limit file names to n (1-999) character.
Output full source listing with embedded error messages
Limit number of detected errors to n (1-999)
Don't quit, try semantics, even if parse errors
Reference manual column layout required
Syntax check only
Tree output file to be generated
List units for this compilation
Verbose mode. Full error output with source lines to stdout
Warning mode. (m=s/e for suppress/treat as error)
Enforce Ada 83 restrictions

Cross-Referencing Switches

The following list contains the descriptions of the cross-referencing flags available with gnatf:

Issues warnings for unnecessary, misplaced or redundant with clauses. Specifically, a warning message is generated in the following cases:
Issues warnings on unused entities, that is entities that are declared but never used. Note that no warnings are issued for unreferenced entities such as the following:
Generate cross-reference information. The `-x3' switch gives the most succinct cross-referencing information, `-x5' the most comprehensive. The `-x4' switch gives more information than `-x3' but not as much as `-x5'. The information given by switches `-x3' and `-x4' is used in the smart recompilation system currently under development. The `-x5' switch lists all entities defined or used in the analyzed compilation units. It gives the source location of their definition and all their uses in the analyzed units.
The cross-reference output is the same as with `-x5', except that with `-x6', all cross-reference information is stored in the single file `X.ref', and the entity kind of each cross-referenced entity is also given.

Cross Reference Information and Smart Recompilation

The cross reference information gathered by the `-x3' and `-x4' switches is a subset of the information specified by the `-x5' switch. The former information is specifically tailored to the smart recompilation system currently under development. When `-x3' or `-x4' are specified, the cross-referencing tool gnatf produces the following information for each compilation unit analyzed. We refer to that unit as unit in the following list.

File Structure

The cross-referencing file is divided into various sections. There is one section for each compilation unit explicitly requested. We call these units, RUs, for "requested units." There is also one section for each AU, (auxiliary unit); that is, those compilation units that are implicitly loaded by the compiler, but whose compilation has not been explicitly requested by the user. Specs of withed packages are typical AUs.

All entities exported by RUs (the `-x3' and `-x4' switches) or all entities belonging to RUs (the `-x5' and `-x6' switches) appear in the cross-referencing file(s).

However, only the entities defined in AUs that are imported in RUs appear in the cross-referencing file. Their order is the order of declaration in the source files.

The sections in the cross reference referring to RUs and AUs are respectively denoted:

for an RU
for an AU

Note: An entity defined inside a generic and used through a generic instantiation is listed under the cross-referencing section of the generic unit.

Example of gnatf Usage

01 with Part1; -- unused
02 with Part2; use Part2;
03 procedure Test is
05 Thing : Number;
06 type Client is record
07 Number : Integer;
08 State : Boolean;
09 end record;
10 type Color is (Red, Green); -- unused
11 My_Client : Client;
13 begin
14 My_Client.Number := 1;
15 My_Client.State := True;
16 Thing := 20;
17 Thing := Thing + Thing;
18 end;
01 package Part1 is
02 type Useless is new Integer;
03 end;
01 package Part2 is
02 type Number is new Integer range 1 .. 1000;
03 The_Number : constant := 42;
04 end;

The result of invoking gnatf -x5 test.adb is the following (just skim the file `test.xrb', explanations follow:

Warnings on stderr (the screen)
test.adb:1:06: warning: "Part1" withed but unused.  test.adb:3:11:
warning: "Test" unused test.adb:10:09: warning: "Color" unused
01 V "SGNAT v1.0 "
02 test.adb 941012154746 2 3
03 941012154531
04 941012154620
06 %% test.adb
07 test 3:11
08 thing 5:4
09 {16:4 17:4 17:13 17:21}
10 client 6:9
11 {11:16}
12 client.number 7:7
13 {14:14}
14 client.state 8:7
15 {15:14}
16 color 10:9
17 red 10:19
18 green 10:24
19 my_client 11:4
20 {14:4 15:4}
22 --
23 part1 1:9
24 {1:6}
26 --
27 part2 1:9
28 {2:6 2:17}
29 number 2:9
30 {5:14}

The unit Test is the only RU (requested unit). AUs (auxiliary units) are packages Part1 and Part2. First, the graph of the loaded units with their time stamps is given:

02 test.adb 941012154746 2 3
03 941012154531
04 941012154620

Unit Test requires the loading of units Part1 and Part2 (the second and third units listed in the inclusion graph).

The entry

06 %% test.adb
07 [...]
08 thing 5:4 
09 {16:4 17:4 17:13 17:21}

means Thing is an entity (a variable) defined in line 5 column 4; used in line 16 column 4; and in line 17 columns 4, 13, and 21; in file `test.adb'.

The entity Useless may be used in units other than Test, but that information is not contained in the `test.xrb' file because Test does not use Useless.

File Name Krunching With gnatk8

This chapter discusses the gnatk8 file name krunching utility.

About gnatk8

The normal rule in using GNAT is that the file name must be derived from the unit name. The exact default rule is: Take the unit name and replace all dots by hyphens, except that if such a replacement occurs in the second character position of a name, replace the dot by a plus instead of a hyphen.

The `-gnatknn' switch of the compiler activates a "krunching" circuit that limits file names to nn characters (where nn is a decimal integer). This is primarily intended for use on MS-DOS and similar systems where nn=8, to fit in the 8+3 limitation on file names found in these systems.

The gnatk8 utility can be used to determine the krunched name for a given file, when krunched to a specified maximum length.

Using gnatk8

The gnatk8 command has the form

gnatk8 name [length]

name can be an Ada name with dots or the GNAT name of the unit where the dots representing child units or subunit are replaced by hyphens. The only confusion arises if a name ends in `.ads' or `.adb'. gnatk8 takes this to be an extension if there are no other dots in the name and the whole name is in lower case.

length represents the length of the krunched name. The default without any argument given is 8 characters. A length of zero stands for unlimited, in other words no chop except for system files which are always 8.

The output is the kruched name. The output has an extension only if the original argument was a file name with an extension.

Krunching Method

The initial file name is determined by the name of the unit that the file contains. The name is formed by taking the full expanded name of the unit and replacing the separating dots with hyphens and using lower case for all letter, except that a hyphen in the second character position is replaced by a plus sign. The extension is `.ads' for a specification and `.adb' for a body.

Krunching does not affect the extension, but the file name is shorted to the specified length by following these rules:

Of course no file shortening algorithm can guarantee uniqueness over all possible unit names, and if file name krunching is used then it is your responsibility to ensure that no name clashes occur. The utility program gnatk8 is supplied for conveniently determining the krunched name of a file.

Examples of gnatk8 Usage

gnatk8      ---->
gnatk8 6    ---->
gnatk8 0    ---->
gnatk8 ---->
gnatk8 grandparent.parent.child     ----> grparchi

Other Utility Programs

This chapter discusses some other utility programs available in the Ada environment.

Using Other Utility Programs With GNAT

The object files generated by GNAT are in standard system format and in particular the debugging information uses this format. This means programs generated by GNAT can be used with existing utilities that depend on these formats.

In general, any utility program that works with C will also work with Ada programs generated by GNAT. This includes software utilities such as gprof (a profiling program), gdb (the FSF debugger), and utilities such as Purify.

The Naming Scheme of GNAT

In order to interpret the output from GNAT, it is necessary to understand the conventions used to generate link names from the Ada entity names.

All names are in all lower-case letters. With the exception of library procedure names, the mechanism used is simply to use the full expanded Ada name with dots replaced by double underscores. For example, suppose we have the following package spec:

package QRS is MN : Integer; end QRS;

The variable MN has a full expanded Ada name of QRS.MN, so the corresponding link name is qrs__mn.

Of course if a pragma Export is used this may be overridden:

package Exports is
   Var1 : Integer; 
   pragma Export (Var1, C, External_Name => "var1_name"); 
   Var2 : Integer; 
   pragma Export (Var2, C, Link_Name => "var2_link_name"); 
end Exports;

In this case, the link name for Var1 is var1_name, and the link name for Var2 is var2_link_name.

One exception occurs for library level procedures. A potential ambiguity arises between the required name _main for the C main program, and the name we would otherwise assign to an Ada library level procedure called Main (which might well not be the main program).

To avoid this ambiguity, we attach the prefix _ada_ to such names. So if we have a library level procedure such as

procedure Hello (S : String);

the external name of this procedure will be _ada_hello.

Ada Mode for Emacs

In the subdirectory `emacs-ada-mode' you will find a set of files implementing an Ada mode under GNU emacs. The mode is still under development, but a number of features are complete.

For instance, the Ada mode has the same indenting friendliness that C programmers get with the c-mode, you can toggle between specification and body with a few keystrokes, etc. This mode also uses `gnatf' to be able to point to an entity with the mouse, click it and open a window with its definition. This mode is copyrighted by Markus Heritsch and Rolf Ebert.

Running and Debugging Ada Programs

This chapter discusses how to run and debug Ada programs.

Getting Internal Debugging Information

Most compilers have secret internal debugging switches and modes. GNAT does also, except GNAT internal debugging switches and modes are not secret. A summary and full description of all the compiler and binder debug flags are in the file `debug.adb'. You must obtain the sources of the compiler to see the full detailed effects of these flags.

The switches that print the source of the program (reconstructed from the internal tree) are of general interest, as are the options to print the full internal tree, and the entity table (that is the symbol table information).

GNAT Crashes

GNAT may experience problems in operation, such as aborting with a segmentation fault or illegal memory access, raising an internal exception, or terminating abnormally. If such problems occur, try the solutions described in this section.

The following strategies are presented in increasing order of difficulty, corresponding to the user's skill level and curiosity about the functioning of the compiler.

  1. Run gcc with the -gnatf and -gnate switches. The first switch causes all errors on a given line to be reported. In its absence, only the first error on a line is displayed. The `-gnate' switch causes errors to be displayed as soon as they are encountered, rather than after compilation is terminated. Often this is enough to identify the construct that produced the crash.
  2. Run gcc with the `-v' (verbose) switch. In this mode, gcc produces ongoing information about the progress of the compilation and provides the name of each procedure as code is generated. This switch allows you to find which Ada procedure was being compiled when it encountered a code generation problem.
  3. Run gcc with the `-gnatdc' switch. This is a GNAT specific switch that does for the frontend what `-v' does for the backend. The system prints the name of each unit, either a compilation unit or nested unit, as it is being analyzed.
  4. On systems that have gdb available (most UNIX systems), start gdb directly on the gnat1 executable. gnat1 is the front-end of GNAT, and can be run independently (normally it is just called from gcc). You can use gdb on gnat1 as you would on a C program (but see section Using gdb for caveats). The where command is the first line of attack; the variable lineno (seen by print lineno), used by the second phase of gnat1 and by the gcc backend, indicates the source line at which the execution stopped, and input_file name indicates the name of the source file.

Using gdb

gdb awaits modifications to handle Ada properly, and for now can only be used as it would be for a C program. In the meantime, the following naming conventions allow you to find the Ada entities defined in your program:

See section The Naming Scheme of GNAT for more information.

Exceptions can be caught by breaking in the __gnat_raise function and then entering a bt or where command.

Performance Considerations

The GNAT system provides a number of options that allow a trade off between

The defaults if no options are selected are aimed at improving the speed of compilation and minimizing dependences at the expense of performance of the generated code:

These options are suitable for most program development purposes. This chapter describes how you can modify these choises.

Controlling Runtime Checks

By default, GNAT produces all runtime checks except arithmetic overflow checking for integer operations (including division by zero) and checks for access before elaboration on subprogram calls.

Two gnat switches, `-gnatp' and `-gnato' allow this default to be modified. See section Runtime Checks.

Our experience is that the default is suitable for most development purposes.

We treat integer overflow and elaboration checks specially because these are quite expensive and in our experience are not as important as other runtime checks in the development process.

Note that the setting of the switches controls the default setting of the checks. They may be modified using either pragma Suppress (to remove checks) or pragma Unsuppress (to add back suppressed checks) in the program source.

Optimization Levels

The default is optimization off. This results in the fastest compile times, but GNAT makes absolutely no attempt to optimize, and the generated programs are considerably larger and slower. You can use the `-On' switch, where n is an integer from 0 to 3, on the gcc command to control the optimization level:

no optimization (the default)
medium level optimization
full optimization
full optimization, and also attempt automatic inlining of small subprograms within a unit (see section Inlining of Subprograms).

The penalty in compilation time, and the improvement in execution time, both depend on the particular application and the hardware environment. You should experiment to find the best level for your application.

Note: Unlike the case with some other compiler systems, gcc has been tested extensively at all optimization levels. There are some bugs which appear only with optimization turned on, but there have also been bugs which show up only in unoptimized code. Selecting a lower level of optimization does not improve the reliability of the code generator, which in practice is highly reliable at all optimization levels.

Inlining of Subprograms

A call to a subprogram in the current unit is inlined if all the following conditions are met:

Calls to subprograms in with'ed units are normally not inlined. To achieve this level of inlining, the following conditions must all be true:

Note that specifying the `-gnatn' switch causes additional compilation dependencies. Consider the following:

package R is
   procedure Q;
   pragma Inline Q;
end R;
package body R is
end R;
with R;
procedure Main is
end Main;

With the default behavior (no `-gnatn' switch specified), the compilation of the Main procedure depends only on its own source, `main.adb', and the spec of the package in file `'. This means that editing the body of R does not require recompiling Main.

On the other hand, the call R.Q is not inlined under these circumstances. If the `-gnatn' switch is present when Main is compiled, the call will be inlined if the body of Q is small enough, but now Main depends on the body of R in `r.adb' as well as the spec. This means that if the body is edited, the main program must be recompiled. Note that this extra dependency occurs whether or not the call is in fact inlined by gcc.

Note: The gcc switch `-fno-inline' can be used to prevent all inlining. This switch overrides all other conditions and ensures that no inlining occurs. The extra dependencies resulting from `-gnatn' will still be active, even if the `-fno-inline' switch is used.



  • `-a' gnatmake switch
  • `-A' gnatmake switch
  • `-aI' gnatmake switch
  • `-aO' gnatmake switch
  • `-b' binder switch
  • `-B' switch
  • `-b' switch
  • `-bargs' gnatmake switch
  • `-c' binder switch
  • `-c' gnatmake switch
  • `-c' switch
  • `-cargs' gnatmake switch
  • `-e' binder switch
  • `-f' gnatmake switch
  • `-fno-inline' switch
  • `-g' gnatlink swtch
  • `-g' gnatmake switch
  • `-g' switch
  • `-gnat83' switch
  • `-gnata' switch
  • `-gnatb' switch
  • `-gnatc' switch
  • `-gnatd' switch
  • `-gnatdc' switch
  • `-gnate' switch
  • `-gnatf' switch
  • `-gnatg' switch
  • `-gnati' switch
  • `-gnatj' switch
  • `-gnatk' switch
  • `-gnatl' switch
  • `-gnatlink' gnatlink switch
  • `-gnatm' switch
  • `-gnatn' switch, `-gnatn' switch, `-gnatn' switch
  • `-gnato' switch, `-gnato' switch
  • `-gnatp' switch, `-gnatp' switch
  • `-gnatq' switch
  • `-gnatr' switch
  • `-gnats' switch
  • `-gnatt' switch
  • `-gnatu' switch
  • `-gnatv' switch
  • `-gnatwe' switch
  • `-gnatws' switch
  • `-I' gnatmake switch
  • `-I' switch
  • `-I-' gnatmake switch
  • `-j' gnatmake switch
  • `-k' gnatchop switch
  • `-k' gnatmake switch
  • `-l' binder switch
  • `-L' gnatmake switch
  • `-largs' gnatmake switch
  • `-m' binder switch
  • `-M' gnatmake switch
  • `-n' binder switch
  • `-n' gnatmake switch
  • `-o' binder switch
  • `-o' gnatlink switch
  • `-o' gnatmake switch
  • `-o' switch
  • `-O' switch, `-O' switch
  • `-q' gnatmake switch
  • `-r' gnatchop switch
  • `-s' binder switch
  • `-s' gnatchop switch
  • `-S' switch
  • `-t' binder switch
  • `-v' binder switch
  • `-v' gnatlink switch
  • `-v' gnatmake switch
  • `-V' switch
  • `-v' switch
  • `-w' gnatchop switch
  • `-we' binder switch
  • `-ws' binder switch
  • `-Wuninitialized' switch
  • `-x' binder switch
  • `-x6' gnatf switch
  • `-x[345]' gnatf switches
  • _

  • __gnat_finalize
  • __gnat_initialize
  • __gnat_raise
  • __main_priority
  • _main
  • a

  • Access before elaboration
  • ACVC, Ada 83 tests
  • Ada, Ada
  • Ada 83 compatibility
  • Ada Language Reference Manual
  • Ada.Characters.Latin_1
  • Ada.Command_Line
  • Ada.Command_Line.Set_Exit_Status
  • adafinal
  • adainit
  • Annex A
  • Annex B
  • argc
  • argv
  • Assert
  • Assertions
  • b

  • Binder output file
  • Binder, multiple input files
  • Body_Version
  • c

  • Check, overflow
  • Checks, access before elaboration
  • Checks, division by zero
  • Checks, suppressing
  • code page 437
  • code page 850
  • Combining GNAT switches
  • Compilation model
  • Compilation units, unused
  • Conventions
  • CR
  • d

  • Debug
  • Debugging information, including, Debugging information, including
  • Dependencies, producing list
  • Dependency rules
  • Division by zero
  • e

  • Elaborate
  • Elaborate_All
  • Elaborate_Body
  • Elaboration order control
  • End of source file
  • Entites, unused
  • Entities, unused
  • Entities, where defined
  • Error messages, suppressing
  • EUC Coding
  • Export
  • f

  • FF
  • g

  • Generic formal paramaters
  • Generics, Generics
  • GNAT compilation model
  • GNAT library
  • gnat1
  • gnat_argc
  • gnat_argv
  • gnat_exit_status
  • Gnatvsn
  • h

  • HT
  • i

  • Inline, Inline
  • Inlining
  • Interfaces, Interfaces
  • Internal trees, writing to file
  • l

  • Latin-1, Latin-1
  • Latin-2
  • Latin-3
  • Latin-4
  • LF
  • Linker libraries
  • Linker_Option
  • m

  • Machine_Overflows
  • Multiple units, syntax checking
  • n

  • No code generated
  • o

  • Overflow checks, Overflow checks
  • p

  • Parallel make
  • Preelaborate
  • Priority, Priority
  • Pure
  • r

  • Recompilation, by gnatmake
  • Remote_Call_Interface
  • Remote_Types
  • RTL
  • s

  • Search paths, for gnatmake
  • Shared_Passive
  • Shift JIS Coding
  • Source code, listing of generated
  • Source file, end
  • Source files, suppressing search
  • Source files, use by binder
  • Source_Reference
  • Standard, Standard, Standard
  • stderr
  • stdout
  • Stringt
  • Style
  • SUB
  • Subunits
  • Suppress, Suppress
  • Suppressing checks
  • System, System
  • System.IO
  • System.Task_Specific_Data
  • t

  • Time stamp errors, in binder
  • Typographical conventions
  • u

  • Uname
  • Unsuppress, Unsuppress
  • Unused compilation units
  • Unused entities
  • Upper-Half Coding
  • v

  • Version
  • VT
  • w

  • Warning messages
  • Warnings
  • Writing internal trees

  • This document was generated on 6 November 1996 using the texi2html translator version 1.51.