TOC PREV NEXT INDEX DOC LIST MASTER INDEX



C/C++ Build Management

Apex Build Management for C and C++ provides facilities for the definition, management and customization of build environments. In addition to the general facilities for the definition of build environments, Apex Build Management also provides standard models of build environments which can be used with little or no modification. The majority of this chapter will focus on the characteristics of the standard build models.

Note: Build Management for C and C++ is only available with Apex C/C++ and Apex Duo. For more information about these products, contact your Rational sales representative.


Standard Models for C/C++ Build Management

Standard models for C/C++ build management provide an "out-of-the-box" solution which supports the common build activities of compilation, construction of libraries, and linking of executables. In addition the standard models provide their own methods for customization which are less complex than constructing a build management model from scratch.

The standard build management models provide the following:

Basic Concepts

This section presents a brief overview of how the standard C/C++ build management facilities are used to support compilation and other activities.

All build activities occur in views.The specific characteristics of build activities in a view are determined by the view's build key which is specified by a switch of the same name in the view's switch file. The build key is usually derived from the model which was provided when the view was created. The standard models for C/C++ build management are based on standard build keys which contain the following:

Views utilizing the standard C/C++ build keys and models are created by the ceate_working and create_release commands and copied by the copy_view command. Generally C/C++ views are created using the default C/C++ model which is available in the session switch APEX_DEFAULT_MODEL. When a view is created with a standard C/C++ model all makefiles and directory structures required by the build system are created.

C/C++ source files are usually created by either the create_c or create_cpp commands. These commands create C/C++ header and source files with initial contents that are based on special prototype files which are located in the directory named by the APEX_PROTOTYPE_DIR environment variable. C/C++ files may also be copied into views by Apex commands or by Unix shell commands. Regardless of how files are created, makefiles and related directory structures are updated appropriately by Apex prior to running any build commands.

C/C++ source files are compiled by running the code command. C/C++ source files may directly include any header file within the same view. Header files in other views may only be included if architectural relationships have been established. Namely the view containing the header file must export the header file and the view containing the include must import the view which exports the header file. Header files may be named either by their simple name (for example,. #include "file.h") or by their subsystem-relative name (for example., #include "subsystem/file.h")

The dependencies between an object file and header files are updated automatically as a side-effect of each compilation. Dependencies may also be updated manually by running the dependencies command.

Entire views may be compiled by running the code command on the view itself. Compiling a view causes all source files in the view to be compiled and in addition creates any required libraries. The creation of libraries is controlled by the build policy associated with the view. Different build policies are defined by the standard build keys to allow libraries to be built with different contents or allow externally constructed libraries to be managed. By default, when libraries are constructed all object files are checked and regenerated if they are obsolete including the object files associated with template instantiations.

Prior to linking a main program, the source file containing the main entry point must be registered as a main program. Registration is automatic when Apex C/C++ compilers are used. Manual registration must be performed when running other compilers. Manual registration is accomplished by running the register_main_program command. Actual linking occurs when the link command is run on the registered main program file. The closure of a main program is the set of object files, libraries and option settings which must be passed to the linker in order to link the main program. The closure of a C/C++ main program is computed by first identifying appropriate views and then querying views to determine the contribution which each view will make to the overall closure. Support is also provided for linking C/C++ code in the closure of Ada main programs.

All Summit/CM operations may be applied to C/C++ files. C/C++ files may be placed under version control. When C/C++ files are created, deleted, or copied between views by Summit/CM operations, all appropriate makefiles and directories are automatically updated.

A number of mechanisms are provided for customization of the standard build operations. The customization operations allow standard operations to be augmented or completely redefined.


Build Management Commands

Command Overview

Apex provides a rich set of build management commands which can be used to support the normal activities involved in building software systems. These commands cover different phases of build management from initial preparation of source files, to compilation, test and final delivery. In the various predefined build management models some of these commands have predefined meanings while others are provided for user customization.

The full set of build management commands are summarized below. The following sections provide a detailed explanation of the commands.

Standard Options

The build commands accept a standard set of options which include:

-build_component

In views which support multiple "components" this switch is used to determine the component to which the operation is applied. The standard models support development of C/C++ and Java components, the value of the switch determines whether the C/C++ components, the Java components, or both will be built. For example, if the value of the switch is "cpp" (the default) then applying the code command to the view will cause C/C++ units to be coded but no Java units will be compiled. The possible values are cpp, java, and java_cpp. Note that java_cpp is used when the view contains Java and C/C++ units to compile. The default value in a particular view can be changed by setting the BUILD_COMPONENT context switch in the view.
Default value: cpp

-effort_only

Specifies that the command should only emit information about what the command would do if invoked in the normal way. For example, when the option is applied to the code command, the names of the files requiring recompilation are emitted.
Default value: false

-first_error

If set then processing stops when the first error occurs.
Default value: false

-force

Specifies that operation should be forced to occur even if it is not necessary. For example, when the option is applied to the code command, all arguments are recompiled even if recompilation is not needed.
Default value: false

-imports

When this option is applied to a build command, the command is applied to specified objects and to all imported views of the specified objects. The imported views are processed in the import order so that views which have no imports are processed first.
Default value: false

-make_options make-options

Options that will be passed to each invocation of make. In particular, these options will be passed to make when make is called as part of executing other build commands. For example, setting -make_options to the value "-d" will normally provide tracing of the underlying make command.
Default value: " "

-verbose

Specifies that the command should emit additional informational output. For example, when the option is applied to the code command, invocations of the compiler by make will be emitted along with their arguments.
Default value: false

Main Program Commands

C/C++ source files containing main programs must be registered in order to allow those main programs to be linked and to prevent the object files associated with those main programs from being included in the link of other main programs.

Main program registration occurs automatically when compiling with Apex C/C++ compiler. Therefore, when those compilers are used, the register_main_program and unregister_main_program commands described below need not be used. Whenever non-Apex compilers are used manual main program registration must be performed.

The following commands provide methods to register, unregister and show information about registered main programs. These commands utilize the general mechanisms for source file registration which are discussed later.

Registration Commands

Registered sets provide a general way in which files can be grouped together in order to record some common characteristic of all files in the set. Inclusion in a set or exclusion from a set is one criteria that is used to manage build activities. For example, registered sets are used to keep track of C/C++ source files which contain main programs.

The name of a registered set must be a simple identifier. The file containing the contents of the registered set is stored in the view's Policy directory and has the extension .reg.

Coordination of set membership across views can be accomplished in two ways. Firstly, whenever a new version is propagated by accept_changes between two views, membership in a registered set is also propagated provided that the set exists in the destination view and is not itself controlled. Secondly, a registration file may itself be controlled and propagated between views.

Although arbitrary sets can be created, their use depends on the setting in the C/C++ models. There are two sets defined in the standard C/C++ models:

Compilation (C/C++)

This section presents a detailed description of how compilation is managed by the standard C/C++ models.

Compiler Kinds

The standard models provide support for three different types of compilers. The type of compiler that is being used is identified by the CPP_COMPILER_KIND context switch and should be set to one of the values below:

Compiling C/C++ Files

The standard C/C++ models provide several capabilities for managing compilation of C/C++ source files. These capabilities include:

Compiler Selection

Selection of the compiler to use is based on switches in the view and applies to all compilation and linking in the view. The switches which control compiler selection are normally derived from the model associated with the view. The switches include:

Compiler Switches

Compiler options are stored in the switch file associated with the view and apply to the compilation of all files within the view. The names of the switches are:

For individual compilations the values of the switches may be overridden on the command line by specifying new values for the -cpp_options or -c_options switches.

Non-Apex Compiler Switches

A number of options are provided to control the behavior or non-Apex compilers:

Compilation Artifacts

Compiling source files generates an object file and possibly a number of additional artifact files which are used for debugging, navigation, and dependency management. Compilation artifact files are removed when the clean command is run on the source file.

Compilation Dependencies

Each object file has a number of dependencies. The dependencies include the header files which are referenced by the source file. The dependencies also include other files and switch values which effect the way in which an object file is produced. The full set of dependencies include the following:

Resolution of Include Names

Names in include directives are resolved based on the naming environment constructed by build management and by any explicit -I directives set in the compilation options in the switch file. The default behavior provides direct visibility to header files in all imported views provided those header files have been exported. The later section on Name Space Management describes the ways in which the naming environment can be customized.

Template Instantiations

The standard C/C++ models provide two modes for the management of template instantiation repositories. These two modes are global and local.

Not all of the compiler kinds supported by the standard models support all of the repository modes. In particular, the generic compiler kind only supports the use of global repositories.

The following context switches are used to manage repositories:

Compiling C/C++ Views and Using Build Policies

In the standard C/C++ keys, the build policy of a view defines what happens when a build operation is applied to the entire view. The build policy of a view also defines what the view will contribute when it is involved in linking a main program. For example, the predefined build policy library, specifies that coding a view will cause a library to be created containing the object files in the view. The build policy library also specifies that when the view is in the closure of a main program, the library will be provided as part of the link.

The build policy of a view is specified by the BUILD_POLICY switch in the view's switch file.

Standard Build Policies

The standard C/C++ keys support a number of predefined build policies, including:

Users may also define their own build policies with arbitrary names and semantics. This is discussed in the later section on customization.

Building Libraries

A number of the standard build policies specify that libraries will be constructed when the view is compiled. In general the standard build models are capable of constructing either archive or shared libraries, however shared libraries are not supported for all platforms.

When a build policy specifies that a library is to be constructed there are independent switches which determine whether archived libraries and/or shared libraries are to be built. These switches are called CREATE_ARCHIVED_LIBRARY and CREATED_SHARED_LIBRARY. The default settings in the standard models specify that archive libraries are to be built and shared libraries are not to be built. The name of an archive library is specified by the LIBRARY_NAME context switch and the name of a shared library is specified by the SHARED_LIBRARY_NAME context switch.

Whenever a library is constructed a closure file is also constructed which contains the names of all object files which were included in the library. The closure file has the.closure extension.

There are 5 steps in the construction of either an archive library or a shared library:

1 . Code the Closure

If the switch -closure_compilation_policy is set to compile_all and neither -no_closure_compilation nor -use_existing_closure is set, then code all source files whose objects files will be contained in the library. This will include source files in the current view and in other views depending on the setting of the BUILD_POLICY switch.

2 . Compute the Library Closure

Compute the set of object files that will be included in the library. If the -use_existing_closure option is set and the closure file for the library exists then use the current contents of the closure file to construct the library. Otherwise, reconstruct the closure file by examining the contents of all views which will contribute to the library.

3 . Check Template Instantiations

Template instantiations associated with object files in the library are checked to make sure they are up to date. Instantiation objects which are obsolete will be regenerated. Object files containing instantiation code are included in the library closure file. If a closure file exists and the -use_existing_closure option is set then this step is skipped.

This step will be skipped if the template repository mode is global. Libraries for views with a global template repository mode will not contain any instantiation objects.

4 . Check Library Currency

If a library exists then a check is made to see if the library is up to date with respect to the files in the closure file. If the library is up to date then it will not be rebuilt.

5 . Generate the Library

Generate the library based on the specified closure. Note that the options -no_closure_compilation and -use_existing_closure can significantly reduce the time to generate libraries when it is known that all source files are already compiled and that the desired contents of the library have not changed from the last time the library was constructed.

Name Space Management

The ability of a C/C++ client file to include a C/C++ header file is determined by the visibility and architectural control characteristics of the views containing both files.

Visibility Control

A reference from a client file to an included header file may only be resolved if the naming environment of the view containing the client file has been configured to provide visibility to the included file through the name that is given in the include directive. Visibility control provides a way to specify a naming environment and have Apex automatically construct the directory structures and makefile macros needed to implement that naming environment. A default naming environment is provided as part of the standard model and customization of the naming environment is provided by the visibility description file.

There are two types of file references in include directives which can be resolved in the naming environments constructed by Apex:

Include references based on fully-qualified names are not subject to management by Apex.

There are three directories in each view which are constructed by the standard models as part of the management of naming environments:

The directories named above are normally used by C/C++ models in order to control the naming environment of the compiler through the use of the -I directives to the compiler. For example, the include directives -ILinks/Local and -ILinks/Imported provide immediate access to all local files and qualified access to files in imported views. Other tools may also base their name spaces on these links.

Default Visibility Control

The standard model provides both immediate and subsystem-qualified visibility by default to all header files in the current view and in imported views. Immediate visibility allows a header file to be named by its simple name regardless of which view or directory contains the header file. Subsystem-qualified visibility allows a header file to be named by a two-part name composed of the simple subsystem name (without the .ss extension) followed by the simple header file name. For example, the following illustrates the two default visibility modes:

Visibility Description File

The visibility description file provides a means by which access to header files may be customized for header files in both the current view and in imported views.

Each view may contain a visibility description file which is named Imports/Description.vdf. If a view does not contain a visibility description file then the view is subject to the default visibility control described previously.

A supplier view may also contain a visibility description file which may be used by its clients. This file is named Exports/Description.vdf and is used by all clients of the view in order to determine which type of link should be created for the supplier.


Warning: The contents of Exports/Description.vdf in various views are not tracked by the system and will not cause recomputation of import information when changed unless the
-recompute option is passed to the import command.

A visibility description file contains a series of lines which are either subsystem entries or indirect description entries.

A subsystem entry has the form:

An indirect description entry has the form:

Where the fields of both types of entries have the following meaning:

Visibility description files may also contain comments which begin with the character "#".

Below is an example of a visibility description file which provides the same visibility as the default visibility.

The contents of a view's visibility description file are examined whenever the view's imports are recomputed. For each imported view the visibility description file is searched for any entries which are applicable. If one or more entries are found, all of those entries are applied and symbolic links and makefile macros are adjusted accordingly. If no entry is found for an imported view, then the default visibility control is applied to that import.

Local Visibility Switches

As mentioned earlier, by default the Links/Local directory of a view contains symbolic links to all source files in the view. This behavior may be modified by using the following context switches:

Architectural Control

In addition to being resolved within the naming environment constructed by Apex visibility control, an included file must also satisfy any architectural restrictions. In particular, a client file may only include a supplier file if one of the following is true:

Linking (C / C++)

Linking C/C++ Main Programs

Linking a C/C++ main program requires that the appropriate object files, libraries, and option settings be identified and passed to the platform linker for processing.

In general, linking a C/C++ program has six steps:

1 . The link mode of the main program is identified. The link mode is used to specify whether archive or shared libraries will be linked against.

2 . The view closure sequence is computed. This sequence contains all of the views which will contribute to the link in the proper order.

3 . The views in the closure sequence are compiled if the -closure_compilation_policy switch is set to compile_all and neither -no_closure_compilation nor -use_existing_closure switches are set.

4 . The link contribution of each view is computed. The link contribution of a view contains the object files, libraries, and options which the view contributes to a main program. For views containing libraries, the link mode of the main program determines whether an archive of shared library will be contributed to the link.

5 . The main program contribution is computed. The main program contribution consists of the object file for the main program and additional options specific to the main program.

6 . The platform linker is invoked to perform the link based on the closure that was constructed from the link contributions of all the views in the closure sequence.

If the program has been previously linked and the -use_existing_closure option is set then the previous closure is used and steps 1 to 5 are skipped.

A successful link produces an executable whose name is the root name of the source file which contained the main program.

Main Program Link Modes

The link mode of a main program determines whether archive or shared libraries will be used when linking a main program. The link mode is specified by the -c_link_mode and -cpp_link_mode options for C and C++ main programs respectively.

There are four link modes:

The default settings of switches are such that archived libraries are created and linked against for all build policies which involve libraries.

Computing the View Closure Sequence of a Main Program

The view closure sequence is the sequence of views which will make contributions to the link. The sequence is computed from the imports, an optional configuration specified by the CONFIGURATION switch, and the value of the LINK_CLOSURE_POLICY switch.

Note: The contents of a configuration file should only be those units not already included in the import closure.

For the different values of LINK_CLOSURE_POLICY, the closure sequence is composed of the following:

Computing the Link Contribution for Views in a Closure

The link contribution of a view contains the object files, libraries, and options which the view contributes to the link of a main program. The link contribution is dependent on the link mode of the main program being linked.

The link contribution of a view usually has three parts:

1 . The value of the LINK_CONTRIBUTION_PRE_OPTIONS switch (if objects files or an archived library are being contributed) or the value of the LINK_CONTRIBUTION_SHARED_PRE_OPTIONS switch (if a shared library is being contributed).

2 . The content of the view which is usually either the object files or the libraries in the view. When archive libraries are specified then the content is the value of the LINK_CONTRIBUTION_LIBRARY context switch. When shared libraries are specified then the content is the value of the LINK_CONTRIBUTION_SHARED_LIBRARY context switch.

3 . The value of the LINK_CONTRIBUTION_OPTIONS switch (if objects files or an archived library are being contributed) or the value of the LINK_CONTRIBUTION_SHARED_OPTIONS switch (if a shared library is being contributed).

The content of the view is determined by the setting of the BUILD_POLICY switch in the view.

For example, consider a view whose build switches are as shown below:

This view would contain an archive library called foo.a and a library closure file called foo.a.closure, but the view would not contain a shared library. Whenever the view is included in the closure of a main program, the view would contribute the archive library foo.a, unless the link mode dynamic was specified, in which case an error would occur.

For another example, consider a view containing an external library libxyz.a which is to be statically linked into any programs that require it. An appropriate setting for entries in this view's switch file would be:

Computing the Main Program Link Contribution

The main program contribution is composed of three parts:

1 . The main program's object file.

2 . The value of the CPP_LINK_PRE_OPTIONS switch for a C++ program (or C_LINK_PRE_OPTIONS for a C program). The value of this switch will precede the link contributions for all views.

3 . The value of the CPP_LINK_OPTIONS switch for a C++ program (or C_LINK_OPTIONS for a C program). The value of this switch will follow the link contributions for all views.

Invoking the Platform Linker

When all contributions have been computed the platform linker is invoked with an argument list that contains the main program contribution and the contributions from all of the views in the closure sequence. The view contributions occur in the order defined by the sequence. The full argument list to the platform linker is saved as part of every link in the file <main>.closure.

Linking Ada Programs Containing C/C++ (Apex Duo only)

Ada programs may be linked with C/C++ in their closure. The view containing the Ada main program must have been enabled for C/C++ linking by the enable_cpp_linking command. When an Ada program is linked against C++, the link occurs in three steps:

1 . The Ada pre-linker is run to compute the Ada closure in the usual way.

2 . The C/C++ closure is computed and recompiled as if the main program were a C/C++ program. Recompilation of the C/C++ closure can be prevented by setting the -no_cpp_closure_compilation option.

3 . The closures are combined (with the Ada closure preceding the C/C++ closure) and then the platform linker is run as if the main program were C/C++.

More information on linking Ada programs containing C/C++ can be found in the Programmer's Guide and the Ada Compiler Reference.

Customization (Build Management)

Apex provides a number of ways in which the standard build management mechanisms can be customized for individual views. Customization capabilities include modifying existing build policies and defining new build policies. Customization of individual object types may also be accomplished by defining the objects and their operations.

Customization is performed by modifying the contents of the following two files:

Customizing Build Policies

Build Policy Implementation

The build policy for a view defines the actions that occur when a build operation is applied to the view as a whole. The build policy affects the standard build operations, including:

The build policy also effects two queries that are made of views:

In the standard keys, whenever a build operation or query is applied to a view, make is invoked in such a way as to build the target "build-policy.operation-or-query". For example, when the code command is run on a view with build policy library, make will eventually be asked to build the target "library.code".

Each build policy must define targets for all of the standard operations and queries. For example, the build policy library, which causes the view to construct a library from all object files in the view and provide the library as the link contribution of the view, has the following targets which implement the policy.

Customizing Existing Build Policies

The existing build policies may be customized through the use of trigger macros whose values can be set in the customization makefile Policy/Customization.mk. For each of the standard operations (although not for the standard queries), there are two macros:

Creating New Build Policies

Users may also define their own build policies. The Customization.mk contains the full set of targets necessary to define the build policy custom_build. Users may define the semantics of the custom_build policy by associating actions with targets. When the custom_build policy has been defined, it will be activated in the view by setting the BUILD_POLICY switch to custom_build.

The custom_build policy (and any other user policy) should make free use of the standard targets defined for other policies. For example, if the code operation for custom_build was to perform the same operation as that for the library policy then one could define the following target:

Customizing Build Properties for New File Classes

In addition to defining and modifying build policies for entire views it is also possible to define new classes of objects and the commands which will be applied to those objects. For example, it is possible to define a new class of object for YACC files and to define the meaning of build management commands when they are applied to YACC files.

Customization of build properties occurs in the Policy/Customization.prop file.

Defining New Object Classes

New object classes are defined by modifying the Subclasses property in the Policy/Customization.prop file. The format of the file is shown below.


Warning: The syntax of the first line, "{Subclasses:+" implies that the subclass entries in this table will be added to the overall set of subclasses entries. If the "+" was absent then these entries would replace all of the predefined entries .

where each field has the following meaning:

For example, in order to define a new class for YACC files the following could be used:

Command Translation Tables

Command translation tables are used to determine the meaning of a particular build command on a particular class of object. The command translation table is a property in the file Policy/Customization.prop. The command translation table can be used to define any shell command which should be executed when the original command is applied to the designated type of object.

The format of a command translation table is shown below.


Warning: Note that the syntax of the first line, "{Command_Translation:+" implies that the translation entries in this table will be added to the overall set of translation entries. If the "+" was absent then these entries would replace all of the predefined entries.

The fields in a command translation entry have the following meaning:

For example, assuming that the makefiles contain suffix rules to generate .c files from .y then the prepare command on YACC objects can be defined as shown below:

In the example above, the apexsummit command

will be translated into the command:

The actual selection and execution of command strings proceeds according to the following steps:

1 . The original arguments to the build command are placed in sets. Each set contains objects which have the same class and the same parent directory.

In the example above the set of objects would contain the source file foo.y.

2 . For each object set, the command translation table is searched for the command translation for the specified class. If no entry for the specified class is found then the table is searched for an entry for the parent class. If no command translation is found for the original class or any parent class then an error is emitted and no further processing occurs.

3 . If a command string is identified then the string undergoes keyword replacement in the context of the set of objects.

In the example, above the keyword <dir> would be replaced the name of the directory containing the set of objects, and the keyword string {<object:t:r>.c, } would be replaced by the name of the object with the parent directory removed and the original extension .y replaced by the new extension .c. Note that the because the keyword <object:t:r> was placed in braces, if the original command was applied to multiple objects in the same directory then all objects in the set would be processed.

4 . The resulting string (with keywords replaced) is executed in a Bourne shell subprocess. If the string contains separators of the form "<;;>" then the separate substrings are executed consecutively in separate shells.

Utility Translation Table

Utility actions are invoked when certain events happen to files or directories in specified object classes. The recognized events are:

The utility translation table has the same format as the command translation table:

The fields in a command translation entry have the following meaning:

For example, below is a utility translation table containing empty command strings for all of the events defined for YACC files.

Directory Structure

Views that utilize the standard C/C++ models have a directory structure that is illustrated below.

The objects have the following meaning:

Context Switches for Build Management

This section presents the context switches associated with C/C++ Build Management. The meaning of these switches in the standard C/C++ models is described.

The default value are used if the switch is not set in the switch file.

General Build Management Switches

C Compilation and Linking Switches

C++ Compilation and Linking Switches

Java Compilation and Linking Switches

Assembly File Switches

Local Visibility Switches

Link Contribution Switches

Delivery Switches

Non-Apex C/C++ Compilation Switches

These options are provided to control the behavior when non-Apex compilers being used to generate code (i.e., when CPP_COMPILER_KIND is not set to apex),

Ada Linking Switches (Apex Duo only)


Rational Software Corporation 
http://www.rational.com
support@rational.com
techpubs@rational.com
Copyright © 1993-2002, Rational Software Corporation. All rights reserved.
TOC PREV NEXT INDEX DOC LIST MASTER INDEX TECHNOTES APEX TIPS