<--Last Chapter | Table of Contents | Next Chapter--> |
IDE: TIA will run gnatstub on the current file using Stub in the File menu. |
For example, suppose you have the following package specification in a file called tiny.ads:
package tiny is procedure simple_procedure; function simple_function return boolean; end tiny;
You can create a stub body for this package using
gnatstub tiny.ads
Gnatstub produces the following tiny.adb file:
package body tiny is --------------------- -- simple_function -- --------------------- function simple_function return boolean is begin return simple_function; end simple_function; ---------------------- -- simple_procedure -- ---------------------- procedure simple_procedure is begin null; end simple_procedure; end tiny;
This package body is in proper Ada format, ready to be compiled.
Of course, it doesn't actually do anything useful. It's up to the
programmer fill in the implementation details.
The -v option produces a listing in the format for a vi editor tags file.
IDE: TIA will run gnatxref on the current file by chosing Xref in the File menu. |
For our hello.adb program, Gnatxref produces the following:
Text_IO U a-textio.ads:51:13 {} {hello.adb:1:10 4:7 } Put_Line U a-textio.ads:260:14 {} {hello.adb:4:15 } Ada U ada.ads:18:9 {} {hello.adb:1:6 4:3 } hello U hello.adb:2:11 {} {}
Each line begins with the identifier being indexed. The "U" means [not sure-KB]. The next segment is the file that defines the identifier, and the position in the file. The {} means [not sure-KB]. The final bracketed section lists all occurrences of the identifier in the program.
In this example, identifier text_io appears in the first line (the with) and the fourth line (the put_line).
gnatelim is a utility that searches for unused parts of your program in the object files and removes them from the final executable. It works by creating a list of subprograms that the compiler shouldn't compile. If you save this list as gnat.adc, gnatmake will automatically read this file and will skip these subprograms when compiling.
To use gnatelim, you need to generate tree files using the -gnatt switch. The Gnat manual recommends these steps when using gnatelim (assuming that your main program is main.adb):
These commands will generate a complete set of tree files for your project, strip out all unused subprograms, and will then recompile the project as a finished executable.
gnatelim is is based on ASIS.
[gnatelim doesn't work under gnat 3.11.--KB]
Gnat 3.11 does not display the execution stack in the event of of an exception. Gnat 3.12 provides additional information about the source of an exception. You can get additional information about the execution stack using the gnat.traceback package (12.15).
The gnatmem utility monitors a running programming using the Gnat gdb
debugger. When the program is finished running, gnatmem displays
a summary of dynamically allocated memory. You can use this information
to find "memory leaks", places in your program where allocated memory was
not deallocated. Because gnatmem uses gdb, the program should be
compiled with gdb support turned on (the -g switch).
Note: gnatmem doesn't work with Gnat 3.11. |
To run gnatmem, type
gnatmem program
The gnatmem switches are:
-q - quiet - hides statistics and shows only potential
memory leaks
n - a number between 1 and 10 indicating the depth
of the backtrace information
-o file - save the gdb output to the indicated
file. The gdb script is saved as gnatmem.tmp
-i file - processing using the file previously
saved with -o. Use this to test a program that crashed while
gnatmem was running.
Gnatprep, the Gnat PREProcessor, takes a source file with
conditional directives, a file with variable assignments for the
conditional directives, and produces a source file with all
statements not satisfying the conditional directives removed.
C: The conditional directives do not allow expressions. There must only be a variable, and that variable must be true or false. |
IDE: No IDE's currently support gnatprep. |
Suppose you create a file called "prepvalues" with the following Gnatprep definitions:
ALPHAVERSION := true BETAVERSION := false RELEASEVERSION := false TRANSLATION := English
Suppose also that you had a short program with Gnatprep statements in it:
with text_io; use text_io; procedure preptest is -- only include the relevant parts for this version #if ALPHAVERSION s_version : string := "alpha"; #elsif BETAVERSION s_version : string := "beta"; #elsif RELEASEVERSION s_version : string := "release"; #else s_version : string := "unknown"; #end if; -- string is the value of the gnatprep variable named translation s_translation : string := "$TRANSLATION"; begin Put_Line( "This is the " & s_version & " edition" ); Put_Line( "This is the " & s_translation & " translation" ); end preptest;
Running gnatprep on the above program with the prepvalues file gives you the following program:
with text_io; use text_io; procedure preptest is -- only include the relevant parts for this version s_version : string := "beta"; -- string is the value of the gnatprep variable named translation s_translation : string := "English"; begin Put_Line( "This is the " & s_version & " edition" ); Put_Line( "This is the " & s_translation & " translation" ); end preptest;
The Gnatprep command switches are:
-Dsymbol=value - define values on the command line
instead of a prep values file, same as -D in C. For example,
-DMacintosh=FALSE
-b - replace gnatprep commands with blank lines (instead of
-c)
-c - comment out gnatprep commands (instead of -b)
-r - generate a Source_Reference pragma
-s - print a sorted list of symbols and values
-u - treat undefined symbols as if they were FALSE
C: There is no gnatprep equivalent of __FILE__ (name of current source file) or __LINE__ (number of current line). |
To use Gprof, you must rebuild your project using the
-pg switch at both the compiling and linking stages. With
Gnatmake, you must include -pg with both -cargs and -largs
switches.
IDE: TIA will profile your project with gprof if you select Profile in the Project menu. It automatically rebuilds your project with the necessary gprof switches, starts your main program, and then displays the gprof results. |
For example, we can use Gprof on the following factorial program:
package fact is function factorial( param : integer ) return integer; end fact; package body fact is function factorial( param : integer ) return integer is begin if param < 2 then return 1; end if; return param * factorial( param - 1 ); end factorial; end fact; with fact; use fact; procedure bench2 is maxFactorials : constant integer := 1000; type factorialArray is array( 1..maxFactorials ) of integer; list : factorialArray; begin for i in 1..maxFactorials loop list( i ) := factorial( i ); end loop; end bench2;
After compiling and linking the program with the -pg switch, run the program. The program produces a gmon.out file containing profile information about the program. Now we can use Gprof to get an analysis of the program.
Running gprof -c bench2 returns the following information. Note that Ada subprograms are labeled with the package name, a double underscore, and the subprogram name.
[Need to clean this up--KB]Flat profile: Each sample counts as 0.01 seconds. %cumulative self self total time seconds seconds callsus/callus/callname 62.500.050.05__mcount_internal 25.000.070.02mcount 12.500.080.01100010.0010.00fact__factorial 0.000.080.0010.00 10000.00_ada_bench2 0.000.080.0010.000.00fact___elabb %the percentage of the total running time of the time program used by this function. cumulative a running sum of the number of seconds accounted seconds for by this function and those listed above it. self the number of seconds accounted for by this seconds function alone.This is the major sort for this listing. calls the number of times this function was invoked, if this function is profiled, else blank. self the average number of milliseconds spent in this ms/call function per call, if this function is profiled, else blank. total the average number of milliseconds spent in this ms/callfunction and its descendents per call, if this function is profiled, else blank. name the name of the function. This is the minor sort for this listing. The index shows the location of the function in the gprof listing. If the index is in parenthesis it shows where it would appear in the gprof listing if it were to be printed. Call graph (explanation follows) granularity: each sample hit covers 4 byte(s) for 100.00% of 0.01 seconds index % time self children called name 499500fact__factorial [1] 0.010.001000/1000_ada_bench2 [3] [1]100.00.010.001000+499500fact__factorial [1] 0.000.000/0mcount (177) 499500fact__factorial [1] ----------------------------------------------- 0.000.000/0_start [473] [2]100.00.000.01main [2] 0.000.011/1_ada_bench2 [3] 0.000.000/0__gnat_initialize [399] 0.000.000/0adainit [61] 0.000.000/0__gnat_break_start [395] 0.000.000/0adafinal [60] 0.000.000/0__gnat_finalize [397] 0.000.000/0exit [95] ----------------------------------------------- 0.000.011/1main [2] [3]100.00.000.011_ada_bench2 [3] 0.010.00 1000/1000fact__factorial [1] 0.000.000/0mcount (177) ----------------------------------------------- 0.000.001/1adainit [61] [6]0.00.000.001fact___elabb [6] 0.000.000/0mcount (177) ----------------------------------------------- This table describes the call tree of the program, and was sorted by the total amount of time spent in each function and its children. Each entry in this table consists of several lines.The line with the index number at the left hand margin lists the current function. The lines above it list the functions that called this function, and the lines below it list the functions this one called. This line lists: index A unique number given to each element of the table. Index numbers are sorted numerically. The index number is printed next to every function name so it is easier to look up where the function in the table. % time This is the percentage of the `total' time that was spent in this function and its children.Note that due to different viewpoints, functions excluded by options, etc, these numbers will NOT add up to 100%. self This is the total amount of time spent in this function. children This is the total amount of time propagated into this function by its children. called This is the number of times the function was called. If the function called itself recursively, the number only includes non-recursive calls, and is followed by a `+' and the number of recursive calls. name The name of the current function. The index number is printed after it. If the function is a member of a cycle, the cycle number is printed between the function's name and the index number. For the function's parents, the fields have the following meanings: self This is the amount of time that was propagated directly from the function into this parent. children This is the amount of time that was propagated from the function's children into this parent. called This is the number of times this parent called the function `/' the total number of times the function was called. Recursive calls to the function are not included in the number after the `/'. name This is the name of the parent.The parent's index number is printed after it.If the parent is a member of a cycle, the cycle number is printed between the name and the index number. If the parents of the function cannot be determined, the word `<spontaneous>' is printed in the `name' field, and all the other fields are blank. For the function's children, the fields have the following meanings: self This is the amount of time that was propagated directly from the child into the function. children This is the amount of time that was propagated from the child's children to the function. called This is the number of times the function called this child `/' the total number of times the child was called. Recursive calls by the child are not listed in the number after the `/'. name This is the name of the child.The child's index number is printed after it.If the child is a member of a cycle, the cycle number is printed between the name and the index number. If there are any cycles (circles) in the call graph, there is an entry for the cycle-as-a-whole. This entry shows who called the cycle (as parents) and the members of the cycle (as children.) The `+' recursive calls entry shows the number of function calls that were internal to the cycle, and the calls entry for each member shows, for that member, how many times it was called from other members of the cycle. Index by function name (418) __mcount_internal[1] fact__factorial[5] <cycle 2> [3] _ada_bench2(177) mcount [6] fact___elabb[4] <cycle 1>
If factorial is a function internal to program bench2, the function name won't show up in Gprof. For example:
procedure bench2 is function factorial( param : integer ) return integer is begin if param > 1 then return param * factorial( param - 1 ); end if; return 1; end factorial; maxFactorials : constant integer := 100; type factorialArray is array( 1..maxFactorials ) of integer; list : factorialArray; begin for i in 1..maxFactorials loop list( i ) := factorial( i ); end loop; end bench2;
gprof -c bench2 returns the following information:
Flat profile: Each sample counts as 0.01 seconds. no time accumulated %cumulativeselfselftotal time seconds seconds callsTs/callTs/callname 0.000.000.00990.000.00main 0.000.000.0010.000.00_ada_bench2 etc.
Note: gnatmem doesn't work with Gnat 3.11. |
To create static libraries (.a suffix under Linux), create the archive file by combining all the .o object files into an .a archive file using ar. Then, put the .ads and .ali files in a appropriate directories. Change the .ali files to read-only. Gnat will then search for the object files in a library. When building your project, use the appropriate switches (-I, -L, -l, etc.) so that gcc and find your library and the include files.
To create shared libraries, Gnat has a tool called gnatdll to automate the process in a operating system independent way.
[To be completed]
This utility converts an Ada source file into a series of indexed, coloured HTML web pages. By default, the web pages are stored under a subdirectory called HTML. By posting your source code on a network or the Internet, developers can examine your work with a web browser.
The gnathtml switches are:
with Ada.Text_IO;
use Ada.Text_IO;
procedure htmltest is
-- a demonstration of gnathtml
function factorial( n : natural ) return natural
is
-- compute the factorial of n
begin
if n < 2 then
return 1;
else
return n * factorial(
n-1 );
end if;
end factorial;
-- main program
begin
put_line( "Browse this source!" );
new_line;
put_line( "The factorial of 5 is" & natural'image( factorial(
5 ) ) );
end htmltest;
This creates an index file like this:
The first link would show you your entire file:
with Ada.Text_IO; use Ada.Text_IO; procedure htmltest is -- a demonstration of gnathtml function factorial( n : natural ) return natural is -- compute the factorial of n begin if n < 2 then return 1; else return n * factorial( n-1 ); end if; end factorial; -- main program begin put_line( "Browse this source!" ); new_line; put_line( "The factorial of 5 is" & natural'image( factorial( 5 ) ) ); end htmltest;
The links use the .htm (not .html) extension for portability.
<--Last Chapter | Table of Contents | Next Chapter--> |