APPENDIX A2: GNAT User's Guide

A2.1.0 About This Guide
A2.1.1 What This Guide Contains
A2.1.2 What You Should Know Before Reading This Guide
A2.1.3 Related Information
A2.1.4 Conventions
A2.2.0 Getting Started With GNAT
A2.2.1 Running GNAT
A2.2.2 Running a Simple Ada Program
A2.2.3 Running a Program With Multiple Units
A2.2.4 Using the gnatmake Utility
A2.3.0 The GNAT Compilation Model
A2.3.1 Source Representation
A2.3.2 Foreign Language Representation
A2.3.2.1 Latin-1
A2.3.2.2 Other 8-Bit Codes
A2.3.3 File Naming Rules
A2.3.4 Naming of GNAT Source Files
A2.3.5 Generating Object Files
A2.3.6 Source Dependencies
A2.3.7 The Ada Library Information
A2.3.8 Representation of Time Stamps Files
A2.3.9 Binding an Ada Program
A2.3.10 Mixed Language Programming
A2.3.11 Comparison of GNAT Model With C/C++ Compilation Model
A2.3.12 Comparison of GNAT Model With Traditional Ada Library Model
A2.4.0 Compiling Ada Programs With gcc
A2.4.1 Compiling Programs
A2.4.2 Switches for gcc
A2.4.3 Switches for GNAT
A2.4.3.1 Error Message Control
A2.4.3.2 Debugging and Assertion Control
A2.4.3.3 Runtime Checks
A2.4.3.4 Using gcc for Syntax Checking
A2.4.3.5 Using gcc for Semantic Checking
A2.4.3.6 Compiling Ada 83 Programs
A2.4.3.7 Style Checking
A2.4.3.8 Character Set Control
A2.4.3.9 File Naming Control
A2.4.3.10 Subprogram Inlining Control
A2.4.3.11 Auxiliary Output Control
A2.4.3.12 Debugging Control
A2.4.4 Search Paths and the Run-Time Library (RTL)
A2.4.5 Order of Compilation Issues
A2.4.6 Examples
Appendix A2 continues...


APPENDIX A


Documentation Supplement for GNAT
Part 2: GNAT User's Guide

(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.

A2.1.0 About This Guide

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


A2.1.1 What This Guide Contains

This guide contains the following chapters:

A2.1.2 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.


A2.1.3 Related Information

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

A2.1.4 Conventions

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

A2.2.0 Getting Started With GNAT

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


A2.2.1 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.

A2.2.2 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
begin
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 compile 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
or
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
./hello
and, if all has gone well, you will see
Hello WORLD!
appear in response to this command.


A2.2.3 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
   begin
      Put_Line ("Hello WORLD!");
   end Hello;
   procedure Goodbye is
   begin
      Put_Line ("Goodbye WORLD!");
   end Goodbye;
end Greetings;

with Greetings;
procedure Gmain is
begin
   Greetings.Hello;
   Greetings.Goodbye;
end Gmain;
Following the one-unit-per-file rule, prepare this program in the following three separate files:
'greetings.ads'
spec of package Greetings
'greetings.adb'
body of package Greetings
'gmain.adb'
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 'greetings.ads'. 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 greetings.ads
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.


A2.2.4 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 preceding case, if you edit 'gmain.adb', you only need recompile that file. But if you edit 'greetings.ads', you must recompile both 'greetings.adb' and 'gmain.adb', since both files contain units that depend on 'greetings.ads'.

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'.


A2.3.0 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 are described and discussed. If you have used other Ada compilers, you may find this section helps you to understand those differences.


A2.3.1 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 "3.2 Foreign Language Representation" for support of non-USA character sets). The format effector characters are represented using their standard ASCII encodings, as follows:

VT Vertical tab 16#0B#
HT Horizontal tab 16#09#
CR Carriage return 16#0D#
LF Line feed 16#0A#
FF 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.


A2.3.2 Foreign Language Representation

GNAT supports the standard character sets defined in Ada 95:

A2.3.2.1 Latin-1

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 'a-chlat1.ads'.

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.

A2.3.2.2 Other 8-Bit Codes

GNAT also supports several other 8-bit coding schemes:

Latin-2
Latin-2 letters allowed in identifiers, with uppercase and lowercase equivalence.
Latin-3
Latin-3 letters allowed in identifiers, with uppercase and lower case equivalence.
Latin-4
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.

A2.3.3 File Naming Rules

The filename 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.ads'
Main (spec)
'main.adb'
Main (body)
'arith_functions.ads'
Arith_Functions (package spec)
'arith_functions.adb'
Arith_Functions (package body)
'func-spec.ads'
Func.Spec (child package spec)
'func-spec.adb'
Func.Spec (child package body)
'main-sub.adb'
Sub (subunit of Main)

Following these rules can result in very long filenames 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 filenames (called filename "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 filename lengths. See section "A2.10.2 Using gnatk8"

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


A2.3.4 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:

A2.3.5 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 preceding 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 of this 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.


A2.3.6 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.


A2.3.7 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 'gnatvsn.ads'. 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:

EB Unit has pragma Elaborate_Body.
NE 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.
PK Unit is a package, rather than a subprogram.
PU Unit has pragma Pure.
PR Unit has pragma Preelaborate.
RC Unit has pragma Remote_Call_Interface.
RT Unit has pragma Remote_Types.
SP Unit has pragma Shared_Passive.
SU 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 filename 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 filename 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 'stringt.ads'. 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.


A2.3.8 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:

YY year (2 low order digits)
MM month (2 digits 01-12)
DD day (2 digits 01-31)
HH hour (2 digits 00-23)
MM minutes (2 digits 00-59)
SS 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.


A2.3.9 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.


A2.3.10 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.


A2.3.11 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.


A2.3.12 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.


A2.4.0 Compiling Ada Programs With gcc

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


A2.4.1 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] filename
where filename 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 the gcc manual, 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 filenames 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.


A2.4.2 Switches for gcc

The gcc command accepts numerous switches. The following are the ones you will 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.
'-Bdir'
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.
'-c'
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.
'-g[options]'
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.
'-Idir'
Direct GNAT to search the dir directory for source files needed by the current compilation (see section "A2.4.4 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.
'-O[n]'
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 "A2.4.3.10 Subprogram Inlining Control" for details on control of inter-unit inlining.
'-S'
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.
'-v'
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.
'-Wuninitialized'
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.


A2.4.3 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.

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


You may combine a sequence of GNAT switches into a single switch. For example, the specifying the switch
-gnatcfi3
is equivalent to specifying the following sequence of switches:
-gnatc -gnatf -gnati3

A2.4.3.1 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 filename 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:

'-gnatv'
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.

'-gnatl'
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.    funcion 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.
'-gnatb'
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.

'-gnatmn'
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
'-gnatf'
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
'-gnatq'
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.
'-gnate'
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 "A2.12.2 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:


'-gnatwe' 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.
'-gnatws' The 's' stands for suppress. This switch completely suppress the output of all warning messages.


A2.4.3.2 Debugging and Assertion Control

'-gnata'
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.


A2.4.3.3 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:

'-gnatp'
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.
'-gnato'
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.


A2.4.3.4 Using gcc for Syntax Checking

'-gnats'
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 "A2.8.0 Handling Files With Multiple Units With gnatchop").



A2.4.3.5 Using gcc for Semantic Checking

'-gnatc'
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).



A2.4.3.6 Compiling Ada 83 Programs

'-gnat83'
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.



A2.4.3.7 Style Checking

'-gnatr'
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.
'-gnatg'
Enforces a set of style conventions that correspond to the style used in the GNAT source code. All compiler units are always compiled 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.



A2.4.3.8 Character Set Control

'-gnatic' 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:
'1'Latin-1 identifiers
'2'Latin-2 letters allowed in identifiers
'3'Latin-3 letters allowed in identifiers
'4'Latin-4 letters allowed in identifiers
'p'IBM PC letters (code page 437) allowed in identifiers
'8'IBM PC letters (code page 850) allowed in identifiers
'f'Full upper-half codes allowed in identifiers
'n'No upper-half codes allowed in identifiers
'w'Wide-character codes allowed in identifiers
See section "A2.3.2 Foreign Language Representation" for full details on the implementation of these character sets.
'-gnatje' Specify the method of encoding for wide characters. e is one of the following:
'n'No wide characters allowed (default setting)
'h'Hex encoding
'u'Upper half encoding
's'Shift/JIS encoding
'e' EUC encoding

A2.4.3.9 File Naming Control

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



A2.4.3.10 Subprogram Inlining Control

'-gnatn'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 "A2.13.3 Inlining of Subprograms" for further details on when inlining is possible.



A2.4.3.11 Auxiliary Output Control

'-gnatt'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.
'-gnatu'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.

A2.4.3.12 Debugging Control

'-gnatdx'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.
target^(source)A conversion with floating-point truncation instead of rounding.
target?(source)A conversion that bypasses normal Ada semantic checking. In particular enumeration types and fixed-point types are treated simply as integers.
target?^(source)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 itypeReference (and hence definition) to internal type itype.
function-name! (arg, arg, arg)Intrinsic function call.
labelname : labelDeclaration of label labelname.
expr && expr && expr ... && exprA multiple concatenation (same effect as expr & expr & expr, but handled more efficiently).
[constraint_error]Raise the Constraint_Error exception.
expression'referenceA pointer to the result of evaluating expression.
target-type!(source-expression)An unchecked conversion of source-expression to target-type.
[numerator/denominator]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).

A2.4.4 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 filename 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_SOURCE_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.


A2.4.5 Order of Compilation Issues

If, in our earlier example, there were a spec for the hello procedure, it would be contained in the file 'hello.ads'; 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.


A2.4.6 Examples

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.


[ Top of Page ][ A2.5.0 Binding Ada Programs With gnatbind ][ Table of Contents ]