Clang を使用して Mac OS X で実行しようとしている C++ ライブラリがあります。このライブラリは、DLL と Unit-Test 実行可能ファイルで構成されています。GCC と MSVC で問題なくコンパイルできます。GCC では、次の設定を使用します。
- ライブラリはでコンパイルされます
-fvisibility=hidden
- 公開されたすべてのクラスは、明示的に次のようにマークされます。
__attribute__(visibility("default"))
- ライブラリには、 から派生したいくつかの例外クラスがあります
std::runtime_error
。そのようなすべてのクラスは、デフォルトの可視性のためにマークされています。LibraryException
より具体的な例外が派生するルート クラスがあります。 - GCCでは
-std=c++0x
、clangを使用して、ライブラリと単体テスト実行可能ファイルの両方をビルドします-stdlib=libc++ -std=c++11
Mac OS X では、例外のタイプが間違っているため、ユニット テスト フレームワークが失敗するようになりました。つまり、次のようなテストは失敗します。
// bla.foo () throws CustomException, which is derived from LibraryException
TEST_THROWS (bla.foo (), CustomException)
// This works however
TEST_THROWS (bla.foo (), LibraryException)
カスタム例外クラスの typeinfo と vtable が を使用してエクスポートされることを確認しましたnm -g library.dylib | c++filt -p -i
。これはすべての例外に当てはまるようです...一体何がここで起こっているのでしょうか? エラーのデバッグを試みましたが、ライブラリで正しい型がスローされているのに、単体テスト実行可能ファイルで同じ型をキャッチできないことがわかりました。これを機能させるために Clang で何か特別なことが必要ですか? テストには、SVN の最新の googletest フレームワークを使用しています。
小さなテスト プログラムでも同じ問題が発生します。
try {
funcThatThrowsCustomExceptionFromLibraryDylib ();
} catch (CustomException& e) {
// doesn't get here
} catch (LibraryException& e) {
// does get here
// after demangle, this prints CustomException
// Can cast down to CustomException and access the fields as well
std::cout << typeid (e).name () << "\n";
}
boost::lexical_cast
たとえば、ライブラリから例外がスローされた場合にも失敗します。