Xcodeでフレームワークや共有ライブラリの出力シンボルを制御する

Xcodeのデフォルト設定では、フレームワークや共有ライブラリで実装した関数や定数のシンボルがすべて出力されます。この記事ではすべてのシンボルが出力されてしまうことで起きる問題や制御方法について解説します。

シンボルがすべて出力されることで起きる問題

フレームワークや共有ライブラリのシンボルがすべて出力されてしまうと、次のような問題が起きます。

  • 内部専用関数、特に一般的な名称の関数が出力されてしまうと、ライブラリ利用側のプログラム内で定義する関数と衝突する可能性が高くなる。
  • 動的にロードされる複数のライブラリで同じ名前のグローバルシンボルがいると実行時に衝突し、どの関数が使われるか不定状態になる。
  • 外部から使われることを想定していない関数が直接使われることで、設計や実装の変更に弱くなる。意図しない使われ方をする可能性がある。

大規模なプログラム内で使われるときには特にシンボル名の衝突は起きやすくなります。

出力されているシンボルの調べ方

ライブラリが出力しているシンボルを調べるには、nmを次のようにします。

nm -gm path-to-binary

例えば、次のようなCの関数を持ったフレームワークがあるとします。

/* ExpSymbol.c */
#include "ExpSymbol.h"

int private_add(int i, int j)
{
    return i + j;
}

int add(int i, int j)
{
    return private_add(i, j);
}
/* ExpSymbol.h */
#ifndef EXP_SYMBOL_H
#define EXP_SYMBOL_H

#ifdef __cplusplus
extern "C" {
#endif

extern int add(int i, int j);

#ifdef __cplusplus
}
#endif

#endif /* EXP_SYMBOL_H */

このフレームワークの出力シンボルを調べてみると、次のようになります。

% nm -gm nm -gm ExpSymbol.framework/Versions/A/ExpSymbol
0000000000003fa8 (__TEXT,__const) external _ExpSymbolVersionNumber
0000000000003f78 (__TEXT,__const) external _ExpSymbolVersionString
0000000000003f4c (__TEXT,__text) external _add
0000000000003f2c (__TEXT,__text) external _private_add
                 (undefined) external dyld_stub_binder (from libSystem)

この例では4つのシンボルが出力されています。ExpSymbol.cで実装した2つの関数も出力されています。しかし、公開したいAPIはExpSymbo.hで宣言しているaddだけの想定でした。addが使っているprivate_addはプライベート関数の位置づけで出力しない想定です。

このように、デフォルト設定では実装した関数のシンボルがすべて出力されてしまいます。

出力シンボルファイルを使う

Xcodeで出力されるシンボルを制御するには、出力シンボルファイルを使います。

出力シンボルファイルの作成方法

出力シンボルファイルを作成するには次のように操作します。

(1) 「File」メニューの「New」から「File…」を選択します。

(2) 「Exports File」を選択して、「Next」ボタンをクリックします。

(3) ファイル名はライブラリ名など分かりやすいものを設定します。ここでは「ExpSymbol」としました。「Targets」はすべてチェックオフです。

出力シンボルファイルの設定

出力シンボルファイルは、次のようにフレームワークやライブラリのターゲットのビルド設定の「Linking」の「Exported Symbols File」に設定します。

出力するシンボルを定義する

出力シンボルファイルは、1行に1シンボルで出力するシンボルを列挙します。#以降は行末までコメントとして扱われます。

例えば、この例ではaddだけ出力したいので次のようになります。

#  ExpSymbol.exp
#  ExpSymbolTest
#
#  Created by Akira Hayashi on 2021/04/19.
#  

_add

シンボルをどのように書いたら良いか分からないときは、「Exported Symbols File」の設定をクリアして、すべてのシンボルを出力し、nmでどのように出力されているか調べると分かります。

検証

ExpSymbol.expaddだけ出力されるように設定しビルドします。ビルドしたライブラリの出力シンボルを調べてみると、次のようになり、意図したようにaddだけが出力されていることが分かります。

% nm -gm nm -gm ExpSymbol.framework/Versions/A/ExpSymbol
0000000000003f4c (__TEXT,__text) external _add
                 (undefined) external dyld_stub_binder (from libSystem)

著書紹介

Authored Books

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

Akira Hayashi (林 晃)のアバター Akira Hayashi (林 晃) Representative(代表), Software Engineer(ソフトウェアエンジニア)

アールケー開発代表。Appleプラットフォーム向けの開発を専門としているソフトウェアエンジニア。ソフトウェアの受託開発、技術書執筆、技術指導・セミナー講師。note, Medium, LinkedIn
-
Representative of RK Kaihatsu. Software Engineer Specializing in Development for the Apple Platform. Specializing in contract software development, technical writing, and serving as a tech workshop lecturer. note, Medium, LinkedIn

目次