Next: , Previous: Interfacing to C++, Up: Building Mixed Ada & C++ Programs


2.11.2 Linking a Mixed C++ & Ada Program

Usually the linker of the C++ development system must be used to link mixed applications because most C++ systems will resolve elaboration issues (such as calling constructors on global class instances) transparently during the link phase. GNAT has been adapted to ease the use of a foreign linker for the last phase. Three cases can be considered:

  1. Using GNAT and G++ (GNU C++ compiler) from the same GCC installation: The C++ linker can simply be called by using the C++ specific driver called c++. Note that this setup is not very common because it may involve recompiling the whole GCC tree from sources, which makes it harder to upgrade the compilation system for one language without destabilizing the other.
              $ c++ -c file1.C
              $ c++ -c file2.C
              $ gnatmake ada_unit -largs file1.o file2.o --LINK=c++
         
  2. Using GNAT and G++ from two different GCC installations: If both compilers are on the PATH, the previous method may be used. It is important to note that environment variables such as C_INCLUDE_PATH, GCC_EXEC_PREFIX, BINUTILS_ROOT, and GCC_ROOT will affect both compilers at the same time and may make one of the two compilers operate improperly if set during invocation of the wrong compiler. It is also very important that the linker uses the proper libgcc.a GCC library – that is, the one from the C++ compiler installation. The implicit link command as suggested in the gnatmake command from the former example can be replaced by an explicit link command with the full-verbosity option in order to verify which library is used:
              $ gnatbind ada_unit
              $ gnatlink -v -v ada_unit file1.o file2.o --LINK=c++
         

    If there is a problem due to interfering environment variables, it can be worked around by using an intermediate script. The following example shows the proper script to use when GNAT has not been installed at its default location and g++ has been installed at its default location:

              $ cat ./my_script
              #!/bin/sh
              unset BINUTILS_ROOT
              unset GCC_ROOT
              c++ $*
              $ gnatlink -v -v ada_unit file1.o file2.o --LINK=./my_script
         
  3. Using a non-GNU C++ compiler: The commands previously described can be used to insure that the C++ linker is used. Nonetheless, you need to add a few more parameters to the link command line, depending on the exception mechanism used.

    If the setjmp/longjmp exception mechanism is used, only the paths to the libgcc libraries are required:

              $ cat ./my_script
              #!/bin/sh
              CC $* `gcc -print-file-name=libgcc.a` `gcc -print-file-name=libgcc_eh.a`
              $ gnatlink ada_unit file1.o file2.o --LINK=./my_script
         

    Where CC is the name of the non-GNU C++ compiler.

    If the zero cost exception mechanism is used, and the platform supports automatic registration of exception tables (e.g. Solaris or IRIX), paths to more objects are required:

              $ cat ./my_script
              #!/bin/sh
              CC `gcc -print-file-name=crtbegin.o` $* \
              `gcc -print-file-name=libgcc.a` `gcc -print-file-name=libgcc_eh.a` \
              `gcc -print-file-name=crtend.o`
              $ gnatlink ada_unit file1.o file2.o --LINK=./my_script
         

    If the zero cost exception mechanism is used, and the platform doesn't support automatic registration of exception tables (e.g. HP-UX, Tru64 or AIX), the simple approach described above will not work and a pre-linking phase using GNAT will be necessary.