记一次库连接的问题。
问题
场景是这样的
1. liba.so link the grpc++.a
2. binary b link the liba.so and the grpc++.a
因为 link 顺序的导致 binary b 优先使用 liba.so 中有的 grpc++.a symbol,liba.so 中没有的才去 link grpc++.a,这导致一些比较微妙的运行时问题,而且是偶现的
所以还是对于写动态库没有经验,这个问题说明要控制动态库 visibility 的 symbol
控制 symbol visibility 的方法
1. -fvisibility=hidden
在代码中加入
然后编译时使用 -fvisibility=hidden
选项就可以只暴露 foo 这种 API
但是这个方法不适合开始介绍的问题,因为 grpc++.a 中的 symbol visibility 不受我们的代码控制
2. -Wl,—exclude-libs,…
ld 中有 --exclude-libs
这个选项,可以 man 查看详情,会移除 archive 中 automatic export 的符号,经实验,使用前 grpc 相关的符号有 4000,使用后 grpc 相关的符号 300,还是很有用
3. ld version-script
最强控制 export,参考 script 写法,甚至支持 C++ mangle 前的写法
liba.so 只会暴露 script 指定的 symbol,grpc public 的只剩下两个
番外
会发生什么?调用到了 foo 函数!
reference
使用到的 research 工具
link
- https://blog.csdn.net/found/article/details/105263450
- https://holtstrom.com/michael/blog/post/437/Shared-Library-Symbol-Conflicts-%28on-Linux%29.html
- https://stackoverflow.com/questions/8432431/ld-script-for-symbol-hidding-in-c
- https://www.akkadia.org/drepper/dsohowto.pdf
- https://jdhao.github.io/2020/02/16/ripgrep_cheat_sheet/