United States |
Previous | Contents | Index |
The C++ template instantiation model includes the following features:
A C++ template is a framework for defining a set of classes or functions. The process of instantiation creates a particular class or function of the set by resolving the C++ template with a group of arguments that are themselves types or values. For example:
template <class T> class Array { T *data; int size; public: T &operator[](int); }; |
The code in this example declares a C++ class template named Array that has two data members named data and size and one subscript operator member function. Array<int> instantiates Array with type int . This instantiation generates the following class definition:
class Array { int *data; int size; public: int &operator[](int); }; |
The compiler supports instantiation of C++ class, function, and static
data member templates. The following sections describe the alternative
methods available for instantiating templates: automatic or manual
instantiation.
5.2 Automatic Template Instantiation
In automatic template instantiation mode, the compiler attempts to instantiate every referenced template at compile time. For automatic instantiation to work, at least one compilation that references a template function must be able to find the template definition. There is no restriction on where a template can be declared or defined, as long as the definition is visible to the compilation unit. You can use implicit inclusion to find it.
The compiler writes instantiation object files to a directory called
the repository; file names are based on the names of the entities being
instantiated. The default repository is
./cxx_repository
.
5.2.1 Specifying Alternate Repositories
You can use the -ptr command-line option to specify one or more alternate repository directories. The first repository named is the read-write repository into which the compiler writes instantiation objects when processing. At link time, all repositories are read only. There is one object file in the repository for each instantiated template function, for each instantiated static data member, and for each virtual table required for virtual functions.
When the program is linked, the linker searches the repositories for
needed template instantiations.
5.2.2 Reducing Compilation Time with the -ttimestamp Option
To keep instantiations up to date, the compiler always instantiates templates by default, even if the required template already exists in the respository. However, in environments that share many templates among many sources, this process can increase compilation time.
In these environments, users can specify the -ttimestamp option to override the default behavior and thereby reduce compilation time. This option causes the compiler to create a timestamp file named TIMESTAMP in the repository. Thereafter, instantiations are added or regenerated only if needed; that is, if they do not alreay exist, or if existing ones are older than the timestamp.
The -ttimestamp option is immediately useful when building a system from scratch, starting with an empty repository. It avoids reinstantiating unchanged code and is totally safe, because all required instantiations are generated and up to date.
Incremental application building is normally done without this option, so that new instantiations overwrite earlier ones as sources are recompiled.
Although the -ttimestamp option is intended mainly for initial builds, you can use it for ongoing development in a structured way. Because the compiler creates a new timestamp file only if one does not already exist, you must remove or modify any existing timestamp file before making changes to your code base. This procedure ensures that all subsequent compilations generate up-to-date instantiations. In the following example, the file is removed before and immediately after the compilation of a.cxx , b.cxx , and c.cxx .
rm cxx_repository/TIMESTAMP cxx -ttimestamp -c a.cxx cxx -ttimestamp -c b.cxx cxx -ttimestamp -c c.cxx rm cxx_repository/TIMESTAMP |
The compiler generates all instantiations needed by a.cxx , b.cxx , and a.cxx only once, as opposed to the default scheme, in which it would generate them once for each module that used the instantiations.
Specifying the
-ptv
option causes the compiler to emit an informational message naming the
instantiation and repository file being skipped in this mode.
When implicit inclusion is enabled, the compiler assumes that if it
needs a definition to instantiate a template entity declared in a
.h
or
.hxx
file, it can implicitly include the corresponding implementation file
to obtain the source code for the definition.
If a template entity
ABC::f
is declared in file
xyz.h
, and if an instantiation of
ABC::f
is required in a compilation but no definition of
ABC::f
appears in the source code, the compiler checks whether a file
xyz.cxx
exists. If it does, the compiler processes it as if it were included at
the end of the main source file.
When looking for a template definition, the compiler uses the following
lookup order:
For source files, the appropriate suffixes are, in order of preference:
.cxx
,
.CXX
,
.C
,
.cc
,
.CC
,
.cpp
, and
.c
, or as defined by the
-ptsuf
command-line option.
The compiler ignores any file extension that does not begin with a dot
(.).
The
-ptsuf
command-line option allows the user to explicitly define the file
extensions to be used with implicit inclusion. For example:
5.3 Implicit Inclusion
cxx -ptsuf ".CPP.CC" file.cxx |
This command searches for template definition files with the extensions
.CPP
and
.CC
.
In general, the use of automatic template instantiation is transparent
to the user. Automatic template instantiation is enabled by default.
The following commands are equivalent:
5.3.1 Compiling Programs with Automatic Instantiation
cxx file.cxx cxx -pt file.cxx cxx -pt -ptr ./cxx_repository file.cxx |
These commands:
You can specify the repository explicitly with the -ptr switch. For example:
cxx -pt -ptr /project/repository -c file.cxx |
This command compiles file.cxx , produces a file.o in the current directory, and puts instantiated template files in the directory /project/repository .
The compiler attempts to instantiate templates at compile time; therefore, any specialization used in the program must be declared in each file in which the specialization is referenced, to prevent the instantiation of the overridden template function.
If a template instantiation refers to a static function, that function is created as an external entry point in the primary object file, and the instantiation object file in the repository then refers to this __STF function.
If the template instantiation is linked into an application that does
not have the original primary object file, an unresolved reference to
the
__STF
function occurs. If this happens, recompile an object file that
regenerates the instantiation or use manual instantiation to
reinstantiate the template.
5.3.2 Linking Programs with Automatic Instantiation
When all source files are compiled and linked in the same step, the operation is transparent. For example, the following command compiles a.cxx and b.cxx , writes instantiations to ./cxx_repository , and links the application using the object files and the instantiations from ./cxx_repository :
cxx a.cxx b.cxx |
When compiling and linking an application in separate steps, the repositories that were used during the compilation step must be used in the link step as well. For example, the following command uses ./cxx_repository implicitly in both the compile and link step:
cxx -c a.cxx b.cxx cxx a.o b.o |
If a repository is explicitly named in the compile step, then it must also be named in the link step. For example:
cxx -c -ptr my_repository a.cxx b.cxx cxx -ptr my_repository a.o b.o |
It is easiest if the compilation of all sources use the same repository:
cxx -c -ptr my_repository a.cxx cxx -c -ptr my_repository b.cxx cxx -ptr my_repository a.o b.o |
If different repositories are used for the compilation of the sources, then all repositories must by specified on the link step, as follows:
cxx -c -ptr repository1 a.cxx cxx -c -ptr repository2 b.cxx cxx -ptr repository1 -ptr repository2 a.o b.o |
At link time, the specified repositories are searched in the order given, to find the required instantiations. If one of the repositories used is the default repository, it must be explicitly specified on the link step if more than one repository is used, as follows:
cxx -c a.cxx cxx -c -ptr repository2 b.cxx cxx -ptr ./cxx_repository -ptr repository2 a.o b.o |
It is usually much easier and safer to use a single repository, because the same instantiations could potentially be present in multiple repositories, and it is possible to update some but not all repositories when changes are made to templates.
The link phase of cxx processes object files so that all the external symbol references are resolved. The objects are linked together in the following order:
The following apply to instantiations:
The compiler provides the following methods to instantiate templates manually:
The next sections describe the following instantitation directives:
#pragma define_template
#pragma instantiate_template
#pragma do_not_instantiate_template
The compiler provides a mechanism for manual instantiation, using the
#pragma define_template
directive. This directive lets you tell the compiler what class or
function template to instantiate in conjunction with the actual
arguments with which the template is to be instantiated. The
#pragma define_template
directive has the following format:
#pragma define_template identifier
<template_arguments>
Identifier is the name of the class or function template that the compiler is directed to instantiate at compile time. For the instantiation to succeed, the definition of the template must appear before the #pragma define_template directive.
Template_arguments is a list of one or more actual types that correspond to the template parameters for the particular class or function template being instantiated. Whatever type is specified is used as the type for the instantiation.
The following is an example of a valid template manual instantiation:
//main.cxx #include <stdlib.h> template <class T> void sort (T*); int al[100]; float a2[100]; int main() { sort(a1); sort(a2); return EXIT_SUCCESS; } //sort.cxx template <class T> void sort (T *array) { /* body of sort */ } #pragma define_template sort<int> #pragma define_template sort<float> |
To compile and link these sources, enter the following command:
cxx -nopt main.cxx sort.cxx |
When you use #pragma define_template or explicit instantiation, only the specified template is instantiated; templates to which it refers because of member types or base classes are not instantiated.
Sorting an array of template class elements requires the use of additional pragmas for the module sort.cxx . For example:
template <class T> void sort (T* array) { /*body of sort*/ } template <class T> class entity { public: T member; int operator < (const entity<T> &) const; } template <class T> int entity<T>::operator < (const entity<T> &operand) const { return member < operand.member; } int al[100]; float a2[100]; entity<int> a3[100]; #pragma define_template sort<int> #pragma define_template sort<float> #pragma define_template sort<entity<int> > void sort_all_arrays () { sort(a1); sort(a2); sort(a3); } |
The define_template pragma is position sensitive. If a define_template occurs lexically before a function, member function, or static data member template definition, the compiler is unable to instantiate the corresponding template because the body of that template is not present before the pragma directive.
The compiler instantiates all instances of sort and of entity::operator < needed for this compilation unit.
To organize a program to use the define_template pragma, you can place the declarations of class and functions templates into header files, and instantiate all instances of a particular template from a single compilation unit. The following example shows how to do this:
// sort.h #include <stdlib.h> template <class T> void sort (T*); // entity.h template <class T> class entity { public: T member; int operator < (const entity<T> &) const; }; // main.cxx #include "sort.h" #include "entity.h" int al[100]; float a2[100]; entity<int> a3[100]; int main() { sort(a1); sort(a2); sort(a3); return EXIT_SUCCESS; } // sort.cxx #include "sort.h" #include "entity.h" template <class T> void sort (T* array) { /*body of sort*/ } #pragma define_template sort<int> #pragma define_template sort<float> #pragma define_template sort<entity<int> > |
Compiling the following file provides a definition of entity::operator < with type int :
// entity.cxx #include "entity.h" template <class T> int entity<T>::operator < (const entity<T> &operand) const { return member < operand.member; } #pragma define_template entity<int> |
To compile this example, issue the following command:
cxx main.cxx sort.cxx entity.cxx |
If the program uses other instantiations of entity in other compilation units, you can provide definitions of operator < for those entities by adding define_template pragmas to entity.cxx . For example, if other compilation units use the following instantiations of entity , appending the following pragmas to entity.cxx causes the compiler to generate instantiations of operator < for those requests of entity:
entity<long> and entity< entity<int> >, #pragma define_template entity<long> #pragma define_template entity< entity<int> > |
The compiler also provides several pragmas that provide fine control over the instantiation process. Instantiation pragmas, for example, can be used to control the instantiation of specific template entities or sets of template entities. There are two instantiation pragmas:
The argument to the instantiation pragma can be:
a template class name | A<int> |
a template class declaration | class A<int> |
a member function name | A<int>::f |
a static data member name | A<int>::i |
a static data declaration | A<int>::i |
a member function declaration | void A<int>::f(int, char) |
a template function declaration | char* f(int, float) |
A pragma in which the argument is a template class name (for example, A<int> or class A<int> is equivalent to repeating the pragma for each member function and static data member declared in the class. When instantiating an entire class, a given member function or static data member may be excluded using the do_not_instantiate pragma. For example:
#pragma instantiate A<int> #pragma do_not_instantiate A<int>::f |
The template definition of a template entity must be present in the compilation for an instantiation to occur. If an instantiation is explicitly requested by use of the instantiate pragma and no template definition is available or a specific definition is provided, an error is issued.
template <class T> void f1(T); // No body provided template <class T> void g1(T); // No body provided void f1(int) {} // Specific definition #include <stdlib.h> int main() { int i; double d; f1(i); f1(d); g1(i); g1(d); return EXIT_SUCCESS; } #pragma instantiate void f1(int) // error - specific definition #pragma instantiate void g1(int) // error - no body provided |
The functions f1(double) and g1(double) are not instantiated (because no bodies were supplied) but no errors are produced during the compilation (if no bodies are supplied at link time, a linker error is produced).
A member function name (for example, A<int>::f can be used as a pragma argument only if it refers to a single user-defined member function (that is, not an overloaded function). Compiler-generated functions are not considered, so a name may refer to a user-defined constructor even if a compiler-generated copy constructor of the same name exists. Overloaded member functions can be instantiated by providing the complete member function declaration:
#pragma instantiate char* A<int>::f(int, char*) |
The argument to an instantiation pragma must not be a
compiler-generated function, an inline function, or a pure virtual
function.
The following sections discuss templates in the context of advanced
program development.
The compiler does no dependency management of its own. Because template
instantiations are compiled when source files that reference those
instantiations are compiled, those source files must be recompiled if
the template declaration or definition changes.
The
-M
output from the compiler lists the implicitly included files, so that
the
make
program can automatically recompile any source files that depend upon
template files. If
make
is not being used, it is the user's responsibility to ensure that
instantiations that have changed are recompiled. The user does so by
recompiling at least one source file that references the changed
instantiations.
The compiler does not check command line dependencies of template
instantiations at link time. If you compile two different source files
that instantiate a specific template with two different sets of
options, the last option setting affects the template instantiation.
Use consistent option settings for each build into each repository.
Object files that have been compiled using manual instantiation can be
linked freely with objects that have been compiled using automatic
instantiation. To ensure that the template instantiations needed by the
files compiled with automatic instantiation are provided, the
application must be linked using automatic instantiation, and the
appropriate repositories must be present.
When a template instantiation is present in an explicitly named object
file or object library it takes precedence over the same named
instantiation in a repository.
Creating libraries with object files created with automatic
instantiations is relatively straightforward. You must decide where the
instantiations that were generated automatically are provided to the
users of the library.
For applications that use the library to link successfully, all
template instantiations that are needed by the code in the library must
be available at link time. Because template instantiation happens at
compile time, the object files that contain the instantiated templates
must be available at link time. This can be done in two ways:
It is usually easiest to put the instantiations in the library. This is
a good choice if the instantiations are internal to the library and are
not instantiated directly by the user's code. To put the instantiations
in the library, add all of the object files in the repositories
required by the library into the library, as shown in the following
example:
5.5 Advanced Program Development and Templates
5.5.1 Dependency Management
5.5.2 Mixing Automatic and Manual Instantiation
5.5.3 Creating Libraries
cxx -c -ptr lib_repository a.cxx b.cxx c.cxx ar r mylib.a a.o b.o c.o lib_repository/*.o |
If the template instantiations can be overridden by the user, the templates should be provided in a repository that the user specifies after all the user's repositories. For the previous example, create the library as follows:
cxx -c -ptr lib_repository a.cxx b.cxx c.cxx ar r mylib.a a.o b.o c.o |
When linking the application, the user would specify lib_repository as the last read-only repository on the line as follows:
cxx -c -ptr ./cxx_repository -ptr lib_repository user_code.cxx mylib.a |
The user must explicitly name the repository when linking, even if it is the default repository ./cxx_repository . The compiler first satisfies all unresolved instantiations from ./cxx_repository , and then it uses lib_repository to resolve any remaining unresolved instantiations.
Only the instantiations that are required by the code in the library
are generated in the library repository
lib_repository
. If you must provide other instantiations that the user requires but
cannot instantiate, you must provide these instantiations using manual
template instantiation.
5.5.4 Creating A Common Instantiation Library
If you want to put all current instantiations into a common instantiation library, follow these steps:
The following examples show how to create a common instantiation library for all the instantiations currently being automatically instantiated for this file.
// foo.cxx #include <stdlib.h> #include <vector> #include "C.h" int main() { vector<C> v; v.resize(20); return EXIT_SUCCESS; } // C.h #ifndef __C_H class C {}; #endif |
Compiling with the -ptv option shows which instantiations occur automatically:
Writable_repository: ./cxx_repository Repository_list: ./cxx_repository cxx: Info: /usr/proj/decc2/mainline/exxalphaosf/stdlibinclude/vector.cc, line 90: automatically instantiating void std::vector<C, std::allocator<C > >::resize(unsigned long) void vector<T,Allocator>::resize (size_type new_size) // etc. etc. |
// inst.cxx #include <vector> #include "C.h" #pragma instantiate void std::vector<C, std::allocator<C > >::resize(unsigned long) #pragma instantiate void std::vector<C, std::allocator<C > >::insert(C *, unsigned long, const C &) #pragma instantiate void std::vector<C, std::allocator<C > >::__insert(C *, unsigned long, const C &, __true_category) #pragma instantiate C *std::copy_backward(C *, C *, C *) #pragma instantiate void std::fill(C *, C *, const C &) #pragma instantiate C *std::copy(C *, C *, C *) #pragma instantiate const unsigned long std::basic_string<char, std::char_traits<char >, std::allocator<void> >::npos |
#ifndef __C_H class C {}; #ifndef __BUILDING_INSTANTIATIONS #pragma do_not_instantiate void std::vector<C, std::allocator<C > >::resize(unsigned long) #pragma do_not_instantiate void std::vector<C, std::allocator<C > >::insert(C*, unsigned long, const C &) #pragma do_not_instantiate void std::vector<C, std::allocator<C > >::__insert(C*, unsigned long, const C &, __true_category) #pragma do_not_instantiate C *std::copy_backward(C *, C *, C *) #pragma do_not_instantiate void std::fill(C *, C *, const C &) #pragma do_not_instantiate C *std::copy(C *, C *, C *) #pragma do_not_instantiate const unsigned long std::basic_string<char, std::char_traits<char >, std::allocator<void> >::npos #endif #endif |
cxx -D__BUILDING_INSTANTIATIONS -c inst.cxx |
cxx foo.cxx inst.o |
To verify that your procedure worked correctly, you can remove all files from the cxx_repository subdirectory before you compile foo.cxx . This subdirectory should contain no instantiations after linking with the inst object file.
If you have an
inst.cxx
file that contains many instantiations and you do not want all the
symbols in the
inst
object file to be put into a user's executable even if only some
symbols are used, (as happens with archive libraries), you can either
split the
inst.cxx
into many smaller source files, or specify the
-tused_repository
qualifier to create the instantiations as separate object files in the
repository (see Section 5.6). You must then link all the required
individual object files in the repository into your library.
As shown in Section 5.5.4, multiple repositories can be specified to
link an application. The first repository named is the read-write
repository, and when processing, the compiler writes instantiation
object files into it. At link time, all repositories are read only.
The repositories are searched in a linear order, iteratively, and
satisfy only the unresolved instantiations from each pass. That is,
references from instantiations that are added in one pass are not
resolved until the next pass. Consider the link line in the previous
example:
5.5.5 Multiple Repositories
cxx -c -ptr ./cxx_repository -ptr lib_repository user_code.cxx mylib.a |
In this example, all references that could be resolved from
lib_repository
would be resolved in the first pass. Any reference arising from an
instantiation in
lib_repository
in the first pass would be resolved by instantiations in
./cxx_repository
in the second pass.
Compaq C++ includes various template instantiation modes that control
when, where, and how a template is instantiated:
A C++ program can cause the compiler to perform a template
instantiation in two ways: explicitly or implicitly. A template
instantiation is explicitly requested by using #pragma
define_template, #pragma instantiate, or an
explicit instantiation request (see Stroustrup, section C.13.10). A
template instantiation is implicitly requested by simply using the
template. Requesting a template instantiation explicitly is referred to
as manual instantiation, while the process by which the compiler
instantiates implicit requests is referred to as automatic template
instantiation.
When a template is manually instantiated, it is completely
instantiated. For a template class, a complete instantiation means all
its member functions and static data members are instantiated even if
they were not used. Automatically instantiated templates may optionally
be completely instantiated.
Each of the following modes is mutually exclusive. Only one should be
specified on the command line:
The cxx command supports the following additional options for the
instantiation of templates: 5.6 Template Options
-pt
Automatically instantiate templates into the repository with external
linkage. Manually instantiated templates are placed in the output
object with external linkage. This option is the default.
-tused
Similar to -pt, except that automatically instantiated
templates are placed in the output object.
-tused_repository (cxx -newcxx only)
Similar to -pt, except that manually instantiated
templates are placed in the repository.
-nopt
Disable automatic template instantiation. Manually instantiated
templates are placed in the output object with external linkage.
-define_templates
-tall
Automatically instantiate templates completely and place them in the
output object with external linkage. Manually instantiated templates
are also placed in the output object with external linkage.
-tall_repository (cxx -newcxx only)
Same as -tall except that all instantiations are
placed in the repository instead of the output object. This option is
useful for creating a pre-instantiation library.
-tlocal
Instantiate templates automatically, placing them in the output object
with internal linkage. Manually instantiated templates are also placed
in the output object with internal linkage. This option provides a
simple mechanism for getting started with templates, but it has a
number of limitations. Because the templates have local storage, they
must be instantiated in every module that uses them, and code bloat
could occur. In addition, a variable that would otherwise have a single
global copy can instead have many local copies that do not share the
same state.
-timplicit_local (cxx -newcxx only)
Same as -tlocal, except that manually instantiated
templates are placed in the repository with external linkage. This is
useful for build systems that need to have explicit control of the
template instantiation mechanism. This mode can suffer the same
limitations as -tlocal and is the default when
-std gnu is specified.
-tweak (cxx -newcxx only)
Same as -timplicit_local, but automatically
instantiated templates receive weak linkage. Weak linkage resembles
external linkage, except that duplicate symbols do not result in a link
error. The linker simply chooses one of the symbols. While this
behavior can still result in code bloat, it avoids the problem of
having multiple copies of the same variable not sharing the same state.
-pending_instantiations n
Limit the depth of recursive instantiations so that infinite
instantiation loops can be detected before some resource is exhausted.
-pending_instantiations requires a positive non-zero
value n as argument and issues an error when n
instantiations are pending for the same class template. The default
value for n is 64.
-ttimestamp (cxx -newcxx only)
Used with automatic instantiation. Causes automatic instantiation to
instantiate templates only if they are not already in the repository,
or if the existing instantiations in the repository are older than the
timestamp in the repository.
-Hx
Stops the cxx command after the prelinker runs and before the final
link. Provided for compatibility with previous versions of C++.
-[no]implicit_include (cxx -newcxx only)
Effective only with Version 6.0 and later. Enable or disable inclusion
of source files as a method of finding definitions of template
entities. Implicit inclusion is enabled by default, and it is disabled
when compiling with -E or -P. The
search rules for finding template definition files are the same as for
include files. This option also defines the macro
__IMPLICIT_INCLUDE_ENABLED. You might want to disable
implicit inclusion with the -ms and -std
ms options to match the behavior on Microsoft C++ more closely.
-nopragma_template
Directs the compiler to ignore any #pragma
define_template directives. This option is provided for users
who want to migrate quickly to automatic instantiation without having
to remove all the pragma directives from their code base.
-ptr dir
Specifies a repository, with ./cxx_repository as the
default. If you specify several repositories, only the first is
writable, and the rest are read only. Read-only repositories are used
only at link time. Specifying this option at link time enables C++ to
recognize and use the template instantiation information files within
the specified repository. If you use this option, make sure that the
repository specified at compile time is the same one specified at link
time.
-ptsuf
Specifies a list of file name suffixes that are valid for template
definition files. Items in the list must be separated by commas and
each suffix preceded by a period. A suffix may have no more than eight
characters excluding the beginning period. The default is
".cxx,.CXX,.C,.cc,.CC,.cpp,.c".
-ptv
Turns on verbose or verify mode to display each phase of instantiation
as it occurs. This option is useful as a debugging aid.
5.7 Compatibility with Earlier Versions of C++
The automatic template instantiation model is not directly compatible with previous C++ automatic template instantiation.
The compiler invoked when you use the -oldcxx option is a Version 5.n compiler. Where possible, it is safest to start fresh with an empty repository, and create the required instantiations by compiling all source files. If this is not possible, there are some strategies that can be used to link mixed generation instantiations.
If you used both Version 6.n and Version 5.n to build applications, Compaq strongly recommends that you use different repositories to contain automatic template instantiations for Version 6.n and Version 5.n compilations.
The default repository name is the same for Version 6.n as for
prior versions. Thus, if you use Version 6.n with older C++
compilers, you should do compilations in a different directory for each
compiler or explicitly specify a different repository for each using the
-ptr
option.
When linking applications using Version 6.n against
instantiations created with Version 5.n, it is necessary to
complete the Version 5.n instantiation process, to create
instantiation object files. This can be done with the
-oldcxx
and
-Hx
command-line options when linking. If
old_repository
is a Version 5.n repository then you would create the Version
5.n instantiation object files by using:
5.7.1 Linking with Version 5.n Instantiations
cxx -oldcxx -Hx -ptr old_repository <Version 5.n object files> |
The <Version 5.n object files> are the object files that were created using the Version 5.n compiler; old_repository now contains the instantiation object files. Create a library of these object files as follows:
ar r lib_old_repository.a old_repository/*.o |
When linking using Version 6.n, specify lib_old_repository.a after all of the Version 5.n object files that are being linked.
It is possible for repositories to reference objects in libraries that
had not been referenced previously. If this case, you must specify the
library on the command line again after the repository. The library
might also reference objects not previously referenced. Some cycles
might therefore require a single repository to be specified multiple
times on the command line.
In a similar way, you can create a library of Version 6.n
instantiation object files to link into a Version 5.n
application being linked using C++ Version 5.n. If
new_repository
is the Version 6.n repository, then a library of the
instantiations would be created by:
5.8 Linking Version 5.n Applications Against Version 6.n Repositories
ar r lib_new_repository.a new_repository/*.o |
When linking using Version 5.n, specify lib_new_repository.a after all of the Version 6.n object files that are being linked.
It is possible for repositories to reference objects in libraries that had not been referenced previously. If this case, you must specify the library on the command line again after the repository. The library might also reference objects not previously referenced. Some cycles might therefore require a single repository to be specified multiple times on the command line.
Previous | Next | Contents | Index |