Objective-Cで書かれた静的ライブラリを作成しようとしています。このライブラリの利用者からすべての実装の詳細を隠したいと思います。この例では、「OneThing」オブジェクトは、「SecretThing」など、ライブラリ内の他の機能を使用します。これは、ライブラリ内の多くのもので使用される可能性があります(OneThing内で非表示にすることはできません)。ただし、ライブラリのユーザーに、OneThingがSecretThingを使用していることや、.aファイルを調べてもSecretThingが存在することを確認したくありません。
@interface OneThing
+ (void) do;
@end
@interface SecretThing
+ (void) undo;
@end
@implementation OneThing
+ (void) do
{
[SecretThing undo];
}
@end
@implementation SecretThing
+ (void) undo { }
@end
これをコンパイルして、シンボルテーブルを調べると:
% cc -c onething.m
% nm onething.o | grep Thing
0000000000000000 t +[OneThing do]
00000000000002f8 s +[OneThing do].eh
0000000000000040 t +[SecretThing undo]
0000000000000320 s +[SecretThing undo].eh
0000000000000078 S _OBJC_CLASS_$_OneThing
0000000000000050 S _OBJC_CLASS_$_SecretThing
00000000000000a0 S _OBJC_METACLASS_$_OneThing
00000000000000c8 S _OBJC_METACLASS_$_SecretThing
0000000000000128 s l_OBJC_$_CLASS_METHODS_OneThing
00000000000001d8 s l_OBJC_$_CLASS_METHODS_SecretThing
0000000000000190 s l_OBJC_CLASS_RO_$_OneThing
0000000000000240 s l_OBJC_CLASS_RO_$_SecretThing
0000000000000148 s l_OBJC_METACLASS_RO_$_OneThing
00000000000001f8 s l_OBJC_METACLASS_RO_$_SecretThing
%
予想どおり、OneThingとSecretThingは同じように公開されています。これで、SecretThingのライブラリ内での使用を何らかの方法で解決し、OneThingのみを外部に公開することができれば素晴らしいと思います。私が働きたかったのはこれでした(試して管理する方法を1つだけ選びました):
% ld -r onething.o -exported_symbol "+[OneThing do]" -o onlyonething.o
私はこれが「+[OneThingdo]」をタイプ「T」、(テキストグローバル)としてマークし、それが「ストリップ」を生き残ることを望んでいました。そうではありません。これはある時点で機能すると思っていたので、これは私を悩ませます。ツールチェーンを更新したときに、動作が異なる新しいバージョンのld( "ld -v" == ld64-133.3)を入手した可能性があります。
リンカにソースを取得し、自分のやりたいことを実行するために独自の新しいフラグを作成することを除いて、私はアイデアがありません。私はただ愚かであり、これを容易にする理解できないことがあることを願っています。
回答では、メソッドのディスパッチを実行するには実行時に利用可能なすべてのリンケージ情報が必要なため、これは基本的に不可能であることが示唆されました。この実験はそれが真実ではないことを証明していると思います。
# Move OneThing and SecertThing into their own files, with their own .h
% cat c_api.m
#include "OneThing.h"
void one_thing_do()
{
[OneThing do];
}
% cc -c c_api.c
% cat main.m
int main(int argc, char**argv)
{
extern void one_thing_do();
one_thing_do();
}
% cc main.m c_api.o onething.o secretthing.o -framework Foundation
% ./a.out
% ( runs to completion, no errors )
今、私たちは世界に見せたくない部分を隠そうとします:
% ld -r c_api.o onething.o secretthing.o -o strip_c_api.o -exported_symbol "_one_thing_do"
% strip -x c_strip_c_api.o
% nm strip_c_api.o
0000000000000118 s EH_Frame1
0000000000000098 s EH_Frame1
00000000000000d8 s EH_Frame1
U __objc_empty_cache
U __objc_empty_vtable
U _objc_msgSend
0000000000000000 T _one_thing_do
0000000000000130 s func.eh
00000000000000f0 s func.eh
00000000000000b0 s func.eh
0000000000000020 t l001
0000000000000060 t l002
0000000000000170 s l003
0000000000000190 s l004
00000000000001d8 s l005
0000000000000220 s l006
0000000000000240 s l007
0000000000000288 s l008
00000000000002f0 s l009
0000000000000318 s l010
0000000000000340 s l011
0000000000000368 s l012
% clang main.m strip_c_api.o -framework Foundation
% ./a.out
% nm a.out
0000000100001280 S _NXArgc
0000000100001288 S _NXArgv
0000000100001298 S ___progname
0000000100000000 T __mh_execute_header
U __objc_empty_cache
U __objc_empty_vtable
0000000100001290 S _environ
U _exit
0000000100000db0 T _main
U _objc_msgSend
0000000100000de0 T _one_thing_do
0000000100001000 s _pvars
U dyld_stub_binder
0000000100000d70 T start