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

4. Binding Using gnatbind

4.1 Running gnatbind  
4.2 Consistency-Checking Modes  
4.3 Binder Error Message Control  
4.4 Elaboration Control  
4.5 Output Control  
4.6 Binding with Non-Ada Main Programs  
4.7 Binding Programs with no Main Subprogram  
4.8 Summary of Binder Switches  
4.9 Command-Line Access  
4.10 Search Paths for gnatbind  
4.11 Examples of gnatbind Usage  

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

  1. Checks that a program is consistent, in accordance with the rules in Chapter 10 of the Ada 95 Reference Manual. In particular, error messages are generated if a program uses inconsistent versions of a given unit.

  2. Checks that an acceptable order of elaboration exists for the program and issues an error message if it cannot find an order of elaboration that satisfies the rules in Chapter 10 of the Ada 95 Language Manual.

  3. Generates a main program incorporating the given elaboration order. This program is a small C source file that must be subsequently compiled using the C compiler. The two most important functions of this program are to call the elaboration routines of units in an appropriate order and to call the main program.

  4. Determines the set of object files required by the given main program. This information is output in the forms of comments in the generated C program, to be read by the gnatlink utility used to link the Ada application.


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

4.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 an Ada package in two files whose names are `b~ada_main.ads', and `b~ada_main.adb'. For example, if given the parameter `hello.ali', for a main program contained in file `hello.adb', the binder output files would be `b~hello.ads' and `b~hello.adb'.

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 gnatgcc command). If it can locate this source file, it checks that the time stamps or source checksums of the source and its references to in `ali' files match. In other words, any `ali' files that mentions this spec must have resulted from compiling this version of the source file (or in the case where the source checksums match, a version close enough that the difference does not matter).

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 by 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:

  1. Enter gnatgcc -c hello.adb to compile the main program.

  2. Enter gnatgcc -c p.ads to compile package P.

  3. Edit file `p.ads'.

  4. Enter gnatbind hello.

At this point, the file `p.ali' contains an out-of-date time stamp because 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 (when using -C):

 
extern int gnat_argc;
extern char **gnat_argv;
extern char **gnat_envp;
extern int gnat_exit_status;
void adafinal ();
void adainit ()
{
   __gnat_set_globals (
      -1,    /* Main_Priority              */
      -1,    /* Time_Slice_Value           */
      ' ',   /* Locking_Policy             */
      ' ',   /* Queuing_Policy             */
      ' ',   /* Tasking_Dispatching_Policy */
      adafinal);
   system___elabs ();
/* system__standard_library___elabs (); */
/* system__task_specific_data___elabs (); */
/* system__tasking_soft_links___elabs (); */
   system__tasking_soft_links___elabb ();
/* system__task_specific_data___elabb (); */
/* system__standard_library___elabb (); */
/* m___elabb (); */
}
void adafinal () {
}
int main (argc, argv, envp)
    int argc;
    char **argv;
    char **envp;
{
   gnat_argc = argc;
   gnat_argv = argv;
   gnat_envp = envp;

   __gnat_initialize();
   adainit();

   _ada_m ();

   adafinal();
   __gnat_finalize();
   exit (gnat_exit_status);
}
unsigned mB = 0x2B0EB17F;
unsigned system__standard_libraryB = 0x0122ED49;
unsigned system__standard_libraryS = 0x79B018CE;
unsigned systemS = 0x08FBDA7E;
unsigned system__task_specific_dataB = 0x6CC7367B;
unsigned system__task_specific_dataS = 0x47178527;
unsigned system__tasking_soft_linksB = 0x5A75A73C;
unsigned system__tasking_soft_linksS = 0x3012AFCB;
/* BEGIN Object file/option list
./system.o
./s-tasoli.o
./s-taspda.o
./s-stalib.o
./m.o
   END Object file/option list */

The call to __gnat_set_globals establishes program parameters, including the priority of the main task, and parameters for tasking control. It also passes the address of the finalization routine so that it can be called at the end of program execution.

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 xxx___elabb and xxx___elabs perform necessary elaboration of the bodies and specs respectively of units in the program. These calls are commented out if the unit in question has no elaboration code.

The call to m 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 the full names of all the object files that must be linked to provide 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 run-time unit files. The latter are omitted if the corresponding units reside in shared libraries. The directory names for the run-time units depend on the system configuration. See section 4.5 Output Control.


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

4.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 control binder access to sources.

-s
Require source files to be present. In this mode, the binder must be able to locate all source files that are referenced, in order to check their consistency. In normal mode, if a source file cannot be located it is simply ignored. If you specify this 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 this switch, the binder will not detect that the object file is out of date with respect to the source file. Note that this is the mode that is automatically used by gnatmake because in this case the checking against sources has already been performed by gnatmake in the course of compilation (i.e. before binding).


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

4.3 Binder 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 this 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 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.

-Mxxx
Renames the generated main program from main to xxx. This is useful in the case of some cross-building environments, where the actual main program is separate from the one generated by gnatbind.

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


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

4.4 Elaboration Control

The following switches provide additional control over the elaboration order. For full details see See section 9. Elaboration Order Handling in GNAT.

-f
Instructs the binder to ignore directives from the compiler about implied Elaborate_All pragmas, and to use full Ada 95 Reference Manual semantics in an attempt to find a legal elaboration order, even if it seems likely that this order will cause an elaboration exception.

-p
Normally the binder attempts to choose an elaboration order that is likely to minimize the likelihood of an elaboration order error resulting in raising a Program_Error exception. This switch reverses the action of the binder, and requests that it deliberately choose an order that is likely to maximize the likelihood of an elaboration error. This is useful in ensuring portability and avoiding dependence on accidental fortuitous elaboration ordering.


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

4.5 Output Control

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

-A
Generate binder program in Ada (default). The binder program is named `b~mainprog.adb' by default. This can be changed with -o gnatbind option.

-C
Generate binder program in C. The binder program is named `b_mainprog.c'. This can be changed with -o gnatbind option.

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

-h
Output usage information. The output is written to stdout.

-l
Output chosen elaboration order. The output is written to stdout.

-O
Output full names of all the object files that must be linked to provide the Ada component of the program. The output is written to stdout. This list includes the files explicitly supplied and referenced by the user as well as implicitly referenced run-time unit files. The latter are omitted if the corresponding units reside in shared libraries. The directory names for the run-time units depend on the system configuration.

-o file
Set name of output file to file instead of the normal `b~mainprog.adb' default. Note that file denote the Ada binder generated body filename. In C mode you would normally give file an extension of `.c' because it will be a C source program. Note that if this option is used, then linking must be done manually. It is not possible to use gnatlink in this case, since it cannot locate the binder file.

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


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

4.6 Binding with Non-Ada Main Programs

In our description so far we have assumed that the main program is in Ada, and that the task of the binder is to generate a corresponding function main that invokes 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 (see section 2.10 Mixed Language Programming). 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 units.

The binder takes the name of its output file from the last specified ALI file, unless overridden by the use of the \-o file\/OUTPUT=file\. The output is an Ada unit in source form that can be compiled with GNAT unless the -C switch is used in which case the output is a C source file, which must be compiled using the C compiler. This compilation occurs automatically as part of the gnatlink processing.


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

4.7 Binding Programs with no Main Subprogram

It is possible to have an Ada program which does not have a main subprogram. This program will call the elaboration routines of all the packages, then the finalization routines.

The following switch is used to bind programs organized in this manner:

-z
Normally the binder checks that the unit name given on the command line corresponds to a suitable main subprogram. When this switch is used, a list of ALI files can be given, and the execution of the program consists of elaboration of these units in an appropriate order.


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

4.8 Summary of Binder Switches

The following are the switches available with gnatbind:

-aO
Specify directory to be searched for ALI files.

-aI
Specify directory to be searched for source file.

-A
Generate binder program in Ada (default)

-b
Generate brief messages to stderr even if verbose mode set.

-c
Check only, no generation of binder output file.

-C
Generate binder program in C

-e
Output complete list of elaboration-order dependencies.

-E
Store tracebacks in exception occurrences when the target supports it. This is the default with the zero cost exception mechanism. This option is currently only supported on Solaris and Linux where you explicitly need to use the gnatgcc flag -funwind-tables when compiling every file in your application. See also the packages GNAT.Traceback and GNAT.Traceback.Symbolic

-f
Full elaboration semantics. Follow Ada rules. No attempt to be kind

-h
Output usage (help) information

-I
Specify directory to be searched for source and ALI files.

-I-
Do not look for sources in the current directory where gnatbind was invoked, and do not look for ALI files in the directory containing the ALI file named in the gnatbind command line.

-l
Output chosen elaboration order.

-Mxyz
Rename generated main program from main to xyz

-mn
Limit number of detected errors to n (1-999).

-n
No main program.

-nostdinc
Do not look for sources in the system default directory.

-nostdlib
Do not look for library files in the system default directory.

-o file
Name the output file file (default is `b~xxx.adb'). Note that if this option is used, then linking must be done manually, gnatlink cannot be used.

-O
Output object list.

-p
Pessimistic (worst-case) elaboration order

-s
Require all source files to be present.

-static
Link against a static GNAT run time.

-shared
Link against a shared GNAT run time when available.

-t
Tolerate time stamp and other consistency errors

-Tn
Set the time slice value to n milliseconds. A value of zero means no time slicing and also indicates to the tasking run time to match as close as possible to the annex D requirements of the RM.

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

-z
No main subprogram.

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


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

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


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

4.10 Search Paths for gnatbind

The binder takes the name of an ALI file as its argument and needs to locate source files as well as other ALI files to verify object consistency.

For source files, it follows exactly the same search rules as gnatgcc (see section 3.3 Search Paths and the Run-Time Library (RTL)). For ALI files the directories searched are:

  1. The directory containing the ALI file named in the command line, unless the switch -I- is specified.

  2. All directories specified by -I switches on the gnatbind command line, in the order given.

  3. Each of the directories listed in the value of the ADA_OBJECTS_PATH environment variable. Construct this value exactly as the PATH environment variable: a list of directory names separated by colons.

  4. The default location for the GNAT Run-Time Library (RTL) files, determined when GNAT was built and installed on your system, unless the switch -nostdlib is specified.

In the binder the switch -I is used to specify both source and library file paths. Use -aI instead if you want to specify source paths only, and -aO if you want to specify library paths only. This means that for the binder -Idir is equivalent to -aIdir -aOdir. 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 simplifying access to the RTL, a major use of search paths is in compiling sources from multiple directories. This can make development environments much more flexible.


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

4.11 Examples of gnatbind Usage

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

gnatbind hello
The main program Hello (source program in `hello.adb') is bound using the standard switch settings. The generated main program is `b~hello.adb'. This is the normal, default use of the binder.

gnatbind hello -o mainprog.adb
The main program Hello (source program in `hello.adb') is bound using the standard switch settings. The generated main program is `mainprog.adb' with the associated spec in `mainprog.ads'. Note that you must specify the body here not the spec, in the case where the output is in Ada. Note that if this option is used, then linking must be done manually, since gnatlink will not be able to find the generated file.

gnatbind main -C -o mainprog.c -x
The main program Main (source program in `main.adb') is bound, excluding source files from the consistency checking, generating the file `mainprog.c'.

gnatbind -x main_program -C -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 dbase -C -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 units.


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

This document was generated by Tom Bennet on August, 25 2000 using texi2html