构建XCFramework动态库时如何隐藏内部符号并保留指定导出符号?
隐藏内部符号的解决方案
你观察到的nm -gC输出中Secret::getString() const前面的标识是小写t,说明这个符号本身已经是本地私有符号,无法被外部链接引用,只是没有被剥离所以还保留了符号名,你可以通过以下方案彻底隐藏所有内部符号:
1. 补全编译阶段的符号隐藏配置
- 给所有C++、Objective-C++编译目标统一添加两个编译参数:
-fvisibility=hidden:控制C/C++符号的默认可见性为隐藏-fvisibility-inlines-hidden:隐藏所有内联函数的符号,避免C++内联成员函数意外泄露
- 对于仅在单个cpp文件内使用的类、函数,直接添加
static修饰,或者放到匿名命名空间中,从编译层面就将符号限定为文件本地 - 所有需要对外暴露的C++接口,显式添加
__attribute__((visibility("default")))标记
2. 链接阶段执行符号剥离
- 在Xcode动态库target的构建设置中,把「Strip Style」设置为
Non-Global Symbols,链接后会自动剥离所有非全局的本地符号 - 也可以手动给链接器添加参数
-Wl,-x,实现同样的剥离效果 - 如果需要更精细的符号控制,推荐使用导出符号表方案:
- 新建纯文本文件
exported_symbols.list,每行写一个要保留的导出符号名 - 给链接器添加参数:
-Wl,-exported_symbols_list,${文件实际路径}/exported_symbols.list,链接器只会保留列表内的符号,其余所有符号都会被隐藏
- 新建纯文本文件
3. Swift代码符号适配
- Release模式下打开Swift编译优化选项,默认会隐藏内部Swift符号
- 将「Reflection Metadata Level」设置为
None,避免内部类型的元数据符号泄露 - 不需要对外暴露的Swift类型、函数统一用
internal、fileprivate、private修饰,不要使用public/open
保留_AlexSDKVersionNumber符号的方法
- 如果使用导出符号表方案,直接在
exported_symbols.list中添加一行_AlexSDKVersionNumber即可 - 如果不使用导出符号表,只需要在Xcode构建设置中把「Expose Version Number Symbols」设置为YES,这个自动生成的符号默认就会保留导出状态
内容的提问来源于stack exchange,提问作者Alex Cohn
相关产品推荐
相关产品推荐

