4つの静的ライブラリ(.a
)と1つのオブジェクト(.o
)ファイルから構築された共有ライブラリプロジェクトがあります。 -fvisibility=hidden
オプションを追加して、出力のシンボルを、ソースで__attribute__を使用してマークしたシンボルのみに制限しようとしています。
-fvisibility=hidden
プロジェクト(.so
ファイルをカバーする)と.o
プロジェクトのコンパイルオプションに.a
オプションを追加しました。
オブジェクトファイル内のシンボルは、最終的な.so
から期待どおりに削除されます。ただし、.a
プロジェクトのシンボルはすべて、最終的な.so
ファイルに残っています。 -fvisibility=hidden
オプションを.so
リンクコマンドに追加しても効果はありません。
何が悪いのですか?
ここでの目的は、.so
から、ライブラリへのインターフェイス関数を除くすべてのシンボルを削除することです。
編集:私は実際にこれを解決するために バージョンマップ を実際に使用しました。ただし、外部シンボルが変更されると、バージョンスクリプトの継続的なメンテナンスが必要になります。受け入れられた答えはより良いアイデアを持っています。
基本的に、可視性はリンク中に処理され、リンカーは静的アーカイブにそれを課すようには見えません。 SO here )に関連する質問(重複ではありません)が尋ねられました。
リンクステージを置き換えることをお勧めします:gcc -shared -o mylib.so foo.o libbar.a
を2段階のプロセスに入れ、オブジェクトファイルを取得します。
ar x libbar.a
(おそらく適切な空のディレクトリに)gcc -fvisibility=hidden -shared -o mylib.so foo.o tempdir/*.o
単に-Wl,--exclude-libs,ALL
をgccに渡します
これにより、静的ライブラリ内のすべてのシンボルを非表示に変換するようリンカーに指示します。
--exclude-libs
は、シンボルを非表示にするライブラリをより細かくするために、アーカイブのリスト(つまり、静的ライブラリ名)も受け入れます。
注:これは、GNU binutils(例:Linux)を使用するシステム、または--exclude-libs
をサポートするリンカーを使用するシステムでのみ機能します(例:OSXで機能しません。 ld64)
これはOS Xの問題に対する答えです。
Mac ld
は--exclude-libs
をサポートしていませんが、-exported_symbol sym
をサポートしていますdoesこれを静的ライブラリのオブジェクトファイルに適用します。そして、パブリックAPIにフィルターをかける場合、ホワイトリストはそれを説明するのに十分なほど小さいです。
最終的に、Makefileに次のコードが含まれ、エクスポートされた各シンボルの-Wl,-exported_symbol,_api_func_1
フラグが生成されました。
SYMBOLS = api_func_1 api_func_2 api_func_3 api_func_4
SYMBOLS += api_func_5 # add more as necessary
COMMA = ,
LDFLAGS += $(addprefix -Wl$(COMMA)-exported_symbol$(COMMA)_,$(SYMBOLS))
# ...
libmyapi.so: # ...
$(CC) -shared -o $@ ... $(LDFLAGS)
次に、このバージョンのフラグとGNU ldバージョンのシステム間で検出されたリンカーを検出した後、ldバージョンの間でif-gateを実行できます。