DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
Instantiating C++ templates

The one instantiation per object scheme

Given the results of the previous section, what is needed in occasional cases is a way to include all the necessary instantiations with the archive libraries, but in such a way that the libraries can be linked against without getting multiple definition errors (if the symbols were not weak).

The scheme is do this is called "one instantiation per object". The idea is that, when the appropriate option is given, a source file with instantiations in it will generate more than one object file. In the example of the previous section, the al1.C source file will generate three object files: al1.o, containing the al1() function, and "A<int>:fff().o" and "A<int>:ggg().o" (the actual filenames are in a mangled form). These three object files will all be placed into libal1.a. Similarly, al2.C will generate al2.o, "A<int>:fff().o", and "A<int>:hhh().o", all of which go into libal2.a. In general, there will be a separate .o for each template function, member function of a template class, or static data member of a template class, that is instantiated.

Now, when the main program is linked against the archives, the linker will pull in libal1.a:al1.o, libal1.a:"A<int>:fff().o", libal1.a:"A<int>:ggg().o", libal2.a:al2.o, and libal2.a:"A<int>:hhh().o". It will not pull in libal2.a:"A<int>:fff().o" because it will have already resolved that symbol with the libal1.a:"A<int>:fff().o", and it will not pull in a second "A<int>:fff()" from any other .o because each instantiation is isolated within its own .o.

In this way it is possible to close each archive library and still be able to link against them without fear of multiple copies of instantiation code being pull in.

The CC -Toipo and CC -Toipo_list (oipo is the acronym for "one instantiation per object") options are used to implement this scheme. They are not on by the default because this scheme is complicated and is only rarely needed. When building most archives or dynamic libraries (.so files) or straight executables, the one instantiation per object is not necessary. It can be used in those circumstances and it will work, but it may cause longer build times (especially when the CC -g or -O options are being used), because some of the compilation processes are cycled through for each instantiation.

In plainer words, do not use this scheme unless you are really sure you need to!

Here is how these options are used to build the example from the previous section. First we compile and prelink the a1.C source:

   $ CC -c -Toipo=Template.al1 al1.C
   al1.C:
   $ CC -Tprelink_objects -Toipo=Template.al1 al1.o
   prelink: INFO: C++ prelinker: executing: CC -c -Toipo=Template.al1 al1.C
   al1.C:
   fff__10A__tm__2__b29006af.oipo:
   ggg__10A__tm__2__9fcf3e2f.oipo:
The commands are the same as before except we have added a -Toipo option, which is supplied to both compilation and prelinking commands. When the additional instantiation objects are created in this scheme, they are placed in a separate directory, to keep them out of the way of the "normal" objects of the application. By default this separate directory is the subdirectory ./Template.dir; the compiler will create it if it does not already exist. This directory should be kept around between builds, but can be removed by a make clean or make clobber type of action.

In this simple example we are building two archive libraries from the same source directory, and so we want to keep the instantiation objects in two separate subdirectories. To do this we supply the optional =dirname argument to the -Toipo option. In a real-life application, each archive would probably be built from a separate part of the overall source tree, and the default Template.dir in each directory would work fine.


NOTE: The compiler prints out the names of the instantiation objects as it compiles them, much as it does when you specify multiple source files to a compilation.

Now it is time to make the archive. We want to put not just al1.o into the archive but also these additional instantiation objects. We do could a

   $ ls Template.al1
   fff__10A__tm__2__b29006af.o   ggg__10A__tm__2__9fcf3e2f.o
to see the objects that are there, but these are mangled filename forms that do not have much meaning to us. Furthermore the number of names of them will frequently change as our application is developed.

Instead, we use the CC -Toipo_list command. Given a set of primary object files from our application, it will print to standard output the complete set of object files including instantiation objects:

   $ CC -Toipo_list al1.o
   al1.o Template.al1/ggg__10A__tm__2__9fcf3e2f.o Template.al1/fff__10A__tm__2__b29006af.o
Now, we use this command within backquotes to supply the arguments to ar:
   $ ar rv libal1.a `CC -Toipo_list al1.o`
   r - al1.o
   r - Template.al1/ggg__10A__tm__2__9fcf3e2f.o
   r - Template.al1/fff__10A__tm__2__b29006af.o
   UX:ar: INFO: Creating libal1.a
Next we do the same process to build libal2.a.
   $ CC -c -Toipo=Template.al2 al2.C
   al2.C:
   $ CC -Tprelink_objects -Toipo=Template.al2 al2.o
   prelink: INFO: C++ prelinker: executing: CC -c -Toipo=Template.al2 al2.C
   al2.C:
   fff__10A__tm__2__b29006af.oipo:
   hhh__10A__tm__2__ecda57ee.oipo:
   $ ar rv libal2.a `CC -Toipo_list al2.o`
   a - al2.o
   a - Template.al2/hhh__10A__tm__2__ecda57ee.o
   a - Template.al2/fff__10A__tm__2__b29006af.o
   UX:ar: INFO: Creating libal2.a
Now it is time to link the executable. We are not using the one instantiation per object scheme in this step, since the main function is not going into an archive. So we use the same commands as before:
   $ CC -c main.C
   $ CC -L. main.o -lal1 -lal2
   $ ./a.out
   $ echo $?
   7
This time, the link is successful and the program produces the expected output.

Previously, we stated that it is not necessary to use -Toipo unless templates are being built for archives, but that it can be done. If you are doing this, you should first prelink the objects, and then use -Toipo_list to supply input to the link step. Using the same example as above, a straight build without archives but using -Toipo would look like:

   $ CC -c -Toipo al1.C al2.C main.C
   al1.C:
   al2.C:
   main.C:
   $ CC -Tprelink_objects -Toipo al1.o al2.o main.o   
   prelink: INFO: C++ prelinker: executing: CC -c -Toipo al1.C
   al1.C:
   fff__10A__tm__2__b29006af.oipo:
   ggg__10A__tm__2__9fcf3e2f.oipo:
   hhh__10A__tm__2__ecda57ee.oipo:
   $ CC `CC -Toipo_list al1.o al2.o main.o`
   $ ./a.out
   $ echo $?
   7
As can be seen from these examples, it should never be necessary for you to manually deal with the contents of the instantiations objects subdirectory. By naming the directory (if not the default) on the -Toipo option, and then by using the -Toipo_list option, the compilation system will kept track of the instantiation objects for you. One very minor exception to this is if you use a CC -Toipo -S command to generate assembly (.s) generated code files. This will produce .s files for the primary and all instantiation generated code files. However, if you subsequently do CC -Toipo whatever .s to assemble these files, only the primary file will be assembled. You will need to assemble the instantiation generated code files by hand yourself.
Next topic: Special symbols
Previous topic: More on linking template code into archives

© 2005 The SCO Group, Inc. All rights reserved.
SCO OpenServer Release 6.0.0 -- 02 June 2005