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:
Note that if the C++ code uses inline functions, you will need to compile your C++ code with the -fkeep-inline-functions switch in order to provide an existing function implementation that the Ada code can link with.
$ g++ -c -fkeep-inline-functions file1.C $ g++ -c -fkeep-inline-functions file2.C $ gnatmake ada_unit -largs file1.o file2.o --LINK=g++
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
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), 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 or AIX), the simple approach described above will not work and a pre-linking phase using GNAT will be necessary.
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.