PowerAda PowerAda Projects
A PowerAda project is a hierarchy of directories, files, executables, and sublibraries rooted at a single directory. A project can contain all the components needed to build and update a single application or a suite of applications. The project can be organized in any fashion: with everything located in the root of the project (for small applications), or with separate components located in different directories within the project (for large application suites). All directories/files/sublibraries in a project will be identified by a relative name within the project; this is the project-relative name of the directory, file or sublibrary.
There are two type of projects: working projects and baseline projects (or simply baselines). A working project provides an updatable set of directories, files, executables, and sublibraries for an individual developer. When a working project has reached an acceptable level of stability/completeness, the working project may be baselined (frozen). A baseline project may be imported into a developer's working project so that the developer may work against all the files and sublibraries in the baseline project. The baseline project may, in turn, import another baseline project, and so on. A (working or baseline) project which imports a baseline project (i.e., has a non-null parent baseline) is called a delta project.
In the view of the developer, the working project will have all the files that the baseline project has and the developer will have the ability to modify/recompile/rebind any file in the working project to perform actual work. In reality, only the modified files will exist in the working project, and all unchanged files will exist in the baseline project(s). A file or unit that exists in a baseline project but is visible in the working project is called shadowed. A file or unit that exists in the working project is called local, and it hides or "covers" the same file or unit in any imported baseline projects. Some special issues raised by this multi-layer approach, such as gaining and hiding visibility to shadowed entities, are described in Chapter 5, "Hide deleted files."
In practice, a large Ada development effort will consist of tracking changes to source files using a CM system. A build team will extract a complete set of files (including Ada source) from the CM system and create a baseline project by first creating a working project, populating the working project with the files from CM, and then building/compiling all the files in the working project. Once the working project has been tested and determined to be usable by others on the project, the build team will baseline the project and allow other developers to import this baseline project into their working projects.
Typically, the contents of a baseline project will be controlled by a CM process on a large project. Users will check in various fixes and the build team will provide various baseline projects based on these changes to the rest of the development team. Since baseline projects are read-only, a developer may use a particular baseline project for making changes in a working project, without worrying that someone will change things in that baseline project. The individual user can decide when to start working with a newer baseline project, rather than having things change "underneath him."
Baseline projects do not have to be full builds, but may themselves be based on a previous baseline project (with only the changed files/sublibraries actually being present in the new baseline project). This capability will allow the build team to do periodic incremental builds for developers to work against without disturbing other developers still working with the previous baseline projects.
A more complete description of how to use PowerAda projects for development is provided in Chapter 5, "Project Management with PowerAda".
A working project has the following characteristics:
- It is accessed by only one user at a time. In fact, each user will probably have a personal project (or multiple projects). That is, a working project is not shared (at least while it is being worked on).
- It is identified by its root directory.
- It is created/updated/deleted by the user.
- It may contain any file that the user wishes and may be organized in any manner that the user chooses.
- A working project may be "frozen" (or "published") by the user by converting it into a baseline project.
A baseline project has the following characteristics:
- It was created as a working project and was later baselined by the user.
- Its contents are read-only and cannot be changed.
- It can be accessed by many different users as the basis for their working projects.
- It is identified by its root directory. A baseline project may also have an alias defined in a PowerAda baselines file to provide more meaningful names.
Projects can be built either interactively using the PowerAda Navigator and Build Manager ( See Chapter 4, "The PowerAda Development Environment"), or they may be constructed in batch mode using command-line tools ( See "aprojinit" in Appendix E).
Project Libraries and Sublibraries
PowerAda stores intermediate code files and dependency information associated with compiled Ada units required by the Ada language specification in the Ada library. All compilations, browsing operations, and unit reports are performed against an Ada library.
In all OC Systems' compilers, a library consists of one or more sublibraries, listed in a specific order. If a unit U1 compiled into sublibrary S1 references (withs) another unit U2 compiled into sublibrary S2, then we say that U1 imports U2 and S1 imports S2. In earlier versions of PowerAda, a sublibrary and the transitive closure of all its imported sublibraries were listed in a library list file ( See "Alternate Libraries" below). While this is still supported outside a project, PowerAda now supports the Ada library concept with a project library.
A project library is an ordered set of sublibraries identified by the root sublibrary, and comprises all the sublibraries imported by the root sublibrary and all the sublibraries imported by those sublibraries, and so on. The user need only specify the root sublibrary and PowerAda automatically constructs the list of all imported sublibraries (from each sublibrary's imports file) when needed. The order of the sublibraries, as determined by the sublibrary import dependencies, will determine the specific version of a compilation unit that is used if there is more than one version of a unit in the library. However, PowerAda's automatic recompilation tools do not support compiling the same unit into two different root sublibraries within a project.
The root sublibrary is the only sublibrary that can be updated during a single compilation operation, so it is also known as the working sublibrary. New information about the unit being compiled is stored only in the working sublibrary. If other sublibraries are present in the library, they may be read, but not updated. (Note, however, that automatic recompilation often results in multiple compilation operations, and each of these may write to a different working sublibrary.)
A project sublibrary is implemented as a UNIX directory that contains all the required information. Generally, the sublibrary directory, (named
adalib), is created and maintained by PowerAda. Associated with each sublibrary directory is a sublibrary imports file, which is located in the same directory as the sublibrary directory. Together these form a project library.
Directories and Sublibraries
A PowerAda project may contain any number of directories organized in any desired hierarchy. The directory hierarchy within a project can be used to organize the components of the application or applications under development. Simple applications can use a single directory to contain all the source and other files needed to build the application. More complex applications or application suites can divide the software into logical components and use a separate directory to hold and build each component.
Within a PowerAda project, a directory can contain any number of source files (among other things) but just a single sublibrary. The source files in a directory are normally compiled into the sublibrary associated with the directory containing the source. This may influence how one would partition a complex set of sources into directories.
The Sublibrary Imports File
The sublibrary imports file (named
adalib.imports) is a single list identifying other sublibraries required by the sublibrary in the same directory. This single list is the only file that needs to be updated to add visibility to another sublibrary.
If all the Ada units need for a program are compiled into the same sublibrary, the
adalib.imports file should be empty (or contain only comment lines). If another sublibrary contains a unit needed by a unit in this sublibrary, the adalib.imports file must contain the project-relative name of that sublibrary, for example:
A special sublibrary imports file can be used to indicate that source files should be compiled into a sublibrary in a different directory than the current one. This file contains just one line:
This technique can be used to partition the source and sublibraries in different ways ( See Chapter 5, "Separating Source from Sublibrary").
adalib.imports file is central to building non-trivial programs in PowerAda, and is described in a more concrete manner in Chapter 5, "Creating Initial adalib.imports Files".
Source Files and Compilation Units
Ada source files are normal UNIX text files. Within a PowerAda project, source files are distributed throughout the directory hierarchy (typically by logical component) according to the needs of the application. Ada source files can contain one or more compilation units, though they usually contain a single compilation unit. During compilation, the compilation units in a source file are placed in the sublibrary contained in the directory containing the source file, except as noted above.
Within a PowerAda project, compilation is actually a two-step process. First the source file is loaded into the appropriate sublibrary. This step identifies the new compilation unit or units contained in the source file and the dependencies between the new unit or units and other units in the library. The second step involves compiling (generating code for) the new loaded unit or units, which requires that all the units on which the new unit or units depends be compiled first. The PowerAda Build Manager will take care of these requirements automatically once the files have been loaded. The Build Manager can also re-load files that have changed since the compilation unit was last compiled.
The Sublibrary Files File
A source file is associated with a sublibrary when it is compiled or loaded into that sublibrary. However it is useful and often necessary to identify the files to be compiled into a sublibrary explicitly, before the compilation process. The mechanism to identify which files are to be compiled into a given sublibrary is the sublibrary files file,
adalib.files. This file contains the project-relative names of all files to be compiled into the sublibrary in the same directory. It can name files in other directories, as long as that directory contains an
adalib.imports file that points back to the sublibrary with a
use directive as described above.
The presence of correct and complete sublibrary files file allows aprojbuild (the PowerAda automated compilation tool) to automatically identify the files to be compiled, and allows other tools to recognized the named files as Ada files regardless of their name. See Chapter 5, "Creating Initial adalib.files Files"
PowerAda executable files are created by binding all the compilation units required for an Ada program together with any external object modules and object archive files. The required compilation units are determined by PowerAda based on the main subprogram selected by the user. PowerAda uses the dependency information stored in the project library to form the transitive closure of all the units withed by the main unit. External object modules and archives can be specified explicitly with pragma Linker_Options, bind-time options or in sublibrary imports file ( See Chapter 7, "Interface to Other Languages").
PowerAda then passes the entire collection of object modules and archives to the linker to resolve all the inter-module references. PowerAda appends additional information to the executable image about the contained compilation units and the project library and sublibraries used to build the executable. This information permits the user to browse units in the executable and to rebind the executable with the latest versions of the contained compilation units. The user can also determine the exact version of a source file used to build the executable with the CM information (specified by pragma sccs_id) which PowerAda stores in the executable.