Binary compatibility
In general, C++ objects built with IBM Open XL C/C++ for AIX 17.1.3 are binary compatible with C++ objects built with IBM® XL C/C++ for AIX® 16.1.0 invoked by xlclang++.
The exception is that object files created by IBM XL C/C++ for AIX 16.1.0 with the -qpdf1 option, when the compiler is invoked by xlclang or xlclang++, need to be recompiled. This is because the object files make calls to a different PDF library from the ones used in IBM Open XL C/C++. Refer to Profile Guided Optimization (PGO) for more information.
std
library libc++
, and causes a breakage in C++ binary
compatibility. Therefore, C++ object files built with IBM Open XL C/C++ for AIX 17.1.3 are not
directly interoperable with C++ object files generated by IBM XL C/C++ for AIX
16.1.0 that is
invoked by xlC or earlier releases. You must recompile your classic programs with
IBM Open XL C/C++ for AIX 17.1.3 to
solve such binary incompatibility and link object files successfully. - Symbol names with external linkage contain only the dollar sign and characters from the basic character set.
- Bitfields in C programs are declared only with the types allowed by the C standard regardless of any types allowed as implementation-defined.
Compatibility with Classic XL C++ object files
libc++
ABI, which denotes
the C++ standard library implementation on which the object files are based:- C++ object files built with IBM Open XL C/C++ for AIX. These object files utilize interfaces provided by C++ runtime libraries
libc++.a
,libc++abi.a
, andlibunwind.a
, which are from thelibc++.rte
,libc++abi.rte
, andlibunwind.rte
fileset, respectively. - C++ object files built with IBM XL C/C++ for AIX
16.1.0 that is
invoked by xlclang++. These object files utilize interfaces provided by C++
runtime
libc++.a
, which is from thelibc++.rte
fileset.
libC
ABI:- C++ object files built with IBM XL C/C++ for AIX
16.1.0 that is
invoked by xlC or earlier releases. The object files utilize interfaces provided
by C++ runtime
libC.a
, which is from thexlC.rte
fileset.
Different mangled names
The names of C++ functions and other entities are
mangled using different name mangling schemes in libc++ ABI and libC ABI to prevent linking of
incompatible code. libc++ ABI utilizes the CXA mangling scheme that is defined in the Itanium C++
ABI specification, while libC ABI uses the IBM proprietary mangling scheme. Consequently, the
corresponding symbols for a C++ function in these ABIs are different; for example, the symbol of C++
function func()
is _Z4funcv
in libc++ ABI, whereas it is
func__Fv
in libC ABI. In the CXA mangling scheme, mangled names have the
_Z
prefix.
Different object model and layout
The C++ object model and layout differ
between libc++ ABI and libC ABI. Accessing C++ objects from one C++ ABI in code that is compiled in
another C++ ABI results in undefined behavior, except where the type is subject to rules for
compatibility with C.
Different exception handling
The implementation of exception handling differs
between libc++ ABI and libC ABI. There are exception handling limitations when exceptions are thrown
from the libc++ ABI side and caught or unwound through the libC ABI side, and vice versa. Refer to
Exception compatibility for details.
Due to these differences, libc++ ABI and libC ABI are incompatible and can be considered as different languages, even though both are referred to as C++. However, they can still coexist in the same application with limitations. In such cases, there can be instances of different C++ runtimes coexisting in the same process space without interacting with each other. For example, input and output are buffered separately and are not visible to the other runtime.
Libraries built with coexisting shared objects
- The libc++ ABI or libC ABI shared objects in the library are mutually exclusive.
- Each shared object in the library that presents a C++ API supports only one of libc++ ABI and libC ABI.
- Exported symbols from these ABIs are disjoint.
- There are no cross references between libc++ ABI and libC ABI.
If the libc++ ABI and libC ABI shared objects have cross references, or if there is an executable file referencing symbols from two types of shared objects, the shared objects will be linked with the resulting executable file. This results in two different C++ runtime implementations coexisting in the same process space, which might cause unexpected behavior. To confirm the load dependencies of an executable, use the ldd command.
asm
label. In
the following example, name externCFunctionV2
is used for the
externCFunction
function in libc++
ABI and its original name
externCFunction
is used in libC
ABI.#if defined(_AIX) && defined(__clang__)
extern "C" void externCFunction(void) asm("externCFunctionV2");
#else
extern "C" void externCFunction(void);
#endif
Export only the desired symbols from these shared objects and ensure that exported symbols across
C++ ABIs in your shared objects do not overlap. To learn about how to export symbols, refer to
Symbol exports and visibilities
. When a C++ ABI is no
longer needed for linking new applications but you want to retain load compatibility, a shared
object can be made load-only with the strip -e command.
Unlike shared objects, where exported symbols are controlled by export lists or attribute visibility, having static archive members for both libc++ ABI and libC ABI in the same archive library might result in unexpected behavior. For example, static constructors for both libc++ ABI and libC ABI are executed by the resulting executable, which might not be expected. It is recommended not to include static archive members for both libc++ ABI and libC ABI in the same archive library unless the behavior is well understood.
The following example shows how to build a dual-ABI library from a single source to support both libc++ ABI and libC ABI:
$ cat build_example.sh
#!/usr/bin/ksh
rm -f xlc.shr.o ibmclang.shr.o libfunc.a xlc.a.out ibmclang.a.out
xlC -qmkshrobj func.cpp -o xlc.shr.o -bE:xlc.exp
ibm-clang++_r -shared func.cpp -o ibmclang.shr.o -bE:ibmclang.exp
ar -v -q libfunc.a xlc.shr.o ibmclang.shr.o
xlC main.cpp -o xlc.a.out libfunc.a -blibpath:.:/usr/lib
ibm-clang++_r main.cpp -o ibmclang.a.out libfunc.a -blibpath:.:/usr/lib
$ cat func.hpp
#include <iostream>
#if defined(_AIX) && defined(__clang__)
extern "C" void bar(void) asm("bar2");
#else
extern "C" void bar(void);
#endif
void func(void);
$ cat func.cpp
#include "func.hpp"
#if defined(_AIX) && defined(__clang__)
#define BUILD_COMPILER "build compiler is ibm-clang++_r"
#else
#define BUILD_COMPILER "build compiler is xlC"
#endif
void func(void)
{
std::cout << "func(): " << BUILD_COMPILER << std::endl;
}
extern "C" void bar(void)
{
std::cout << "bar(): " << BUILD_COMPILER << std::endl;
}
$ cat main.cpp
#include "func.hpp"
int main() {
func();
bar();
return 0;
}
$ cat xlc.exp
#!
func__Fv
bar
$ cat ibmclang.exp
#!
_Z4funcv
bar2
$ build_example.sh
$ xlc.a.out
func(): build compiler is xlC
bar(): build compiler is xlC
$ ibmclang.a.out
func(): build compiler is ibm-clang++_r
bar(): build compiler is ibm-clang++_r
$
In this example, the main
program built with either the
xlC or ibm-clang++_r command can call both the
func
and bar
functions from the dual-ABI library. Shared object
ibmclang.shr.o
in libfunc.a
is built using the IBM Open XL C/C++
compiler. The shared object can be used by both IBM Open XL C/C++ for AIX and IBM XL C/C++ for AIX
16.1.0 invoked by
xlclang++. Because ibmclang.shr.o
has dependencies on the C++
runtime of the IBM Open XL C/C++ compiler, applications generated by IBM XL C/C++ for AIX
16.1.0 invoked by
xlclang++ require the appropriate version of the IBM Open XL C/C++ for AIX
runtime to be available on the system. Similarly, ibmclang.shr.o
can also be built
using IBM XL C/C++ for AIX
16.1.0 invoked by
xlclang++ and used by both IBM Open XL C/C++ for AIX and IBM XL C/C++ for AIX
16.1.0 invoked by
xlclang++.xlc.a.out
and ibmclang.a.out
in the example
above:$ ldd xlc.a.out
xlc.a.out needs:
...
/usr/lib/libC.a(shr.o)
...
/usr/lib/libC.a(shrcore.o)
/usr/lib/libC.a(ansi_32.o)
/usr/lib/libC.a(ansicore_32.o)
$ ldd ibmclang.a.out
ibmclang.a.out needs:
...
/usr/lib/libc++.a(shr2.o)
/usr/lib/libc++abi.a(libc++abi.so.1)
/usr/lib/libunwind.a(libunwind.so.1)
/usr/lib/libc++.a(libc++.so.1)
...
$
According to the output, xlc.a.out
has dependencies on the C++ runtime of the
classic XL C/C++ compiler, which is libC.a
, but it does not have dependencies on
the C++ runtime of the Open XL C/C++ compiler, which are libc++.a
,
libc++abi.a
, and libunwind.a
. On the other hand,
ibmclang.a.out
has dependencies on libc++.a
,
libc++abi.a
, and libunwind.a
but does not have dependencies on
libC.a
.