Appendix A2 continues...
A2.5.0 Binding Ada Programs With gnatbind
A2.5.1 Running gnatbind
A2.5.2 Consistency-Checking Modes
A2.5.3 Error-Message Control
A2.5.4 Output Control
A2.5.5 Binding for Non-Ada Main Programs
A2.5.6 Summary of Binder Switches
A2.5.7 Command-Line Access
A2.5.8 Search Paths for gnatbind
A2.5.9 Examples of gnatbind Usage
A2.6.0 Linking Ada Programs Using gnatlink
A2.6.1 Running gnatlink
A2.6.2 Switches for gnatlink
A2.7.0 The GNAT Make Program gnatmake
A2.7.1 Running gnatmake
A2.7.2 Switches for gnatmake
A2.7.3 Notes on the Command Line
A2.7.4 How gnatmake Works
A2.7.5 Examples of gnatmake Usage
A2.8.0 Handling Files With Multiple Units With
gnatchop
A2.8.1 Handling Files With Multiple
Units
A2.8.2 Command Line for gnatchop
A2.8.3 Switches for gnatchop
A2.8.4 Examples of gnatchop Usage
A2.9.0 The Front-End/Cross-Reference Utility gnatf
A2.9.1 Overview of gnatf
A2.9.2 Command Line of gnatf
A2.9.3 Compilation Switches
A2.9.4 Cross-Referencing Switches
A2.9.5 Cross Reference Information and Smart
Recompilation
A2.9.6 File Structure
A2.9.7 Example of gnatf Usage
A2.10.0 Filename Krunching With gnatk8
A2.10.1 About gnatk8
A2.10.2 Using gnatk8
A2.10.3 Krunching Method
A2.10.4 Examples of gnatk8 Usage
A2.11.0 Other Utility Programs
A2.11.1 Using Other Utility Programs
With GNAT
A2.11.2 The Naming Scheme of GNAT
A2.11.3 Ada Mode for Emacs
A2.12.0 Running and Debugging Ada Programs
A2.12.1 Getting Internal Debugging Information
A2.12.2 GNAT Crashes
A2.12.3 Using gdb
A2.13.0 Performance Considerations
A2.13.1 Controlling Runtime Checks
A2.13.2 Optimization Levels
A2.13.3 Inlining of Subprograms
A2.5.0 Binding Ada Programs With gnatbind
This chapter describes the GNAT binder, gnatbind, which is used
to bind compiled GNAT objects. The gnatbind program performs four
separate functions:
- Checks that a program is consistent, in accordance with the rules
in Chapter 10 of the Ada Language Reference Manual. In particular, error
messages are generated if a program uses inconsistent versions of a given
unit.
- Checks that an acceptable order of elaboration exists for the program
and issues an error message if it cannot find an order of elaboration satisfying
the rules in Chapter 10 of the Ada Language Reference Manual.
- Generates a main program incorporating the given elaboration order.
This program is a small C source file that must be subsequently compiled
using the C compiler. The two most important functions of this program are
to call the elaboration routines of units in an appropriate order and to
call the main program.
- Determines the set of object files required by the given main program.
This information is output as comments in the generated C program, to be
read by the gnatlink utility used to link the Ada application.
A2.5.1 Running gnatbind
The form of the gnatbind command is:
gnatbind [switches] mainprog.ali [switches]
where mainprog.adb is the Ada file containing the main program
unit body. If no switches are specified, gnatbind constructs a
C file whose name is 'b_mainprog.c'. For example, if given the
parameter 'hello.ali', for a main program contained in file 'hello.adb',
the binder output file would be 'b_hello.c'.
When doing consistency checking, the binder takes any source files it can
locate into consideration. For example, if the binder determines that the
given main program requires the package Pack, whose ALI file is
'pack.ali' and whose corresponding source spec file is '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:
- Enter gcc -c hello.adb to compile the main program.
- Enter gcc -c p.ads to compile package p.
- Edit file 'p.ads'.
- Enter 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.
A2.5.2 Consistency-Checking Modes
As described in the previous section, by default gnatbind checks
that object files are consistent with one another and are consistent with
any source files it can locate. The following switches can be used to modify
this behavior:
'-s'
| Require source files to be present. In this mode, the binder insists
on being able to locate all source files that are referenced and checks
their consistency. In normal mode, if a source file cannot be located it
is simply ignored. If you specify the '-s' switch, a missing source
file is an error.
|
'-x'
| Exclude source files. In this mode, the binder only checks that ALI
files are consistent with one another. Source files are not accessed. The
binder runs faster in this mode, and there is still a guarantee that the
resulting program is self-consistent. If a source file has been edited since
it was last compiled and you specify the '-x' switch, the binder
will not detect that the object file is out of date with the source file. |
For most purposes the default mode is appropriate, and this is the mode
that is normally used when gnatmake or gnatbind is used
to do the bind operation.
A2.5.3 Error-Message Control
The following switches provide control over the generation of error messages
from the binder:
'-v'
| Verbose mode. In the normal mode, brief error messages are generated
to stderr. If the '-v' switch is present, a header is written to
stdout and any error messages are directed to stdout. All that is written
to stderr is a brief summary message.
|
'-b' | Generate brief error messages to
stderr even if verbose mode is specified. This is relevant only
when used together with the '-v' switch.
|
'-mn' | Limits the number of error messages
to n, a decimal integer in the range 1-999. The binder terminates
immediately if this limit is reached.
|
'-ws' | Suppress all warning messages
|
'-we' | Treat any warning messages as fatal errors
|
'-t | Ignore time stamp errors. Any time stamp error
messages are treated as warning messages. This switch essentially disconnects
the normal consistency checking, and the resulting program may have undefined
semantics if inconsistent units are present. This means that '-t'
should be used only in unusual situations, with extreme care. |
A2.5.4 Output Control
The following switches allow additional control over the output generated
by the binder.
'-e'
| Output complete list of elaboration-order dependencies, showing the
reason for each dependency. This output can be rather extensive but may
be useful in diagnosing problems with elaboration order. The output is written
to stdout.
|
'-l' | Output chosen elaboration order.
The output is written to stdout.
|
'-o file' | Set name of output file to file
instead of the normal 'b_prog.c' default. You would normally give
file an extension of '.c' since it will be a C source program.
|
'-c' | Check only. Do not generate the binder
output file. In this mode the binder performs all error checks but does
not generate an output file. |
A2.5.5 Binding for Non-Ada Main Programs
In our description in this chapter so far we have assumed the main program
is in Ada and the task of the binder is to generate a corresponding function
main to pass control to this Ada main program. GNAT also supports the building
of executable programs where the main program is not in Ada, but some of
the called routines are written in Ada and compiled using GNAT. The following
switch is used in this situation:
'-n'
| No main program. The main program is not in Ada. |
In this case, most of the functions of the binder are still required,
but instead of generating a main program, the binder generates a file containing
the following callable routines:
adainit
| You must call this routine to initialize the Ada part of the program
by calling the necessary elaboration routines. A call to adainit
is required before the first call to an Ada subprogram.
|
adafinal | You must call this routine to
perform any library-level finalization required by the Ada subprograms.
A call to adafinal is required after the last call to an Ada subprogram,
and before the program terminates. |
If the '-n' switch is given, more than one ALI file may appear
on the command line for gnatbind. The normal closure calculation
is performed for each of the specified units. Calculating the closure means
finding out the set of units involved by tracing with references.
The reason it is necessary to be able to specify more than one ALI file
is that a given program may invoke two or more quite separate groups of
Ada subprograms.
The binder takes the name of its output file from the first specified ALI
file, unless overridden by the use of the '-o' switch. It will
be a C source file, which must be compiled using the C compiler.
A2.5.6 Summary of Binder Switches
The following are the switches available with gnatbind:
'-b'
| Generate brief messages to stderr even if verbose mode set.
|
'-c' | Check only, no generation of binder
output file.
|
'-e' | Output complete list of elaboration-order
dependencies.
|
'-I' | Specify directory to be searched
for source and ALI files.
|
'-l' | Output-chosen elaboration order.
|
'-mn' | Limit number of detected errors
to n (1-999).
|
'-n' | No main program.
|
'-o file' | Name the output file
(default is 'b_xxx.c').
|
'-s' | Require all source files to be present.
|
'-t' | Ignore time-stamp errors.
|
'-v' | Verbose mode. Write error messages,
header, summary output to stdout.
|
'-wx' | Warning mode (x=s/e for
suppress/treat as error)
|
'-x' | Exclude source files (check object
consistency only |
You may obtain this listing by running the program gnatbind
with no arguments.
A2.5.7 Command-Line Access
The package Ada.Command_Line provides access to the command-line
arguments and program name. In order for this interface to operate correctly,
the two variables
int gnat_argc;
char **gnat_argv;
are declared in one of the GNAT library routines. These variables must be
set from the actual argc and argv values passed to the
main program. With no '-n' switch present, gnatbind generates
the C main program to automatically set these variables. If the '-n'
switch is used, there is no automatic way to set these variables. If they
are not set, the procedures in Ada.Command_Line will not be available,
and any attempt to use them will raise Constraint_Error. If command
line access is required, your main program must set gnat_argc and
gnat_argv from the argc and argv values passed
to it.
A2.5.8 Search Paths for gnatbind
The binder must be able to find both the ALI files and the source files.
For source files, it follows exactly the same search rules as gcc
(see section "A2.4.4 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:
- The current working directory.
- All directories specified by '-I' switches on the gnatbind
command line, in the order given.
- Each of the directories listed in the value of the ADA_OBJECTS_PATH
environment variable. Construct this value the same as the PATH
environment variable; a list of directory names separated by colons.
- The default location for the GNAT Run-Time Library (RTL) files, determined
when GNAT was built and installed on your system.
For source files accessed by the binder, the search procedure is as described
above for object files, except that in step 3 the environment variable ADA_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.
A2.5.9 Examples of gnatbind Usage
This section contains a number of examples of using the GNAT binding utility
gnatbind.
gnatbind
hello.ali
|
| The main program Hello (source program
in 'hello.adb') is bound using the standard switch settings. The
generated main program is 'b_hello.c'. This is the normal, default
use of the binder.
|
gnatbind main_program.ali -o mainprog.c
-x -e
|
| The main program Main_Program (source
program in 'main_program.adb') is bound, excluding source files
from the consistency checking. A full list of elaboration dependencies is
output to stdout, and the file 'mainprog.c' is generated
|
gnatbind -xe main_program.ali -o mainprog.c
|
| This command is exactly the same as the previous
example. Switches may appear anywhere in the command line, and single letter
switches may be combined into a single switch.
|
gnatbind -n math.ali dbase.ali -o ada-control.c
|
| The main program is in a language other than
Ada, but calls to subprograms in packages Math and Dbase
appear. This call to gnatbind generates the file 'ada-control.c'
containing the adainit and adafinal routines to be called
before and after accessing the Ada subprograms. |
A2.6.0 Linking Ada Programs Using gnatlink
This chapter discusses gnatlink, a utility program used to link
Ada programs and build an executable file. This program is basically a simple
process which invokes the Unix linker (via the gcc command) with
a correct list of object files and library references. gnatlink
automatically determines the list of files and references for the Ada part
of a program. It uses the binder file generated by the binder to determine
this list.
A2.6.1 Running gnatlink
The form of the gnatlink command is
gnatlink [switches] mainprog[.ali] [non-Ada
objects] [linker options]
'mainprog.ali' references the ALI file of the main program. The
'.ali' extension of this file can be omitted. From this reference,
gnatlink locates the corresponding binder file 'b_mainprog.c' and,
using the information in this file along with the list of non-Ada objects
and linker options, constructs a Unix linker command file to create the
executable.
The arguments following 'mainprog.ali' are passed to the linker
uninterpreted. They typically include the names of object files for units
written in other languages than Ada and any library references required
to resolve references in any of these foreign language units, or in pragma
Import statements in any Ada units. This list may also include linker
switches.
gnatlink determines the list of objects required by the Ada program
and prepends them to the list of objects passed to the linker. gnatlink
also gathers any arguments set by the use of pragma Linker_Options
and adds them to the list of arguments presented to the linker.
A2.6.2 Switches for gnatlink
The following switches are available with the gnatlink utility:
'-o
exec-name' | exec-name specifies an alternative name for
the generated executable program. If the '-o' switch is omitted, the executable
is called the name of the main unit. So gnatlink try.ali creates
an executable called 'try'.
|
'-v' | Causes additional information to
be output, including a full list of the included object files. This switch
option is most useful when you want to see what set of object files are
being used in the link step.
|
'-g' | The option to include debugging information
causes the C bind file (in other words, 'b_mainprog.c') to be compiled
with '-g'. In addition, the binder does not delete the 'b_mainprog.c'
and 'b_mainprog.o' files (without '-g', the binder removes
these files by default).
|
'-gnatlink name' | name is the
name of the linker to be invoked. You normally omit this switch, in which
case the default name for the linker is ('gcc'). |
A2.7.0 The GNAT Make Program gnatmake
A typical development cycle when working on an Ada program consists of the
following steps:
- Edit some sources to fix bugs.
- Add enhancements.
- Compile all sources affected.
- Rebind and relink.
- Test.
The third step can be tricky, because not only do the modified files have
to be compiled, but any files depending on these files must also be recompiled.
The dependency rules in Ada can be quite complex, especially in the presence
of overloading, use clauses, generics and inlined subprograms.
gnatmake automatically takes care of the third and fourth steps
of this process. It determines which sources need to be compiled, compiles
them, and binds and links the resulting object files.
Unlike some other Ada make programs, the dependencies are always accurately
recomputed from the new sources. The source based approach of the GNAT compilation
model makes this possible. This means that if changes to the source program
cause corresponding changes in dependencies, they will always be tracked
exactly correctly by gnatmake.
A2.7.1 Running 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:
- By giving the lowercase name of the compilation unit (gnatmake
unit).
- By giving the name of the source containing it (gnatmake file.adb).
All gnatmake output (except when you specify '-M') is
to stderr. The output produced by the '-M' switch is send
to stdout.
A2.7.2 Switches for gnatmake
You may specify any of the following switches to gnatmake:
'-a'
| Consider all files in the make process, even the GNAT internal system
files (for example, the predefined Ada library files). By default, gnatmake
does not check these files (however, if there is an installation problem,
it will be caught when gnatmake binds your program). You may have
to specify this switch if you are working on GNAT itself. The vast majority
of gnatmake users never need to specify this switch. By default
gnatmake -a compiles all GNAT internal files with gcc -c -gnatg
rather than gcc -c.
|
'-c' | Compile only. Do not perform binding
and linking. If the root unit specified by unit_or_file_name is
not a main unit, this is the default. Otherwise gnatmake will attempt
binding and linking unless all objects are up to date and the executable
is more recent than the objects.
|
'-f' | Force recompilations. Recompile all
sources, even though some object files may be up to date, but don't recompile
predefined or GNAT internal files unless the '-a' switch is also
specified.
|
'-g' | Compile with debugging information.
Same effect as -cargs -g.
|
'-jn' | Use n processes to carry
out the (re)compilations. If you have a multiprocessor machine, compilations
will occur in parallel. In the event of compilation errors, messages from
various compilations might get interspersed (but gnatmake will
give you the full ordered list of failing compiles at the end). This can
at times be annoying. To get a clean list of error messages don't use '-j'.
|
'-k' | Keep going. Continue as much as possible
after a compilation error. To ease the programmers's take in case of compilation
errors, the list of sources for which the compile fails is given when gnatmake
terminates.
|
'-M' | Check if all objects are up to date.
If they are output the object dependences to stdout in a form that can be
directly exploited in a 'Makefile'. By default, each source file
is prefixed with its (relative or absolute) directory name. This name is
whatever you specified in the various '-aI' and '-I' switches.
If you use gnatmake -M -q (see '-q' below), only the source
file names, without relative paths, are output. If you just specify the
'-M' switch, dependencies of the GNAT internal system files are omitted.
This is typically what you want. If you also specify the ' T' 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.
|
'-n' | Don't compile, bind, or link. Output
a single command that will recompile an out of date unit, if any. Repeated
use of this option, followed by carrying out the indicated compilation,
will eventually result in recompiling all required units. If any ALI is
missing during the process, gnatmake halts and displays an error message.
|
'-o exec_name' | Output executable name.
The name of the final executable program will be exec_name. If
the '-o' switch is omitted the default name for the executable
will be the name of the input file without the suffix (Unix systems) or
the name of the input file with an '.exe' extension (DOS and OS/2).
You may prefix exec_name with a relative or absolute directory
path.
|
'-q' | Quiet. When this flag is not set,
the commands carried out by gnatmake are displayed.
|
'-v' | Verbose. Displays the reason for
all recompilations gnatmake decides are necessary.
|
'gcc switches' | The switch '-g'
or any upper case switch (other than '-A', or '-L') or
switch that is more than one character is passed to gcc (e.g. '-O',
'-gnato,' etc.) |
Source & Library search path switches:
'-Adir'
| Equivalent to '-aLdir -aIdir'.
|
'-aOdir' | When looking for library and
object files look also in directory dir. The order in which library
files search is undertaken is described in section "A2.4.4
Search Paths and the Run-Time Library (RTL)".
|
'-aIdir' | When looking for source files
also look in directory dir.
|
'-Idir' | Equivalent to '-aOdir -aIdir'.
|
'-I-' | Do not look for source, library
or object files in the default directory.
|
'-Lvar' | Add directory dir to
the list of directories in which the linker will search for libraries. This
is equivalent to '-largs -Ldir'. |
General compiler, binder or linker switches:
'-cargs
options' | Compiler arguments. Without '-cargs', gnatmake
uses gcc -c to perform compilations. Otherwise, gnatmake
uses gcc -c c_opts, where c_opts is a list of parameters
including all the options encountered in the set of '-cargs' switches
present on the gnatmake command line. A given sublist of '-cargs'
options is terminated upon encountering another '-cargs', '-bargs'
or '-largs'. By default, gnatmake -a compiles all GNAT
internal files with gcc -c -gnatg rather than gcc -c.
|
'-bargs options' | Binder arguments. Without
'-bargs', gnatmake uses gnatbind unit.ali to
bind. Otherwise, gnatmake uses gnatbind b_opts unit.ali.
b_opts is akin to c_opts, but is obtained from '-bargs'
switches. '-largs options'. Similar to '-bargs', but specifies
the options for gnatlink. Note that you are not allowed to use
the '-o' switch within a '-largs'. Use the '-o'
switch directly to gnatmake to give a specific name to your executable. |
A2.7.3 Notes on the Command Line
Please note the following with regard to gnatmake:
- If you enter 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.
- If 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.
A2.7.4 How gnatmake Works
Generally gnatmake automatically performs all necessary recompilations
and you don't need to worry about how it works. However, it may be useful
to have some basic understanding of the gnatmake approach and in particular
to understand how it uses the results of previous compilations without incorrectly
depending on them.
First a definition: an object file is considered up to date
if the corresponding ALI file exists and if all the source files listed
in the dependency section of this ALI file have time stamps matching those
in the ALI file. This means that neither the source file itself nor any
files that it depends on have been modified, and hence there is no need
to recompile this file.
gnatmake works by first checking if the specified main program
is up to date. If so, it is done, and no compilations are required. If not,
it compiles the main program to build a new ALI file that reflects the latest
sources. It examines this ALI file to find all the source files on which
the main program depends, and recursively applies the up to date test on
all these files.
This process ensures that gnatmake only trusts the dependencies
in an existing ALI file if they are known to be correct. Otherwise it always
recompiles to determine a new, guaranteed accurate set of dependencies.
Thus the program is compiled "upside down" from what may be more
familiar as the required order of compilation in some other Ada systems.
In particular, clients are compiled before the units on which they depend.
The ability of GNAT to compile in any order is critical in allowing an order
of compilation to be chosen that guarantees that gnatmake will
recompute a correct set of new dependencies if necessary.
A2.7.5 Examples of gnatmake Usage
gnatmake
hello.adb
|
| Compile all files necessary to bind and link
the main program 'hello.adb' (containing unit Hello) and bind and
link the resulting object files to generate an executable file 'hello'.
|
gnatmake -q Main_Unit -cargs -O2 -bargs
-l
|
| Compile all files necessary to bind and link
the main program unit Main_Unit (from file 'main_unit.adb').
All compilations will be done with optimization level 2 and the order of
elaboration will be listed by the binder. gnatmake will operate
in quiet mode, not displaying commands it is executing. |
A2.8.0 Handling Files With Multiple Units With gnatchop
This chapter discusses how to handle files with multiple units by using
the gnatchop utility.
A2.8.1 Handling Files With Multiple Units
The basic compilation model of GNAT requires a file submitted to the compiler
have only one unit and there must be a strict correspondence between the
file name and the unit name.
The gnatchop utility allows both of these rules to be relaxed,
allowing GNAT to process files which contain multiple compilation units
and files with arbitrary 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.
A2.8.2 Command Line for 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.
A2.8.3 Switches for gnatchop
gnatchop recognizes the following switches:
'-k'
| Limit generated filenames to eight characters. This is useful if the
resulting set of files is required to be interoperable with systems like
MS-DOS which limit the length of filenames.
|
'-r' | Generate Source_Reference
pragmas. Use this switch if the output files are regarded as temporary and
development is to be done in terms of the original unchopped file. The '-r'
switch causes Source_Reference pragmas to be inserted into each
of the generated files to refers back to the original 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.
|
'-s' | Write a compilation script to standard
output containing gcc commands to compile the generated files.
|
'-w' | Overwrite existing filenames. Normally
gnatchop regards it as a fatal error situation if there is already
a file with the same name as a file it would otherwise output. The '-w'
switch bypasses this check, and any such existing files will be silently
overwritten. |
directory, if specified, gives the name of the directory to
which the output files will be written. If it is not specified, all files
are written to the current directory.
A2.8.4 Examples of gnatchop Usage
gnatchop
-w hello_s.ada ~gnat/ichibiah/files
|
| Chops the source file 'hello_s.ada'.
The output files will be placed in the directory '~gnat/ichibiah/files',
overwriting any files with matching names in that directory (no files in
the current directory are modified).
|
gnatchop -s -r collect
|
| Chops the source file 'collect'
into the current directory. A compilation script is also generated, and
all output files have Source_Reference pragmas, so error messages
will refer back to the file 'collect' with proper line numbers.
|
gnatchop archive
|
| Chops the source file 'archive'
into the current directory. One useful application of gnatchop
is in sending sets of sources around, for example in email messages. The
required sources are simply concatenated (for example, using a Unix cat
command), and then gnatchop is used at the other end to reconstitute the
original file names. |
A2.9.0 The Front-End/Cross-Reference Utility gnatf
This chapter discusses gnatf, a stripped-down version of the GNAT
compiler containing only the front end. gnatf can preform full
syntax and semantic checking and also has a cross-reference analyzer built
in that can perform a variety of functions.
A2.9.1 Overview of gnatf
The GNAT system provides a stand-alone tool, gnatf, which allows
for syntax and semantics checking without any code generation. This is somewhat
faster than using gcc -gnatc.
The standard GNAT switches that do not concern code generation are still
available in gnatf. However, they should not be proceeded by '-gnat',
so to do syntax only checking with gnatf, use gnatf -s file.adb,
not gnatf -gnats file.adb.
The real point of gnatf is that it contains a cross reference tool,
whose goals are:
- Giving precise information about all declared entities (where they
are defined and where they are used). This is particularly useful in the
Ada emacs mode contained in the GNAT distribution.
- Emitting warnings if an entity is defined but never used or a with
clause is unnecessary, misplaced or redundant.
A2.9.2 Command Line of gnatf
The gnatf command line is of the following form:
gnatf [switches] files
The effect is similar to a gcc command specifying the '-gnatc'
(no code generation) switch, although it is somewhat faster, especially
if several files are processed at the same type.
A2.9.3 Compilation Switches
The following compilation switches are similar to the corresponding switches
in gcc, except that the names are not preceded by '-gnat'.
For example, the gnatf switch for syntax-only checking is '-s'
instead of -gnats. For full details on these switches, see section
"A2.4.2 Switches for gcc"
'-b'
| Generate brief messages to stderr even if verbose mode set
|
'-e' | Error messages generated immediately,
not saved up till end
|
'-f' | Full errors. Multiple errors/line,
all undefined references
|
'-g' | GNAT style checks enabled
|
'-ic' | Identifier char set (c=1/2/3/4/8/p/f/n/w)
|
'-je' | Wide character encoding method (e=n/h/u/s/e)
|
'-kn' | Limit file names to n (1-999)
character.
|
'-l' | Output full source listing with embedded
error messages
|
'-mn' | Limit number of detected errors
to n (1-999)
|
'-q' | Don't quit, try semantics, even if
parse errors
|
'-r' | Reference manual column layout required
|
'-s' | Syntax check only
|
'-t' | Tree output file to be generated
|
'-u' | List units for this compilation
|
'-v' | Verbose mode. Full error output with
source lines to stdout
|
'-wm' | Warning mode. (m=s/e for
suppress/treat as error)
|
'-83' | Enforce Ada 83 restrictions |
A2.9.4 Cross-Referencing Switches
The following list contains the descriptions of the cross-referencing flags
available with gnatf:
'-x1' | Issues
warnings for unnecessary, misplaced or redundant with clauses. Specifically,
a warning message is generated in the following cases:
- A compilation unit which is with'ed but never used (this
works with child library units as well).
- A compilation unit that is with'ed in a body (responsible
subunit) if the same with clause already appears in the specification
(responsible specification or body for subunits).
- A compilation unit that is with'ed within a specification
but is used only by the body or a subunit.
|
'-x2' | Issues warnings on unused entities,
that is entities that are declared but never used. Note that no warnings
are issued for unreferenced entities such as the following:
- Record fields, since they could be referenced indirectly by an aggregate.
- Enumeration entities, since they could be referenced indirectly by
enumeration ranges:
for i in Color'First .. Color'Last
- Loop parameters:
for I in 1 .. 80 loop
Put ('x');
end loop;
|
'-x[345]' | Generate cross-reference information.
The '-x3' switch gives the most succinct cross-referencing information,
'-x5' the most comprehensive. The '-x4' switch gives more
information than '-x3' but not as much as '-x5'. The information
given by switches '-x3' and '-x4' is used in the smart
recompilation system currently under development. The '-x5' switch
lists all entities defined or used in the analyzed compilation units. It
gives the source location of their definition and all their uses in the
analyzed units.
|
'-x6' | The cross-reference output is the
same as with '-x5', except that with '-x6', all cross-reference
information is stored in the single file 'X.ref', and the entity
kind of each cross-referenced entity is also given. |
A2.9.5 Cross Reference Information and Smart Recompilation
The cross reference information gathered by the '-x3' and '-x4'
switches is a subset of the information specified by the '-x5'
switch. The former information is specifically tailored to the smart recompilation
system currently under development. When '-x3' or '-x4'
are specified, the cross-referencing tool gnatf produces the following
information for each compilation unit analyzed. We refer to that unit as
unit in the following list.
- The full graph of the source files, directly or indirectly loaded
as a result of compiling Unit along with their time stamp. This graph includes
the 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).
- The list of entities that can be exported from unit to other
Ada sources along with their line and column of definition and use in unit.
If unit is a subprogram or package specification, the notion of
exported entity matches the set of entities listed therein. If unit
is a package body with no generics or inlined subprograms, then no entities
are exported. In general, however, the set of entities exported from unit
is the set of entities that are needed across compilation units by gnat
when generating code. Specifically inlined subprogram bodies or generic
bodies are always exported, since these are inlined at the point of use
or instantiation. The same happens for subunits, which are inlined in the
parent unit. The difference between the '-x3' and '-x4'
switches is that '-x3' omits all generic bodies or inlined subprograms
from the exported entities, while '-x4' includes them. Both '-x3'
and '-x4' consider subunits as exported entities. 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 list of entities directly imported by unit from other
Ada sources, along with their lines and columns where they are used in unit.
The idea of imported entities is derived from the notion of exported entities
(what is exported by one unit may be imported by another).
A2.9.6 File Structure
The cross-referencing file is divided into various sections. There is one
section for each compilation unit explicitly requested. We call these units,
RUs, for "requested units." There is also one section for each
AU, (auxiliary unit); that is, those compilation units that are implicitly
loaded by the compiler, but whose compilation has not been explicitly requested
by the user. Specs of withed packages are typical AUs.
All entities exported by RUs (the '-x3' and '-x4' switches)
or all entities belonging to RUs (the '-x5' and '-x6'
switches) appear in the cross-referencing file(s).
However, only the entities defined in AUs that are imported in RUs appear
in the cross-referencing file. Their order is the order of declaration in
the source files.
The sections in the cross reference referring to RUs and AUs are respectively
denoted:
%% unit.ad[sb]
for an RU
-- unit.ad[sb]
for an AU
Note: An entity defined inside a generic and used through
a generic instantiation is listed under the cross-referencing section of
the generic unit.
A2.9.7 Example of gnatf Usage
'test.adb'
01 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;
'part1.ads'
01 package Part1 is
02 type Useless is new Integer;
03 end;
'part2.ads'
01 package Part2 is
02 type Number is new Integer range 1 .. 1000;
03 The_Number : constant := 42;
04 end;
The result of invoking gnatf -x5 test.adb is the following (just
skim the file 'test.xrb', explanations follow:
Warnings on stderr (the screen):
test.adb:1:06: warning: "Part1" withed but unused. test.adb:3:11:
warning: "Test" unused test.adb:10:09: warning: "Color" unused
'test.xrb'
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.
A2.10.0 Filename Krunching With gnatk8
This chapter discusses the gnatk8 filename krunching utility.
A2.10.1 About 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.
A2.10.2 Using gnatk8
The gnatk8 command has the form:
gnatk8 name [length]
name can be an Ada name with dots or the GNAT name of the unit
where the dots representing child units or subunit are replaced by hyphens.
The only confusion arises if a name ends in '.ads' or '.adb'.
gnatk8 takes this to be an extension if there are no other dots
in the name and the whole name is in lower case.
length represents the length of the krunched name. The default
without any argument given is 8 characters. A length of zero stands for
unlimited, in other words no chop except for system files which are always
8.
The output is the krunched name. The output has an extension only if the
original argument was a filename with an extension.
A2.10.3 Krunching Method
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 shortened to
the specified length by following these rules:
- The name is divided into segments separated by minus or plus signs
and underscores and all hyphens, plus signs, and underscores are eliminated.
If this leaves the name short enough, we are done.
- If not the longest segment is located (left-most if there are two
of equal length), and shortened by dropping its last character. This is
repeated until the name is short enough. As an example, consider the krunch
of 'our-strings-wide_fixed.adb' to fit the name into 8 characters
as required by MS-DOS:
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
- The filenames for all predefined units are always krunched to eight
characters. The krunching of these predefined units uses the following special
prefix replacements:
'ada-' replaced by 'a-'
'gnat-' replaced by 'g-'
'interfaces-'replaced by 'i-'
'system-' replaced by 's-'
These system files have a hyphen in the second character position. That
is why normal user files replace such a character with a plus sign, to avoid
confusion with system filenames. As an example of this special rule, consider
'ada-strings-wide_fixed.adb', which gets krunched as follows:
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.
A2.10.4 Examples of gnatk8 Usage
gnatk8 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
A2.11.0 Other Utility Programs
This chapter discusses some other utility programs available in the Ada
environment.
A2.11.1 Using Other Utility Programs With GNAT
The object files generated by GNAT are in standard system format and in
particular the debugging information uses this format. This means programs
generated by GNAT can be used with existing utilities that depend on these
formats.
In general, any utility program that works with C will also work with Ada
programs generated by GNAT. This includes software utilities such as gprof
(a profiling program), gdb (the FSF debugger), and utilities such
as Purify.
A2.11.2 The Naming Scheme of GNAT
In order to interpret the output from GNAT, it is necessary to understand
the conventions used to generate link names from the Ada entity names.
All names are in all lower-case letters. With the exception of library procedure
names, the mechanism used is simply to use the full expanded Ada name with
dots replaced by double underscores. For example, suppose we have the following
package spec:
package QRS is MN : Integer; end QRS;
The variable MN has a full expanded Ada name of QRS.MN, so the
corresponding link name is qrs__mn.
Of course if a pragma Export is used this may be overridden:
package Exports is
Var1 : Integer;
pragma Export (Var1, C, External_Name => "var1_name");
Var2 : Integer;
pragma Export (Var2, C, Link_Name => "var2_link_name");
end Exports;
In this case, the link name for Var1 is var1_name, and
the link name for Var2 is var2_link_name.
One exception occurs for library level procedures. A potential ambiguity
arises between the required name _main for the C main program,
and the name we would otherwise assign to an Ada library level procedure
called Main (which might well not be the main program).
To avoid this ambiguity, we attach the prefix _ada_ to such names.
So if we have a library level procedure such as
procedure Hello (S : String);
the external name of this procedure will be _ada_hello.
A2.11.3 Ada Mode for Emacs
In the subdirectory 'emacs-ada-mode' you will find a set of files
implementing an Ada mode under GNU emacs. The mode is still under development,
but a number of features are complete.
For instance, the Ada mode has the same indenting friendliness that C programmers
get with the c-mode, you can toggle between specification and body with
a few keystrokes, etc. This mode also uses 'gnatf' to be able to
point to an entity with the mouse, click it and open a window with its definition.
This mode is copyrighted by Markus Heritsch and Rolf Ebert.
A2.12.0 Running and Debugging Ada Programs
This chapter discusses how to run and debug Ada programs.
A2.12.1 Getting Internal Debugging Information
Most compilers have secret internal debugging switches and modes. GNAT does
also, except GNAT internal debugging switches and modes are not secret.
A summary and full description of all the compiler and binder debug flags
are in the file 'debug.adb'. You must obtain the sources of the
compiler to see the full detailed effects of these flags.
The switches that print the source of the program (reconstructed from the
internal tree) are of general interest, as are the options to print the
full internal tree, and the entity table (that is the symbol table information).
A2.12.2 GNAT Crashes
GNAT may experience problems in operation, such as aborting with a segmentation
fault or illegal memory access, raising an internal exception, or terminating
abnormally. If such problems occur, try the solutions described in this
section.
The following strategies are presented in increasing order of difficulty,
corresponding to the user's skill level and curiosity about the functioning
of the compiler.
- Run gcc with the -gnatf and -gnate switches.
The first switch causes all errors on a given line to be reported. In its
absence, only the first error on a line is displayed. The '-gnate'
switch causes errors to be displayed as soon as they are encountered, rather
than after compilation is terminated. Often this is enough to identify the
construct that produced the crash.
- Run gcc with the '-v' (verbose) switch. In this
mode, gcc produces ongoing information about the progress of the
compilation and provides the name of each procedure as code is generated.
This switch allows you to find which Ada procedure was being compiled when
it encountered a code generation problem.
- Run gcc with the '-gnatdc' switch. This is a GNAT
specific switch that does for the frontend what '-v' does for the
backend. The system prints the name of each unit, either a compilation unit
or nested unit, as it is being analyzed.
- On systems that have gdb available (most Unix systems), start
gdb directly on the gnat1 executable. gnat1 is
the front-end of GNAT, and can be run independently (normally it is just
called from gcc). You can use gdb on gnat1 as
you would on a C program (but see section "A2.12.3
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.
A2.12.3 Using gdb
gdb awaits modifications to handle Ada properly, and for now can
only be used as it would be for a C program. In the meantime, the following
naming conventions allow you to find the Ada entities defined in your program:
- The names of all entities (variables, subprograms, and so on) are
converted to lowercase letters.
- Entities in library package declarations have the form package_name__subprogram_name.
Note the double underscores separating package name from subprogram name.
See section "A2.11.2 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.
A2.13.0 Performance Considerations
The GNAT system provides a number of options that allow a trade off between
- performance of the generated code;
- speed of compilation;
- minimization of dependencies and recompilation;
- and the degree of runtime checking.
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:
- no optimization
- no inlining of subprogram calls
- all runtime checks enabled except overflow and elaboration checks
These options are suitable for most program development purposes. This chapter
documentation describes how you can modify these choices.
A2.13.1 Controlling Runtime Checks
By default, GNAT produces all runtime checks except arithmetic overflow
checking for integer operations (including division by zero) and checks
for access before elaboration on subprogram calls.
Two gnat switches, '-gnatp' and '-gnato' allow
this default to be modified. See section "A2.4.3.3
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.
A2.13.2 Optimization Levels
The default is optimization off. This results in the fastest compile times,
but GNAT makes absolutely no attempt to optimize, and the generated programs
are considerably larger and slower. You can use the '-On' switch,
where n is an integer from 0 to 3, on the gcc command to control the optimization
level:
'-O0'
| no optimization (the default)
|
'-O1' | medium level optimization
|
'-O2' | full optimization
|
'-O3' | full optimization, and also attempt
automatic inlining of small subprograms within a unit (see section "A2.13.3
Inlining of Subprograms"). |
The penalty in compilation time, and the improvement in execution time,
both depend on the particular application and the hardware environment.
You should experiment to find the best level for your application.
Note: Unlike the case with some other compiler systems,
gcc has been tested extensively at all optimization levels. There
are some bugs which appear only with optimization turned on, but there have
also been bugs which show up only in unoptimized code. Selecting
a lower level of optimization does not improve the reliability of the code
generator, which in practice is highly reliable at all optimization levels.
A2.13.3 Inlining of Subprograms
A call to a subprogram in the current unit is inlined if all the following
conditions are met:
- The optimization level is at least '-O1'.
- The called subprogram is suitable for inlining: It must be small enough
and not contain nested subprograms or anything else that gcc cannot support
in inlined subprograms.
- The call occurs after the definition of the body of the subprogram.
- Either 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:
- The optimization level is at least '-O1'.
- The called subprogram is suitable for inlining: It must be small enough
and not contain nested subprograms or anything else gcc cannot
support in inlined subprograms.
- The call appears in a body (not in a package spec).
- There is a pragma Inline for the subprogram.
- The '-gnatn' switch is used in the 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.
[ Top of Page ][ Appendix
B ][ Table of Contents ]