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

6. The GNAT Make Program gnatmake

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 Works  
6.6 Examples of gnatmake Usage  
6.7 Gnatmake in makefiles  
A typical development cycle when working on an Ada program consists of the following steps:

  1. Edit some sources to fix bugs.

  2. Add enhancements.

  3. Compile all sources affected.

  4. Rebind and relink.

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


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

6.1 Running 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] [ ? ]

6.2 Switches for gnatmake

You may specify any of the following switches to gnatmake:

--GCC=compiler_name
Program used for compiling. The default is 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
Program used for binding. The default is 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
Program used for linking. The default is 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
Consider all files in the make process, even the GNAT internal system files (for example, the predefined Ada library files), as well as any locked files. Locked files are files whose ALI file is write-protected. By default, 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
Compile only. Do not perform binding and linking. If the root unit specified by 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 or locked files (files with a write-protected ALI file), unless the -a switch is also specified.

-i
In normal mode, 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
Use n processes to carry out the (re)compilations. On 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). If this is problematic, rerun the make process with n set to 1 to get a clean list of messages.

-k
Keep going. Continue as much as possible after a compilation error. To ease the programmer's task in case of compilation errors, the list of sources for which the compile fails is given when gnatmake terminates.

-m
Specifies that the minimum necessary amount of recompilations be performed. In this mode 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
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 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 -aLdir in the following list) are never reported.

-n
Don't compile, bind, or link. Checks if all objects are up to date. If they are not, the full name of the first file that needs to be recompiled is printed. Repeated use of this option, followed by compiling the indicated source file, will eventually result in recompiling all required units.

-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 in appropriate form for an executable file on the host system.

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

-z
No main subprogram. Bind and link the program even if the unit name given on the command line is a package name. The resulting executable will execute the elaboration routines of the package and its closure, then the finalization routines.

gnatgcc switches
The switch -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
When looking for source files also look in directory dir. The order in which source files search is undertaken is described in 3.3 Search Paths and the Run-Time Library (RTL).

-aLdir
Consider dir as being an externally provided Ada library. Instructs 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
When searching for library and object files, look in directory dir. The order in which library files are searched is described in 4.10 Search Paths for gnatbind.

-Adir
Equivalent to -aLdir -aIdir.

-Idir
Equivalent to -aOdir -aIdir.

-I-
Do not look for source files in the directory containing the source file named in the command line. Do not look for ALI or object files in the directory where gnatmake was invoked.

-Ldir
Add directory dir to the list of directories in which the linker will search for libraries. This is equivalent to -largs -Ldir.

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

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


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

6.3 Mode switches for 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
Compiler switches. Here switches is a list of switches that are valid switches for gnatgcc. They will be passed on to all compile steps performed by gnatmake.

-bargs switches
Binder switches. Here switches is a list of switches that are valid switches for gnatgcc. They will be passed on to all bind steps performed by gnatmake.

-largs switches
Linker switches. Here switches is a list of switches that are valid switches for gnatgcc. They will be passed on to all link steps performed by gnatmake.


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

6.4 Notes on the Command Line

This section contains some additional useful notes on the operation of the gnatmake command.


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

6.5 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 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] [ ? ]

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


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

6.7 Gnatmake in makefiles

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] [ ? ]

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