How To - Using ObjectAda from the Command Line


By no stretch of the imagination would I consider myself an expert on the ObjectAda command line interface, but I am happy to provide you with what I've experienced. The following notes are for a Windows OS (95/98/NT) using version 7.1.2a of the compiler, Professional Edition, and building a non-Windows application (that's important since a Windows application is built with a few different switches and gets bound with a binary resource file that's created by ... oh, lets not go there).

Starting from scratch:

Create a directory and put some Ada source files in the directory, then create an Ada library. This can be done automatically or explicitly depending on your preference. To just create an empty library, run "adareg -cl". This creates the file ADA.LIB in the current directory. Next, add links into the ADA.LIB file for bindings that you may use in your project. The most common would be the Win32 bindings. This can be done using the command "adaopts -p [ObjectAda]\win32ada\binding\lib -i1". The [ObjectAda] reference is the drive and path where ObjectAda is installed on your system. The "-i1" puts the link after the first link in a list of links maintained in the ADA.LIB file. Notice that so far we've only created an ADA.LIB file and added some search criteria. The adareg utility creates the ADA.LIB file and adds references to Ada source files (a process called registering, which I'll get to in a minute). The adaopts utility allows you to add links to other directories in order to search for bindings, other source code directories, etc., and reports on the contents of the ADA.LIB file. To see what's in the ADA.LIB file, you can run adaopts with a "-l" parameter, or "-l -v" to get more verbose information.

Compiling:

We can proceed in two directions from this point. The first method is to register all our Ada source files into the ADA.LIB file using adareg and then attempt to compile them all and build an application using either adabuild or adamake. If you already have a complete Ada application that you just want to get compiled and linked into an executable, this is the way to go. If you're building an Ada application from scratch, then the second method is to compile units as they are created and use the "autoregister" capability of the compiler. When everything compiles, then either adabuild or adamake can be run to create the executable. In either case, the process of registering will create another file in the current directory called UNIT.MAP. This file maintains information for mapping source file names to Ada unit(s) within each source file, hence the name UNIT.MAP. Other information is also included in UNIT.MAP such as the date and time a source file was compiled. This allows the adamake and adabuild utilities to determine which units need to be recompiled in order to build an executable.

The first method is simpler; just run adareg with a set of file names, or the name of a directory then run either adabuild or adamake. If you have a set of source files with no errors, you can't beat this method. Enough said.

The second method takes longer, but if you're creating an application from scratch then it's the method you'll probably use. Let's say you're creating a new package, call it My_Pkg for example, and store it in the file My_Pkg.ads. When you're ready to compile, run "adacomp -sr -lr My_Pkg.ads". The "-sr" switch does the autoregister of the source and the "-lr" switch produces a minimal listing of only warning and error messages. This process is repeated until all your packages, subprograms, etc. will compile without errors. During the compile process, you'll notice several new subdirectories are created such as il, info, msg, obj, and xref. These subdirectories store information used/generated by the compiler and provide a repository for information that will be used/generated by the link step. Their names and locations can be changed using adaopts but I've never had the need to do this.

Linking:

At some point, all the units needed to generate a complete application will have been compiled and it's time to create an executable. Let's call the Ada unit My_App, whose source is stored in the file My_App.adb. We can create the executable My_App.exe using the command "adabuild My_App". Notice that adabuild is given an Ada unit name and not a file name. This makes sense since the object modules generated by the compiler are what's needed by the linker to create the executable, the source code file is pretty much irrelevant at this point (there's a caveat to this which I'll get to in a minute). Adabuild will verify that My_App has an up-to-date closure of units, and if so, will generate one or more intermediate files that are used by the system linker to put all the object modules and library modules together into an executable. The ".rsp" file you mentioned in your original post is one (very important) intermediate file used by the linker. The information in the ".rsp" file comes from the adabuild utility's search for a closure, and information stored in the ADA.LIB file. (I'm not sure but I believe ".rsp" files are called linker response files, or simply response files.) I wouldn't recommend changing the ".rsp" files yourself since they are created/overwritten by adabuild each time it is run. You can change the information that goes into the ".rsp" file by setting switches on the adabuild command line, and/or changing information in the ADA.LIB file using adaopts.

What if you've changed a source file but forgotten to re-compile it? In this case, adabuild will notice that the unit is out-of-date during its closure search and re-compile it for you. To do this, adabuild uses the information in the ADA.LIB file, and the files in the subdirectories under the info directory, to determine what Ada units the application is dependent upon. Adabuild then traces each Ada unit to its original source file using UNIT.MAP, and checks that the object file for that unit is dated later than the source file. If not, then the unit is recompiled. If the unit was compiled at least once before, the same compiler switches are used (this information is also stored in one of those subdirectories, perhaps the info directory, but I'm not sure).

What's the difference between adabuild and adamake? Adabuild will link a particular Ada unit (performing compiles as necessary) and generate an executable. Adamake will compile all units registered in the ADA.LIB file but won't link anything. Thus adabuild MAY run the compiler (e.g., for an out-of-date unit) and will always run the system linker (assuming everything to build an executable exists). In contrast, adamake will always run the compiler for every unit defined in ADA.LIB (regardless of the unit being out-of-date) and never run the linker. Adamake is a great way to force everything to become current, whereas adabuild is the only way to create an executable.


Contributed by: Jeffrey D. Cherry
Contributed on: February 22, 1999
License: Public Domain