[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gnatmake
A typical development cycle when working on an Ada program consists of the following steps:
6.1 Running gnatmake
6.2 Switches for gnatmake
6.3 Mode switches for gnatmake
6.4 Notes on the Command Line 6.5 How gnatmake
Works6.6 Examples of gnatmake
Usage6.7 Gnatmake in makefiles
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
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gnatmake
The form of the gnatmake
command is
$ gnatmake [switches] file_name [mode_switches] |
The only required argument is file_name, which specifies
the compilation unit that is the main program. If switches
are
present, they can be placed before of after file_name.
If mode_switches are present, they must always be placed after
file_name and all switches
.
If you are using standard file extensions (.adb and .ads), then the
extension may be omitted from the file_name argument. However, if
you are using non-standard extensions, then it is required that the
extension be given. A relative or absolute directory path can be
specified in file_name, in which case, the input source file will
be searched for in the specified directory only. Otherwise, the input
source file will first be searched in the directory where
gnatmake
was invoked and if it is not found, it will be search on
the source path of the compiler as described in 3.3 Search Paths and the Run-Time Library (RTL).
All gnatmake
output (except when you specify
-M
) is to
stderr
. The output produced by the
-M
switch is send to
stdout
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gnatmake
You may specify any of the following switches to gnatmake
:
--GCC=compiler_name
gnatgcc
'. You need to use
quotes around compiler_name if compiler_name
contains
spaces or other separator characters. As an example --GCC="foo -x
-y"
will instruct gnatmake
to use foo -x -y
as your
compiler. Note that switch -c
is always inserted after your
command name. Thus in the above example the compiler command that will
be used by gnatmake
will be foo -c -x -y
.
--GNATBIND=binder_name
gnatbind
'. You need to
use quotes around binder_name if binder_name contains spaces
or other separator characters. As an example --GNATBIND="bar -x
-y"
will instruct gnatmake
to use bar -x -y
as your
binder. Binder switches that are normally appended by gnatmake
to
gnatbind
' are now appended to the end of bar -x -y
.
--GNATLINK=linker_name
gnatlink
'. You need to
use quotes around linker_name if linker_name contains spaces
or other separator characters. As an example --GNATLINK="lan -x
-y"
will instruct gnatmake
to use lan -x -y
as your
linker. Linker switches that are normally appended by gnatmake
to
gnatlink
' are now appended to the end of lan -x -y
.
-a
gnatmake
does not check these files,
because the assumption is that the GNAT internal files are properly up
to date, and also that any write protected ALI files have been properly
installed. Note that if there is an installation problem, such that one
of these files is not up to date, it will be properly caught by the
binder.
You may have to specify this switch if you are working on GNAT
itself. -f
is also useful in conjunction with
-f
if you need to recompile an entire application,
including run-time files, using special configuration pragma settings,
such as a non-standard Float_Representation
pragma.
By default
gnatmake -a
compiles all GNAT
internal files with
gnatgcc -c -gnatg
rather than gnatgcc -c
.
-c
gnatmake
will attempt binding and linking
unless all objects are up to date and the executable is more recent than
the objects.
-f
-a
switch is also specified.
-i
gnatmake
compiles all object files and ALI files
into the current directory. If the -i
switch is used,
then instead object files and ALI files that already exist are overwritten
in place. This means that once a large project is organized into separate
directories in the desired manner, then gnatmake
will automatically
maintain and update this organization. If no ALI files are found on the
Ada object path (3.3 Search Paths and the Run-Time Library (RTL)),
the new object and ALI files are created in the
directory containing the source being compiled. If another organization
is desired, where objects and sources are kept in different directories,
a useful technique is to create dummy ALI files in the desired directories.
When detecting such a dummy file, gnatmake
will be forced to recompile
the corresponding source file, and it will be put the resulting object
and ALI files in the directory where it found the dummy file.
-jn
gnatmake
will give you the full ordered
list of failing compiles at the end). If this is problematic, rerun
the make process with n set to 1 to get a clean list of messages.
-k
gnatmake
terminates.
-m
gnatmake
ignores time
stamp differences when the only
modifications to a source file consist in adding/removing comments,
empty lines, spaces or tabs. This means that if you have changed the
comments in a source file or have simply reformatted it, using this
switch will tell gnatmake not to recompile files that depend on it
(provided other sources on which these files depend have undergone no
semantic modifications).
-M
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 below), only the source file names,
without relative paths, are output. If you just specify the
-M
switch, dependencies of the GNAT internal system files are omitted. This
is typically what you want. If you also specify
the -a
switch,
dependencies of the GNAT internal files are also listed. Note that
dependencies of the objects in external Ada libraries (see switch
-aL
dir in the following list) are never reported.
-n
-o exec_name
-o
switch is omitted the default
name for the executable will be the name of the input file in appropriate form
for an executable file on the host system.
-q
gnatmake
are displayed.
-v
gnatmake
decides are necessary.
-z
gnatgcc
switches
-g
or any uppercase switch (other than -A
, or
-L
) or any switch that is more than one character is passed to
gnatgcc
(e.g. -O
, -gnato,
etc.)
Source and library search path switches:
-aIdir
-aLdir
gnatmake
to skip compilation units whose `.ali'
files have been located in directory dir. This allows you to have
missing bodies for the units in dir. You still need to specify
the location of the specs for these units by using the switches
-aIdir
or -Idir
.
Note: this switch is provided for compatibility with previous versions
of gnatmake
. The easier method of causing standard libraries
to be excluded from consideration is to write-protect the corresponding
ALI files.
-aOdir
gnatbind
.
-Adir
-aLdir
-aIdir
.
-Idir
-aOdir
-aIdir
.
-I-
gnatmake
was invoked.
-Ldir
-largs -L
dir.
-nostdinc
-nostdlib
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gnatmake
The mode switches (referred to as mode_switches
) allow the
inclusion of switches that are to be passed to the compiler itself, the
binder or the linker. The effect of a mode switch is to cause all
subsequent switches up to the end of the switch list, or up to the next
mode switch, to be interpreted as switches to be passed on to the
designated component of GNAT.
-cargs switches
gnatgcc
. They will be passed on to
all compile steps performed by gnatmake
.
-bargs switches
gnatgcc
. They will be passed on to
all bind steps performed by gnatmake
.
-largs switches
gnatgcc
. They will be passed on to
all link steps performed by gnatmake
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This section contains some additional useful notes on the operation
of the gnatmake
command.
gnatmake
finds no ALI files, it recompiles the main program
and all other units required by the main program.
This means that gnatmake
can be used for the initial compile, as well as during subsequent steps of
the development cycle.
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
the switch -I
is used to specify both source and
library file paths. Use -aI
instead if you just want to specify
source paths only and -aO
if you want to specify library paths
only.
gnatmake
examines both an ALI file and its corresponding object file
for consistency. If an ALI is more recent than its corresponding object,
or if the object file is missing, the corresponding source will be recompiled.
Note that gnatmake
expects an ALI and the corresponding object file
to be in the same directory.
gnatmake
will ignore any files whose ALI file is write-protected.
This may conveniently be used to exclude standard libraries from
consideration and in particular it means that the use of the
-f
switch will not recompile these files
unless -a
is also specified.
gnatmake
has been designed to make the use of Ada libraries
particularly convenient. Assume you have an Ada library organized
as follows: obj-dir contains the objects and ALI files for
of your Ada compilation units,
whereas include-dir contains the
specs of these units, but no bodies. Then to compile a unit
stored in main.adb
, which uses this Ada library you would just type
$ gnatmake -aIinclude-dir -aLobj-dir main |
gnatmake
along with the
-m (minimal recompilation)
switch provides an
extremely powerful tool: you can freely update the comments/format of your
source files without having to recompile everything. Note, however, that
adding or deleting lines in a source files may render its debugging
info obsolete. If the file in question is a spec, the impact is rather
limited, as that debugging info will only be useful during the
elaboration phase of your program. For bodies the impact can be more
significant. In all events, your debugger will warn you if a source file
is more recent than the corresponding object, and therefore obsolescence of
debugging information will go unnoticed.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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 its time stamp predates that of the object file 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 unit is up
to date. If so, no compilations are required for the main unit. If not,
gnatmake
compiles the main program to build a new ALI file that
reflects the latest sources. Then the ALI file of the main unit is
examined to find all the source files on which the main program depends,
and gnatmake
recursively applies the above procedure 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. As a result 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.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gnatmake
Usage
gnatmake hello.adb
Hello
) and bind and link the
resulting object files to generate an executable file `hello'.
gnatmake -q Main_Unit -cargs -O2 -bargs -l
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.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Complex project organizations can be handled in a very powerful way by using GNU make combined with gnatmake. Here is for instance a Makefile which allows to build each subsystem of a big project into a separate shared library. Such a makefile allows to significantly reduce the link time of very bug applications while maintaining a complete coherence at each step of the build process.
## This Makefile is intended to be used with the following directory ## configuration: ## - The sources are split into a series of csc (computer software components) ## Each of these csc is put in its own directory. ## Their name are referenced by the directory names. ## They will be compiled into shared library (although this would also work ## with static libraries ## - The main program (and possibly other packages that do not belong to any ## csc is put in the top level directory (where the Makefile is). ## toplevel_dir __ first_csc (sources) __ lib (will contain the library) ## \_ second_csc (sources) __ lib (will contain the library) ## \_ ... ## Although this Makefile is build for shared library, it is easy to modify ## to build partial link objects instead (modify the lines with -shared and ## gnatlink below) ## ## With this makefile, you can change any file in the system or add any new ## file, and everything will be recompiled correctly (only the relevant shared ## objects will be recompiled, and the main program will be re-linked). # The list of computer software component for your project CSC_LIST=aa bb cc # Name of the main program (no extension) MAIN=main # If we need to build objects with -fPIC, uncomment the following line #NEED_FPIC=-fPIC # The following variable should give the directory containing libgnat.so # You can get this directory through 'gnatls -v'. This is usually the last # directory in the Object_Path. GLIB=... # The directories for the libraries # (This macro expands the list of CSC to the list of shared libraries, you # could simply use the expanded form : # LIB_DIR=aa/lib/libaa.so bb/lib/libbb.so cc/lib/libcc.so LIB_DIR=${foreach dir,${CSC_LIST},${dir}/lib/lib${dir}.so} ${MAIN}: objects ${LIB_DIR} gnatbind ${MAIN} ${CSC_LIST:%=-aO%/lib} -shared gnatlink ${MAIN} ${CSC_LIST:%=-l%} objects:: # recompile the sources gnatmake -c -i ${MAIN}.adb ${NEED_FPIC} ${CSC_LIST:%=-I%} # Note about the rules below: if your csc are not split into multiple # directories, but simply by their name, you need to replace *.o and # *.ali with the appropriate list of files # Note: In a future version of GNAT, the following commands will be simplified # by a new tool, gnatmlib ${LIB_DIR}: mkdir -p ${dir $ } cd ${dir $ }; gnatgcc -shared -o ${notdir $ } ../*.o -L${GLIB} -lgnat cd ${dir $ }; cp -f ../*.ali . # The dependencies for the modules aa/lib/libaa.so: aa/*.o bb/lib/libbb.so: bb/*.o bb/lib/libcc.so: cc/*.o run:: LD_LIBRARY_PATH=pwd/aa/lib:pwd/bb/lib:pwd/cc/lib ./${MAIN} clean:: ${RM} -rf ${CSC_LIST:%=%/lib} ${RM} ${CSC_LIST:%=%/*.ali} ${RM} ${CSC_LIST:%=%/*.o} ${RM} *.o *.ali ${MAIN} |
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |