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:
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++
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
If you are using the setjmp
/ longjmp
exception mechanism, you need only
inclue 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.