(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.
This guide describes the language itself, as well as the various utilities that allow you to manipulate GNAT code.
This guide contains the following chapters:
gcc
, describes how to compile
Ada programs with gcc
, the Ada compiler.
gnatbind
, describes how to
perform binding in Ada programs with gnatbind
, the GNAT binding
utility.
gnatlink
, describes gnatlink, a
program that provides for linking using the GNAT runtime library to
construct a program consisting of a mix of Ada and C sources.
gnatmake
, describes gnatmake
, a
utility that automatically determines and compiles the set of sources
needed by an Ada compilation unit.
gnatchop
, describes
gnatchop
, a utility that allows you to preprocess a file and
split it into several other files, one for each compilation unit.
gnatf
, discusses
gnatf
, a modified version of the GNAT compiler.
gnatk8
, describes the gnatk8
filename krunching utility.
gnatk8
and gnatf
. This chapter also contains
information on cross references, smart recompilation, and
cross-reference file structure.
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.
For further information about related tools, refer to the following documents:
Following are examples of the typographical and graphic conventions used in this guide:
Functions
, utility program names
, standard names
,
and classes
.
and then shown this way.
This chapter describes the usual ways of using GNAT to compile Ada programs.
Three steps are needed to create an executable file from an Ada source file:
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 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
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.
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:
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.
gnatmake
UtilityAs 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 `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'.
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.
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:
VT
HT
CR
LF
FF
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.
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
`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.
GNAT also supports several other 8-bit coding schemes:
ESC a b c dWhere
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.
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.
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 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.
If you want to examine the workings of the GNAT system, the following brief description of its organization may be helpful:
Ada
, as
defined in Annex A.
Interfaces
, as
defined in Annex B.
System
. This includes
both language-defined children and GNAT runtime routines).
GNAT
. These are useful
general-purpose packages, fully documented in their specifications. All
the other `.c' files are modifications of common gcc
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.
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:
with
's a unit X, the object file
depends on the file containing the spec of unit X. This includes
files that are with
'ed implicitly either because they are parents
of with
'ed child units or they are runtime units required by the
language constructs used in a particular unit.
pragma Inline
applies and inlining is activated with the
`-gnatn' switch, the object file depends on the file containing the
body of this subprogram as well as on the file containing the spec.
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.
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
NE
NE
set, depending on whether or not elaboration code is required.
PK
PU
pragma Pure
.
PR
pragma Preelaborate
.
RC
pragma Remote_Call_Interface
.
RT
pragma Remote_Types
.
SP
pragma Shared_Passive
.
SU
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.
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:
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.
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.
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:
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.
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.
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:
with
'ed, the unit seen by the compiler corresponds
to the version of the unit most recently compiled into the library.
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:
with
'ed, the unit seen by the compiler corresponds
to the source version of the unit that is currently accessible to the
compiler.
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.
gcc
This chapter discusses how to compile Ada program and the switches passed to the compiler.
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 compler) 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.
gcc
The gcc
command accepts numerous switches. The following are the
ones you wil most likely need. Note that these switches are case
sensitive.
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.
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.
gcc
manual for more details.
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.
gcc
driver. Normally used only for
debugging purposes or if you need to be sure what version of the
compiler you are executing.
gcc
version, not the GNAT version.
Many additional gcc
switches are relevant. They are fully
described in the gcc
manual.
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
Pragma Assert
and pragma Debug
to be
activated.
-gnatb
stderr
even if verbose mode set.
-gnatc
-gnate
-gnatf
-gnatg
-gnatic
-gnatje
-gnatkn
-gnatl
-gnatmn
-gnatn
-gnato
-gnatp
-gnatq
-gnatr
-gnats
-gnatt
-gnatu
-gnatv
stdout
.
-gnatwm
-gnatzm
-gnat83
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
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:
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.
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.
stdout
as well as the verbose
format message or full listing.
e.adb:3:04: Incorrect spelling of keyword "function" e.adb:5:35: missing ".." fatal error: maximum errors reached compilation abandoned
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 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:
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.
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:
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.
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.
gcc
for Syntax Checkinggcc -c -gnats x.adbcompiles 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
).
gcc
for Semantic Checking<>
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.
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.
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
.
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.
stdout
.
The listing includes all units on which the unit being compiled depends
either directly or indirectly.
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]
at end procedure-name;
(if expr then expr else expr)
x?y:z
construction in C.
target^(source)
target?(source)
target?^(source)
x #/ y
x #mod y
x #* y
x #rem y
free expr [storage_pool = xxx]
free
statement.
freeze typename [actions]
reference itype
function-name! (arg, arg, arg)
labelname : label
expr && expr && expr ... && expr
[constraint_error]
Constraint_Error
exception.
expression'reference
target-type!(source-expression)
[numerator/denominator]
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 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:
gcc
command line, in the order given.
ADA_SOURCE_PATH
environment variable. Construct this value
exactly as the PATH
environment variable: a list of directory
names separated by colons.
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.
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:
with
's, all its subunits, and the bodies of any generics it
instantiates must be available (findable by the search-paths mechanism
described above), or you will receive a fatal error message.
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
gcc -c -O2 -gnata xyz-def.adb
pragma
Assert
/Debug
statements
enabled.
gcc -c -gnatc abc-def.adb
gnatbind
This chapter describes the GNAT binder, gnatbind
, which is used
to bind compiled GNAT objects. The gnatbind
program performs
four separate functions:
gnatlink
utility used to link the Ada application.
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
`pack.ads', it attempts to locate the source file `pack.ads'
(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 `p.ads' and you perform the following
steps:
gcc -c hello.adb
to compile the main program.
gcc -c p.ads
to compile package p
.
gnatbind hello.ali
.
At this point, the file `p.ali' contains an out-of-date time stamp since the file `p.ads' has been edited. The attempt at binding fails, and the binder generates the following error messages:
error: "hello.adb" must be recompiled ("p.ads" has been modified) error: "p.ads" 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:
int __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; __gnat_initialize(); system__task_specific_data___elabb (); p___elabs (); _ada_hello (); __gnat_finalize(); 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 /usr/local/adainclude/system.o /usr/local/adainclude/s-stoele.o /usr/local/adainclude/s-taspda.o /usr/local/adainclude/s-tasoli.o /usr/local/adainclude/s-stalib.o p.o hello.o 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.
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:
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.
The following switches provide control over the generation of error messages from the binder:
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.
stderr
even if verbose mode is
specified. This is relevant only when used together with the `-v'
switch.
The following switches allow additional control over the output generated by the binder.
stdout
.
stdout
.
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:
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:
adainit
adainit
is
required before the first call to an Ada subprogram.
adafinal
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.
The following are the switches available with gnatbind
:
stderr
even if verbose mode set.
stdout
.
You may obtain this listing by running the program gnatbind
with
no arguments.
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.
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:
gnatbind
command line, in the order given.
ADA_OBJECTS_PATH
environment variable. Construct this value the
same as the PATH
environment variable: a list of directory names
separated by colons.
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_SOURCE_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.
gnatbind
Usage
This section contains a number of examples of using the GNAT binding
utility gnatbind
.
gnatbind hello.ali
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
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
gnatbind -n math.ali dbase.ali -o ada-control.c
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.
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.
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.
gnatlink
The following switches are available with the gnatlink
utility:
gnatlink try.ali
creates
an executable called `try'.
gnatmake
A typical development cycle when working on an Ada program consists of the following steps:
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
.
gnatmake
The gnatmake
command has the form
gnatmake [-a] [-c] [-f] [-g] [-jn] [-k] [-M] [-o exec-name] [-n] [-q] [-v] [compiler_switch] {-Adir} {-aOdir} {-aIdir} {-Idir} {-I-} {-Ldir} unit_or_file_name {-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:
gnatmake
unit
).
gnatmake
file.adb
).
All gnatmake
output (except when you specifiy `-M') is to
stderr
. The output produced by the `-M' switch is send to
stdout
.
gnatmake
You may specify any of the following switches to gnatmake
:
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
.
gnatmake
will attempt binding and linking
unless all objects are up to date and the executable is more recent than
the objects.
-cargs -g
.
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'.
gnatmake
terminates.
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.
gnatmake
halts and
displays an error message.
gnatmake
are displayed.
gnatmake
decides are necessary.
gcc
switches'
gcc
(e.g. `-O', `-gnato,' etc.)
Source & Library search path switches:
General compiler, binder or linker switches:
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
.
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.
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.
Please note the following with regard to gnatmake
:
gnatmake file.adb
, where `file.adb'
is a subunit or body of a generic unit, gnatmake
recompiles
`file.adb' (because it finds no ALI) and stops, issuing a
warning.
gnatmake
does not examine `.o' files, only ALI files.
Deleting `.o' files will not force a recompile. You can force
everything to be recompiled either by deleting the ALI files or by using
the `-f' switch.
gnatmake
finds no ALI files, it recompiles the main program
and all other units required by the main program. Thus gnatmake
can be used for the initial compile, as well as during the re-edit
development cycle.
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.
gnatmake
Usagegnatmake hello.adb
Hello
) and bind and link the
resulting object files to generate an executable file `hello'.
gnatmake -q Main_Unit -cargs -O2 -bargs -l
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.
gnatchop
This chapter discusses how to handle files with multiple units by using
the gnatchop
utility.
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 filenames. 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 filenames 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.
gnatchop
The gnatchop
command has the form:
gnatchop [-k] [-r] [-s] [-w] filename [directory]
The only required argument is the filename of the file to be chopped. There are no restrictions on the form of this filename. 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 begin Put_Line ("Hello"); end hello;
the command
gnatchop hellofiles
generates two files in the current directory, one called `hello.ads' 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.
gnatchop
gnachop
recognizes the following switches:
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 filename 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.
gcc
commands to compile the generated files.
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.
gnatchop
Usagegnatchop -w hello_s.ada ~gnat/ichibiah/files
gnatchop -s -r collect
Source_Reference
pragmas, so error messages will refer back to
the file `collect' with proper line numbers.
gnatchop archive
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.
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.
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:
emacs
mode contained in the GNAT distribution.
with
clause is unnecessary, misplaced or redundant.
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
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
.
stderr
even if verbose mode set
The following list contains the descriptions of the cross-referencing
flags available with gnatf
:
with
clauses. Specifically, a warning message is generated in the following
cases:
with
'ed but never used (this works
with child library units as well).
with
'ed in a body (responsible
subunit) if the same with
clause already appears in the
specification (responsible specification or body for subunits).
with
'ed within a specification but is
used only by the body or a subunit.
for i in Color'First .. Color'Last
for I in 1 .. 80 loop Put (`x'); end loop;
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.
with
'ed unit graph rooted at unit and also
other units automatically loaded by GNAT during code generation (generic
bodies, subunits, and bodies of inlined subprograms).
gnatf
considers only outermost visible entities to be exported.
That is, a record or enumeration type may be exported, but its inner
fields or enumeration literals are never considered exported entities.
It is the same for subprogram parameters and discriminants.
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:
%% unit.ad[sb]
-- unit.ad[sb]
Note: An entity defined inside a generic and used through a generic instantiation is listed under the cross-referencing section of the generic unit.
gnatf
Usage01 with Part1; -- unused 02 with Part2; use Part2; 03 procedure Test is 04 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; 12 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:
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 part1.ads 941012154531 04 part2.ads 941012154620 05 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} 21 22 -- part1.ads 23 part1 1:9 24 {1:6} 25 26 -- part2.ads 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 part1.ads 941012154531 04 part2.ads 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
.
gnatk8
This chapter discusses the gnatk8
filename krunching utility.
gnatk8
The normal rule in using GNAT is that the filename 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 filenames 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 filenames 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.
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 filename with an extension.
The initial filename 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 filename is shorted to the specified length by following these rules:
our-strings-wide_fixed 22 our strings wide fixed 19 our string wide fixed 18 our stri wide fixed 17 our stri wide fixed 16 our stri wide fixe 14 our str wide fixe 14 our str wid fixe 13 our str wid fix 12 ou str wid fix 11 ou st wid fix 10 ou st wi fix 9 ou st wi fi 8 Final filename: oustwifi.adb
ada-strings-wide_fixed 22 a- strings wide fixed 18 a- string wide fixed 17 a- strin wide fixed 16 a- stri wide fixed 15 a- stri wide fixe 14 a- str wide fixe 13 a- str wid fixe 12 a- str wid fix 11 a- st wid fix 10 a- st wi fix 9 a- st wi fi 8 Final filename: a-stwifx.adb
Of course no file shortening algorithm can guarantee uniqueness over all
possible unit names, and if filename 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.
gnatk8
Usagegnatk8 very_long_unit_name.ads ----> velounna.ads gnatk8 very_long_unit_name.ads 6 ----> vlunna.ads gnatk8 very_long_unit_name.ads 0 ----> long_unit_name.ads gnatk8 grandparent-parent-child.ads ----> grparchi.ads gnatk8 grandparent.parent.child ----> grparchi
This chapter discusses some other utility programs available in the Ada environment.
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.
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.
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.
This chapter discusses how to run and debug Ada programs.
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 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.
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.
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.
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.
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_filename
indicates the name of
the source file.
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:
package_name__subprogram_name
. Note the double underscores
separating package name from subprogram name.
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.
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 documentation describes how you can modify these choises.
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.
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:
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.
A call to a subprogram in the current unit is inlined if all the following conditions are met:
gcc
cannot support in inlined subprograms.
pragma Inline
applies to the subprogram or it is very
small and automatic inlining (optimization level `-O3') is
specified.
Calls to subprograms in with
'ed units are normally not inlined.
To achieve this level of inlining, the following conditions must all be
true:
gcc
cannot
support in inlined subprograms.
pragma Inline
for the subprogram.
gcc
command line
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 begin ... R.Q; 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 `r.ads'. 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.