バイナリー互換性
一般に、 IBM® Open XL C/C++ for AIX® 17.1.0 で作成された C++ オブジェクトは、 xlclang++によって呼び出される IBM XL C/C++ for AIX 16.1.0 の Clang ベース・フロントエンドで作成された C++ オブジェクトとバイナリー互換性があります。
例外として、オプション -qpdf116.1.0XL C/C++ for AIXIBM 付きで作成されたオブジェクトファイルは、このコンパイラで使用されているものとは異なるPDFライブラリを呼び出すため、再コンパイルが必要です。詳しくは、Profile Guided Optimization (PGO) のトピックを参照してください。
std library libc++ への更新が必要です。また、C++ バイナリー互換性における破綻が生じます。 したがって、 IBM Open XL C/C++ for AIX 17.1.0 で作成された C++ オブジェクト・ファイルは、 xlCによって呼び出される IBM XL C/C++ for AIX 16.1.0 以前のリリースの XL ベース・フロントエンドで生成された C++ オブジェクト・ファイルと直接相互運用できません。 このようなバイナリー非互換性およびリンク・オブジェクト・ファイルを正常に解決するには、 IBM Open XL C/C++ for AIX 17.1.0 を使用してクラシック・プログラムを再コンパイルする必要があります。IBM Open XL C/C++ for AIX 17.1.0 で作成された C オブジェクトは、 IBM XL C/C++ for AIX 16.1.0 以前のリリースで作成された C オブジェクトとバイナリー互換性があります (外部リンケージを持つシンボル名にドル記号と基本文字セットの文字のみが含まれている場合)。
Classic XL C++ オブジェクト・ファイルとの互換性
- IBM Open XL C/C++ for AIXで作成された C++ オブジェクト・ファイル。 これらのオブジェクト・ファイルは、C++ ランタイム・ライブラリー
libc++.a、libc++abi.a、およびlibunwind.aによって提供されるインターフェースを使用します。これらはそれぞれ、libc++.rte、libc++abi.rte、およびlibunwind.rteファイルセットからのものです。 - IBM XL C/C++ for AIX 16.1.0の Clang ベース・フロントエンドで作成された C++ オブジェクト・ファイル。 これらのオブジェクト・ファイルは、
libc++.rteファイルセットからの C++ ランタイムlibc++.aによって提供されるインターフェースを使用します。
- IBM XL C/C++ for AIX 16.1.0 以前のリリースの XL ベース・フロントエンドで作成された C++ オブジェクト・ファイル。 オブジェクト・ファイルは、
xlC.rteファイルセットからの C++ ランタイムlibC.aによって提供されるインターフェースを使用します。
異なるマングル名
C++ 関数およびその他のエンティティーの名前は、互換性のないコードのリンクを防止するために、libc + + ABI および libC ABI で異なる名前マングリング・スキームを使用してマングルされます。 libc + + ABI は、Itanium C++ ABI 仕様で定義されている CXA マングリング・スキームを使用します。一方、 libC ABI は、 IBM 専有マングリング・スキームを使用します。 したがって、これらの ABI 内の C++ 関数に対応するシンボルは異なります。例えば、C++ 関数 func() のシンボルは、libc + + ABI では _Z4funcv ですが、 libC ABI では func__Fv です。 CXA マングリング・スキームでは、マングルされた名前に _Z 接頭部が付きます。
異なるオブジェクト・モデルとレイアウト
C++ オブジェクト・モデルとレイアウトは、libc + + ABI と libC ABI で異なります。 別の C++ ABI でコンパイルされたコード内の 1 つの C++ ABI から C++ オブジェクトにアクセスすると、未定義の動作になります。ただし、型が C との互換性のための規則に従っている場合を除きます。
異なる例外処理
例外処理の実装は、libc + + ABI と libC ABI で異なります。 例外が libc + + ABI 側からスローされ、 libC ABI 側を介してキャッチまたはアンワインドされた場合、またはその逆の場合には、例外処理の制限があります。 詳細については例外互換性を参照してください。
これらの違いにより、libc + + ABI と libC ABI は互換性がなく、異なる言語と見なすことができます。ただし、両方とも C++ と呼ばれます。ただし、これらは同じアプリケーション内で制限付きで共存できます。 このような場合、相互に対話することなく、同じプロセス・スペースに異なる C++ ランタイムのインスタンスを共存させることができます。 例えば、入力と出力は別個にバッファーに入れられ、他のランタイムには表示されません。
共存する共有オブジェクトで作成されたライブラリー
- ライブラリー内の libc + + ABI または libC ABI 共用オブジェクトは、相互に排他的です。
- C++ API 表面を表すライブラリー内の各共有オブジェクトは、libc + + ABI および libC ABI のいずれか 1 つのみをサポートします。
- これらの ABI からエクスポートされたシンボルは非結合です。
- libc + + ABI と libC ABI の間に相互参照はありません。
libc + + ABI および libC ABI 共有オブジェクトに相互参照がある場合、または 2 つのタイプの共有オブジェクトのシンボルを参照する実行可能ファイルがある場合、共有オブジェクトは結果の実行可能ファイルにリンクされます。 これにより、同じプロセス・スペースに 2 つの異なる C++ ランタイム実装が共存することになり、予期しない動作が発生する可能性があります。 実行可能ファイルのロード依存関係を確認するには、実行可能ファイルに対して ldd コマンドを使用します。
asm ラベルを使用することによって、関数名を別の名前にマップすることができます。 次の例では、名前 externCFunctionV2 が libc + + ABI の externCFunction 関数に使用され、その元の名前 externCFunction が libC ABI で使用されます。#if defined(_AIX) && defined(__clang__)
extern "C" void externCFunction(void) asm("externCFunctionV2");
#else
extern "C" void externCFunction(void);
#endifこれらの共有オブジェクトから目的のシンボルのみをエクスポートし、共有オブジェクト内の C++ ABI 間でエクスポートされたシンボルがオーバーラップしないようにします。 シンボルのエクスポート方法については、 Symbol exports and visibilitiesを参照してください。 新しいアプリケーションをリンクするために古い C++ ABI が不要になったが、ロード互換性を保持したい場合は、 strip -e コマンドを使用して共有オブジェクトをロード専用にすることができます。
エクスポートされたシンボルがエクスポート・リストまたは属性の可視性によって制御される共有オブジェクトとは異なり、同じアーカイブ・ライブラリー内に libc + + ABI と libC ABI の両方の静的アーカイブ・メンバーがあると、予期しない動作が発生する可能性があります。 例えば、結果の実行可能ファイルによって libc + + ABI と libC ABI の両方の静的コンストラクターが実行されますが、これは予期されていない可能性があります。 動作が十分に理解されていない限り、libc + + ABI と libC ABI の両方の静的アーカイブ・メンバーを同じアーカイブ・ライブラリーに組み込むことは推奨されません。
以下の例は、libc + + ABI と libC ABI の両方をサポートするために、単一ソースからデュアル 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
$
この例では、 xlC または ibm-clang++_r コマンドを使用して作成された main プログラムは、 func 関数と bar 関数の両方をデュアル ABI ライブラリーから呼び出すことができます。 libfunc.a の共有オブジェクト ibmclang.shr.o は、 IBM Open XL C/C++ コンパイラーを使用して作成されます。 共有オブジェクトは、 IBM Open XL C/C++ for AIX と、 IBM XL C/C++ for AIX 16.1.0の Clang ベース・フロントエンドの両方で使用できます。 ibmclang.shr.o は IBM Open XL C/C++ コンパイラーの C++ ランタイムに依存しているため、 IBM XL C/C++ for AIX 16.1.0 の Clang ベース・フロントエンドによって生成されたアプリケーションは、適切なバージョンの IBM Open XL C/C++ for AIX ランタイムをシステム上で使用可能にする必要があります。 同様に、 ibmclang.shr.o は、 IBM XL C/C++ for AIX 16.1.0 の Clang ベース・フロントエンドを使用して作成することもでき、 IBM Open XL C/C++ for AIX と IBM XL C/C++ for AIX 16.1.0の Clang ベース・フロントエンドの両方で使用できます。xlc.a.out および ibmclang.a.out で ldd を使用した場合の出力を以下に示します。$ 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)
...
$出力によると、 xlc.a.out は従来の XL C/C++ コンパイラー ( libC.a) の C++ ランタイムに依存していますが、 Open XL C/C++ コンパイラー ( libc++.a、 libc++abi.a、および libunwind.a) の C++ ランタイムには依存していません。 一方、 ibmclang.a.out には libc++.a、 libc++abi.a、および libunwind.a に対する依存関係がありますが、 libC.aに対する依存関係はありません。