Linking a Mixed C++ & Ada Program (GNAT User’s Guide for Native Platforms)

#### 3.11.3.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 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. We consider three cases:

- Using GNAT and G++ (GNU C++ compiler) from the same GCC installation: You can call the C++ linker by using the C++ specific driver called `g++`.

  If the C++ code uses inline functions that you plan to call from Ada, you need to compile your C++ code with the `-fkeep-inline-functions` so `g++` doesn’t delete these functions.

      $ g++ -c -fkeep-inline-functions file1.C
      $ g++ -c -fkeep-inline-functions file2.C
      $ gnatmake ada_unit -largs file1.o file2.o --LINK=g++

- Using GNAT and G++ from two different GCC installations: If both compilers are on the `PATH`, you may use the previous method. However, environment variables such as `C_INCLUDE_PATH`, `GCC_EXEC_PREFIX`, `BINUTILS_ROOT`, and `GCC_ROOT` 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. You can replace the implicit link command as suggested in the `gnatmake` command from the former example with 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’s a problem due to interfering environment variables, you can work around it 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

- Using a non-GNU C++ compiler: You can use the commands previously described 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 you are using the `setjmp` / `longjmp` exception mechanism, you need only include the paths to the `libgcc` libraries:

      $ 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 you are using the “zero cost” exception mechanism and the platform supports automatic registration of exception tables (e.g., Solaris), you need to include paths to more objects:

      $ 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 you are using the “zero cost exception” mechanism is used and the platform doesn’t support automatic registration of exception tables (e.g., HP-UX or AIX), the simple approach described above won’t work and a you will need to preform a pre-linking phase using GNAT.

Another alternative is to use the `gprbuild` multi-language builder which has a large knowledge base and knows how to link Ada and C++ code together automatically in most cases.