You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

OS X下如何修改静态库转共享库后隐藏符号的可见性?

解决第三方libstdc静态库导致的C11特性受限问题

我之前维护老项目的时候碰到过几乎一模一样的坑,给你几个实际试过有效的思路:

1. 修复转共享库后的符号不可见问题

你说转成动态库后符号看不到,先别急,先精准定位问题:

  • nm -gU libyour_lib.dylib查看动态库的导出符号列表,确认是不是真的完全没有需要的符号
  • 如果是静态库没加-fPIC编译导致转动态库失败,试试用macOS下的链接参数强制加载所有符号:
gcc -shared -o libconverted.dylib -Wl,-all_load liboriginal.a

这个命令会把静态库里的所有符号都打包进动态库,大概率能解决符号不可见的问题。要是还不行,用objdump -x liboriginal.a查看静态库的符号表,检查有没有被隐藏的符号,再用objcopy手动导出。

2. 隔离编译:把代码拆成两个模块绕开stdlib冲突

如果没法搞定动态库,那退一步,把你的代码拆成两部分:

  • 依赖第三方库的代码:单独拿出来用-stdlib=libstdc++编译成静态库或者动态模块,这部分就别碰C++11特性了
  • 需要C++11的主代码:用默认的-stdlib=libc++编译,和上面的模块链接

关键是两个模块之间的接口要做兼容——别直接传递两个stdlib里实现不一样的对象(比如std::stringstd::vector这些),最好用纯C接口封装,或者用void*传递对象,在模块内部做类型转换。比如写个C风格的函数:

// wrapper.h(纯C接口)
#ifdef __cplusplus
extern "C" {
#endif
void do_third_party_task(void* param);
#ifdef __cplusplus
}
#endif

然后在libstdc编译的模块里实现这个函数,调用第三方库,主程序用libc编译调用这个接口就行。

3. 长远方案:尽量摆脱libstdc++依赖

苹果从macOS 10.9开始就把libc设为默认stdlib了,libstdc早就被弃用了,要是这个第三方库不是完全不可替代,建议找找支持libc的替代库,或者联系作者要libc版本的静态库——毕竟一直用老stdlib,后续系统升级还会出更多问题。

内容的提问来源于stack exchange,提问作者Arnaud

火山引擎 最新活动