2

Boost を使用する下位互換性のある ABI を使用したライブラリの作成に関するスレッドを読み、共有ライブラリをリンクして安定した ABI を維持し、干渉するシンボルの問題を回避する方法を理解しようとしています。

次の簡単なテスト プロジェクトを作成しました。

cat <<EOF > a.c
#define ABI __attribute__((visibility("default")))

int common();
int ABI a() { return common() + 1; }
EOF

cat <<EOF > b.c
#define ABI __attribute__((visibility("default")))

int common();
int ABI b() { return common() + 2; }
EOF

cat <<EOF > common_v1.c
int common() { return 1; }
EOF

cat <<EOF > common_v2.c
int common() { return 2; }
EOF

cat <<EOF > test.c
#include <assert.h>

int a();
int b();

int main(int argc, const char *argv[])
{
    assert( a() + b() == 6 );
    return 0;
}
EOF

cat <<EOF > CMakeLists.txt
cmake_minimum_required(VERSION 2.8)

project(TEST)

add_library(common_v1 STATIC common_v1.c)
add_library(common_v2 STATIC common_v2.c)

SET_SOURCE_FILES_PROPERTIES( a.c b.c COMPILE_FLAGS -fvisibility=hidden )
add_library(a SHARED a.c)
target_link_libraries(a common_v1)

add_library(b SHARED b.c)
target_link_libraries(b common_v2)

add_executable(test test.c)
target_link_libraries(test a b)
EOF

ライブラリ common_v1 および common_v2 は、ライブラリ a および b (Boost など) の外部依存関係をエミュレートする必要があります。common_v1 と common_v2 は外部ライブラリと見なされるため、ビルド システムを変更しないことをお勧めします (したがって、コンパイル時のフラグも変更しません)。

上記のプロジェクトは正常にコンパイルされますが、動作しません! テスト アプリケーションが実行されると、assert ステートメントにジャンプします。

これは、liba と libb の両方で共通の同じ定義が使用されていると思わせます。なぜそうなのか、何が間違っているのでしょうか?

4

1 に答える 1

0

andライブラリを作成するときにld--retain-symbols-fileオプションを使用してテスト プログラムを修正し、andシンボルのみを保持して、シンボルがこれらのライブラリによってエクスポートされないようにすることができます (したがって、あるライブラリは別のライブラリのシンボルを使用しようとしません)。aba()b()common()common()

  --retain-symbols-file ファイル名
        ファイル名にリストされているシンボルのみを保持し、すべてを破棄します
        その他。filename は、1 行に 1 つのシンボル名を持つ単純なフラット ファイルです。

オプションを使用することもでき--version-scriptます:

  --version-script=バージョンスクリプトファイル
        バージョン スクリプトの名前をリンカに指定します。

version-scriptfile次のとおりです。

  フー{
    グローバル: a; b; # エクスポートするシンボル
    ローカル: *; # 他の人を隠す
  };

関連スレッド:

于 2011-12-07T18:06:09.400 に答える