[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This chapter describes some simple ways of using GNAT to build
executable Ada programs.
1.1 Running GNAT, through 1.4 Using the gnatmake
Utility,
show how to use the command line environment.
1.6 Introduction to Glide and GVD, provides a brief
introduction to the visually-oriented IDE for GNAT.
Supplementing Glide on some platforms is GPS, the
GNAT Programming System, which offers a richer graphical
"look and feel", enhanced configurability, support for
development in other programming language, comprehensive
browsing features, and many other capabilities.
For information on GPS please refer to
Using the GNAT Programming System.
1.1 Running GNAT 1.2 Running a Simple Ada Program 1.3 Running a Program with Multiple Units 1.4 Using the gnatmake
Utility1.5 Introduction to GPS 1.6 Introduction to Glide and GVD
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Three steps are needed to create an executable file from an Ada source file:
All three steps are most commonly handled by using the gnatmake
utility program that, given the name of the main program, automatically
performs the necessary compilation, binding and linking steps.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Any text editor may be used to prepare an Ada program.
If Glide
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
standard format text file:
with Ada.Text_IO; use Ada.Text_IO; procedure Hello is begin Put_Line ("Hello WORLD!"); end Hello; |
This file should be named `hello.adb'.
With the normal default file naming conventions, GNAT requires
that each file
contain a single compilation unit whose file name is the
unit name,
with periods replaced by hyphens; the
extension is `ads' for a
spec and `adb' for a body.
You can override this default file naming convention by use of the
special pragma Source_File_Name
(see section 2.4 Using Other File Names).
Alternatively, if you want to rename your files according to this default
convention, which is probably more convenient if you will be using GNAT
for all your compilations, then the gnatchop
utility
can be used to generate correctly-named source files
(see section 8. Renaming Files Using gnatchop
).
You can compile the program using the following command ($
is used
as the command prompt in the examples in this document):
$ gcc -c hello.adb |
gcc
is the command used to run the compiler. This compiler is
capable of compiling programs in several languages, including Ada 95 and
C. It assumes that you have given it an Ada program if the file extension is
either `.ads' or `.adb', and it will then call
the GNAT compiler to compile the specified file.
The `-c' switch is required. It tells gcc
to only 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
an "Ada Library Information" file `hello.ali',
which contains additional information used to check
that an Ada program is consistent.
To build an executable file,
use gnatbind
to bind the program
and gnatlink
to link it. The
argument to both gnatbind
and gnatlink
is the name of the
`ALI' file, but the default extension of `.ali' can
be omitted. This means that in the most common case, the argument
is simply the name of the main program:
$ gnatbind hello $ gnatlink hello |
A simpler method of carrying out these steps is to use
gnatmake
,
a master program that invokes all the required
compilation, binding and linking tools in the correct order. In particular,
gnatmake
automatically recompiles any sources that have been
modified since they were last compiled, or sources that depend
on such modified sources, so that "version skew" is avoided.
$ gnatmake hello.adb |
The result is an executable program called `hello', which can be run by entering:
$ hello |
assuming that the current directory is on the search path for executable programs.
and, if all has gone well, you will see
Hello WORLD! |
appear in response to this command.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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 Ada.Text_IO; use Ada.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, place this program in the following three separate files:
Greetings
Greetings
To build an executable version of this program, we could use four separate steps to compile, bind, and link the program, as follows:
$ gcc -c gmain.adb $ gcc -c greetings.adb $ gnatbind gmain $ gnatlink gmain |
Note that there is no required order of compilation when using GNAT. In particular it is perfectly fine to compile the main program first. Also, it is not necessary to compile package specs in the case where there is an accompanying body; you only need to compile the body. If you want to submit these files to the compiler for semantic checking and not code generation, then use the `-gnatc' switch:
$ gcc -c greetings.ads -gnatc |
Although the compilation can be done in separate steps as in the
above example, in practice it is almost always more convenient
to use the gnatmake
tool. All you need to know in this case
is the name of the main program's source file. The effect of the above four
commands can be achieved with a single one:
$ gnatmake gmain.adb |
In the next section we discuss the advantages of using gnatmake
in
more detail.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gnatmake
Utility
If you work on a program by compiling single components at a time using
gcc
, you typically keep track of the units you modify. In order to
build a consistent system, you compile not only these units, but also any
units that depend on the units you have modified.
For example, in the preceding case,
if you edit `gmain.adb', you only need to recompile that file. But if
you edit `greetings.ads', you must recompile both
`greetings.adb' and `gmain.adb', because both files contain
units that depend on `greetings.ads'.
gnatbind
will warn you if you forget one of these compilation
steps, so that it is impossible to generate an inconsistent program as a
result of forgetting to do a compilation. Nevertheless it is tedious and
error-prone to keep track of dependencies among units.
One approach to handle the dependency-bookkeeping is to use a
makefile. However, makefiles present maintenance problems of their own:
if the dependencies change as you change the program, you must make
sure that the makefile is kept up-to-date manually, which is also an
error-prone process.
The gnatmake
utility takes care of these details automatically.
Invoke it using either one of the following forms:
$ gnatmake gmain.adb $ gnatmake gmain |
The argument is the name of the file containing the main program;
you may omit the extension. 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'.
In a large program, it
can be extremely helpful to use gnatmake
, because working out by hand
what needs to be recompiled can be difficult.
Note that gnatmake
takes into account all the Ada 95 rules that
establish dependencies among units. These include dependencies that result
from inlining subprogram bodies, and from
generic instantiation. Unlike some other
Ada make tools, gnatmake
does not rely on the dependencies that were
found by the compiler on a previous compilation, which may possibly
be wrong when sources change. gnatmake
determines the exact set of
dependencies from scratch each time it is run.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gnatmake
, etc.) alone
is sufficient, a graphical Interactive Development
Environment can make it easier for you to compose, navigate, and debug
programs. This section describes the main features of GPS
("GNAT Programming System"), the GNAT graphical IDE.
You will see how to use GPS to build and debug an executable, and
you will also learn some of the basics of the GNAT "project" facility.
GPS enables you to do much more than is presented here; e.g., you can produce a call graph, interface to a third-party Version Control System, and inspect the generated assembly language for a program. Indeed, GPS also supports languages other than Ada. Such additional information, and an explanation of all of the GPS menu items. may be found in the on-line help, which includes a user's guide and a tutorial (these are also accessible from the GNAT startup menu).
1.5.1 Building a New Program with GPS 1.5.2 Simple Debugging with GPS
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This section will explain how you can use GPS to create a project, to associate Ada source files with a project, and to build and run programs.
Invoke GPS, either from the command line or the platform's IDE. After it starts, GPS will display a "Welcome" screen with three radio buttons:
Start with default project in directory
Create new project with wizard
Open existing project
Select Create new project with wizard
and press OK
.
A new window will appear. In the text box labeled with
Enter the name of the project to create
, type `sample'
as the project name.
In the next box, browse to choose the directory in which you
would like to create the project file.
After selecting an appropriate directory, press Forward
.
A window will appear with the title
Version Control System Configuration
.
Simply press Forward
.
A window will appear with the title
Please select the source directories for this project
.
The directory that you specified for the project file will be selected
by default as the one to use for sources; simply press Forward
.
A window will appear with the title
Please select the build directory for this project
.
The directory that you specified for the project file will be selected
by default for object files and executables;
simply press Forward
.
A window will appear with the title
Please select the main units for this project
.
You will supply this information later, after creating the source file.
Simply press Forward
for now.
A window will appear with the title
Please select the switches to build the project
.
Press Apply
. This will create a project file named
`sample.prj' in the directory that you had specified.
After you create the new project, a GPS window will appear, which is partitioned into two main sections:
Select File
on the menu bar, and then the New
command.
The Workspace area will become white, and you can now
enter the source program explicitly.
Type the following text
with Ada.Text_IO; use Ada.Text_IO; procedure Hello is begin Put_Line("Hello from GPS!"); end Hello; |
Select File
, then Save As
, and enter the source file name
`hello.adb'.
The file will be saved in the same directory you specified as the
location of the default project file.
You need to add the new source file to the project.
To do this, select
the Project
menu and then Edit project properties
.
Click the Main files
tab on the left, and then the
Add
button.
Choose `hello.adb' from the list, and press Open
.
The project settings window will reflect this action.
Click OK
.
In the main GPS window, now choose the Build
menu, then Make
,
and select `hello.adb'.
The Messages window will display the resulting invocations of gcc
,
gnatbind
, and gnatlink
(reflecting the default switch settings from the
project file that you created) and then a "successful compilation/build"
message.
To run the program, choose the Build
menu, then Run
, and
select hello
.
An Arguments Selection window will appear.
There are no command line arguments, so just click OK
.
The Messages window will now display the program's output (the string
Hello from GPS
), and at the bottom of the GPS window a status
update is displayed (Run: hello
).
Close the GPS window (or select File
, then Exit
) to
terminate this GPS session.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Start GPS and select Open existing project
; browse to
specify the project file `sample.prj' that you had created in the
earlier example.
Select File
, then New
, and type in the following program:
with Ada.Text_IO; use Ada.Text_IO; procedure Example is Line : String (1..80); N : Natural; begin Put_Line("Type a line of text at each prompt; an empty line to exit"); loop Put(": "); Get_Line (Line, N); Put_Line (Line (1..N) ); exit when N=0; end loop; end Example; |
Select File
, then Save as
, and enter the file name
`example.adb'.
Add Example
as a new main unit for the project:
Project
, then Edit Project Properties
.
Main files
tab, click Add
, then
select the file `example.adb' from the list, and
click Open
.
You will see the file name appear in the list of main units
OK
To build the executable
select Build
, then Make
, and then choose `example.adb'.
Run the program to see its effect (in the Messages area). Each line that you enter is displayed; an empty line will cause the loop to exit and the program to terminate.
Note that the `-g' switches to gcc
and gnatlink
,
which are required for debugging, are on by default when you create
a new project.
Thus unless you intentionally remove these settings, you will be able
to debug any program that you develop using GPS.
Select Debug
, then Initialize
, then `example'
After performing the initialization step, you will observe a small icon to the right of each line number. This serves as a toggle for breakpoints; clicking the icon will set a breakpoint at the corresponding line (the icon will change to a red circle with an "x"), and clicking it again will remove the breakpoint / reset the icon.
For purposes of this example, set a breakpoint at line 10 (the
statement Put_Line (Line (1..N));
Select Debug
, then Run
. When the
Program Arguments
window appears, click OK
.
A console window will appear; enter some line of text,
e.g. abcde
, at the prompt.
The program will pause execution when it gets to the
breakpoint, and the corresponding line is highlighted.
Move the mouse over one of the occurrences of the variable N
.
You will see the value (5) displayed, in "tool tip" fashion.
Right click on N
, select Debug
, then select Display N
.
You will see information about N
appear in the Debugger Data
pane, showing the value as 5.
Right click on the N
in the Debugger Data
pane, and
select Set value of N
.
When the input window appears, enter the value 4
and click
OK
.
This value does not automatically appear in the Debugger Data
pane; to see it, right click again on the N
in the
Debugger Data
pane and select Update value
.
The new value, 4, will appear in red.
Select Debug
, then Next
.
This will cause the next statement to be executed, in this case the
call of Put_Line
with the string slice.
Notice in the console window that the displayed string is simply
abcd
and not abcde
which you had entered.
This is because the upper bound of the slice is now 4 rather than 5.
Toggle the breakpoint icon at line 10.
Select Debug
, then Continue
.
The program will reach the next iteration of the loop, and
wait for input after displaying the prompt.
This time, just hit the Enter key.
The value of N
will be 0, and the program will terminate.
The console window will disappear.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
1.6.1 Building a New Program with Glide 1.6.2 Simple Debugging with GVD 1.6.3 Other Glide Features
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
glide
at the command prompt. It will generally be useful to issue this
as a background command, thus allowing you to continue using
your command window for other purposes while Glide is running:
$ glide& |
Glide will start up with an initial screen displaying the top-level menu items as well as some other information. The menu selections are as follows
Buffers
Files
Tools
Edit
Search
Mule
Glide
Help
For this introductory example, you will need to create a new Ada source file.
First, select the Files
menu. This will pop open a menu with around
a dozen or so items. To create a file, select the Open file...
choice.
Depending on the platform, you may see a pop-up window where you can browse
to an appropriate directory and then enter the file name, or else simply
see a line at the bottom of the Glide window where you can likewise enter
the file name. Note that in Glide, when you attempt to open a non-existent
file, the effect is to create a file with that name. For this example enter
`hello.adb' as the name of the file.
A new buffer will now appear, occupying the entire Glide window,
with the file name at the top. The menu selections are slightly different
from the ones you saw on the opening screen; there is an Entities
item,
and in place of Glide
there is now an Ada
item. Glide uses
the file extension to identify the source language, so `adb' indicates
an Ada source file.
You will enter some of the source program lines explicitly, and use the syntax-oriented template mechanism to enter other lines. First, type the following text:
with Ada.Text_IO; use Ada.Text_IO; procedure Hello is begin |
Observe that Glide uses different colors to distinguish reserved words from
identifiers. Also, after the procedure Hello is
line, the cursor is
automatically indented in anticipation of declarations. When you enter
begin
, Glide recognizes that there are no declarations and thus places
begin
flush left. But after the begin
line the cursor is again
indented, where the statement(s) will be placed.
The main part of the program will be a for
loop. Instead of entering
the text explicitly, however, use a statement template. Select the Ada
item on the top menu bar, move the mouse to the Statements
item,
and you will see a large selection of alternatives. Choose for loop
.
You will be prompted (at the bottom of the buffer) for a loop name;
simply press the Enter key since a loop name is not needed.
You should see the beginning of a for
loop appear in the source
program window. You will now be prompted for the name of the loop variable;
enter a line with the identifier ind
(lower case). Note that,
by default, Glide capitalizes the name (you can override such behavior
if you wish, although this is outside the scope of this introduction).
Next, Glide prompts you for the loop range; enter a line containing
1..5
and you will see this also appear in the source program,
together with the remaining elements of the for
loop syntax.
Next enter the statement (with an intentional error, a missing semicolon) that will form the body of the loop:
Put_Line("Hello, World" & Integer'Image(I)) |
Finally, type end Hello;
as the last line in the program.
Now save the file: choose the File
menu item, and then the
Save buffer
selection. You will see a message at the bottom
of the buffer confirming that the file has been saved.
You are now ready to attempt to build the program. Select the Ada
item from the top menu bar. Although we could choose simply to compile
the file, we will instead attempt to do a build (which invokes
gnatmake
) since, if the compile is successful, we want to build
an executable. Thus select Ada build
. This will fail because of the
compilation error, and you will notice that the Glide window has been split:
the top window contains the source file, and the bottom window contains the
output from the GNAT tools. Glide allows you to navigate from a compilation
error to the source file position corresponding to the error: click the
middle mouse button (or simultaneously press the left and right buttons,
on a two-button mouse) on the diagnostic line in the tool window. The
focus will shift to the source window, and the cursor will be positioned
on the character at which the error was detected.
Correct the error: type in a semicolon to terminate the statement.
Although you can again save the file explicitly, you can also simply invoke
Ada
=> Build
and you will be prompted to save the file.
This time the build will succeed; the tool output window shows you the
options that are supplied by default. The GNAT tools' output (e.g.
object and ALI files, executable) will go in the directory from which
Glide was launched.
To execute the program, choose Ada
and then Run
.
You should see the program's output displayed in the bottom window:
Hello, world 1 Hello, world 2 Hello, world 3 Hello, world 4 Hello, world 5 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This section describes how to set breakpoints, examine/modify variables, and step through execution.
In order to enable debugging, you need to pass the `-g' switch
to both the compiler and to gnatlink
. If you are using
the command line, passing `-g' to gnatmake
will have
this effect. You can then launch GVD, e.g. on the hello
program,
by issuing the command:
$ gvd hello |
If you are using Glide, then `-g' is passed to the relevant tools
by default when you do a build. Start the debugger by selecting the
Ada
menu item, and then Debug
.
GVD comes up in a multi-part window. One pane shows the names of files comprising your executable; another pane shows the source code of the current unit (initially your main subprogram), another pane shows the debugger output and user interactions, and the fourth pane (the data canvas at the top of the window) displays data objects that you have selected.
To the left of the source file pane, you will notice green dots adjacent
to some lines. These are lines for which object code exists and where
breakpoints can thus be set. You set/reset a breakpoint by clicking
the green dot. When a breakpoint is set, the dot is replaced by an X
in a red circle. Clicking the circle toggles the breakpoint off,
and the red circle is replaced by the green dot.
For this example, set a breakpoint at the statement where Put_Line
is invoked.
Start program execution by selecting the Run
button on the top menu bar.
(The Start
button will also start your program, but it will
cause program execution to break at the entry to your main subprogram.)
Evidence of reaching the breakpoint will appear: the source file line will be
highlighted, and the debugger interactions pane will display
a relevant message.
You can examine the values of variables in several ways. Move the mouse
over an occurrence of Ind
in the for
loop, and you will see
the value (now 1
) displayed. Alternatively, right-click on Ind
and select Display Ind
; a box showing the variable's name and value
will appear in the data canvas.
Although a loop index is a constant with respect to Ada semantics,
you can change its value in the debugger. Right-click in the box
for Ind
, and select the Set Value of Ind
item.
Enter 2
as the new value, and press OK
.
The box for Ind
shows the update.
Press the Step
button on the top menu bar; this will step through
one line of program text (the invocation of Put_Line
), and you can
observe the effect of having modified Ind
since the value displayed
is 2
.
Remove the breakpoint, and resume execution by selecting the Cont
button. You will see the remaining output lines displayed in the debugger
interaction window, along with a message confirming normal program
termination.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
You may have observed that some of the menu selections contain abbreviations;
e.g., (C-x C-f)
for Open file...
in the Files
menu.
These are shortcut keys that you can use instead of selecting
menu items. The C stands for Ctrl; thus (C-x C-f)
means
Ctrl-x followed by Ctrl-f, and this sequence can be used instead
of selecting Files
and then Open file...
.
To abort a Glide command, type Ctrl-g.
If you want Glide to start with an existing source file, you can either
launch Glide as above and then open the file via Files
=>
Open file...
, or else simply pass the name of the source file
on the command line:
$ glide hello.adb& |
While you are using Glide, a number of buffers exist.
You create some explicitly; e.g., when you open/create a file.
Others arise as an effect of the commands that you issue; e.g., the buffer
containing the output of the tools invoked during a build. If a buffer
is hidden, you can bring it into a visible window by first opening
the Buffers
menu and then selecting the desired entry.
If a buffer occupies only part of the Glide screen and you want to expand it
to fill the entire screen, then click in the buffer and then select
Files
=> One Window
.
If a window is occupied by one buffer and you want to split the window to bring up a second buffer, perform the following steps:
Files
=> Split Window
;
this will produce two windows each of which holds the original buffer
(these are not copies, but rather different views of the same buffer contents)
Buffers
menu
To exit from Glide, choose Files
=> Exit
.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |