合并两个静态库为动态库并解决多重定义冲突问题
解决静态库合并后转动态库的符号冲突问题
问题原因
ar工具仅负责将目标文件归档为静态库,不会处理符号冲突或去重。当你用--whole-archive选项强制链接合并后静态库中的所有目标文件时,两个目标文件里的version()全局符号会被同时引入,而动态库要求全局符号唯一,因此触发多重定义错误。
解决方案
方案1:修改源码(推荐)
如果有权限修改源码,直接让冲突符号避免全局可见:
- 将
version()定义改为static,使其仅在当前源文件可见:// return_zero.cpp static int version() { return 0; }// return_one.cpp static int version() { return 1; } - 或者给两个
version()分别加上命名空间,让符号名唯一:// return_zero.cpp namespace zero { int version() { return 0; } }// return_one.cpp namespace one { int version() { return 1; } }
修改后重新编译静态库,再合并转动态库即可。
方案2:修改目标文件符号(无需源码)
如果无法修改源码,可以通过objcopy重命名其中一个冲突符号:
- 从合并的静态库中提取冲突的目标文件:
ar x libreturn.a return_zero.cpp.o ar x libreturn.a return_one.cpp.o - 重命名其中一个目标文件里的
version符号(比如改成version_one):objcopy --redefine-sym version=version_one return_one.cpp.o - 重新打包成新的静态库:
ar rcs libreturn_fixed.a return_zero.cpp.o return_one.cpp.o - 用新静态库生成动态库:
g++ -fPIC -shared -Wl,-soname,libreturn.so -o libreturn.so dummy.cpp.o -Wl,--push-state,--whole-archive libreturn_fixed.a -Wl,--pop-state
方案3:强制允许多重定义(不推荐)
可以通过链接器选项-Wl,--allow-multiple-definition跳过错误,但链接器会随机选择其中一个符号生效,行为不可控,仅在明确知道要保留哪个符号且风险可接受时使用:
g++ -fPIC -shared -Wl,-soname,libreturn.so -o libreturn.so dummy.cpp.o -Wl,--push-state,--whole-archive libreturn.a -Wl,--pop-state -Wl,--allow-multiple-definition
内容的提问来源于stack exchange,提问作者CraigDavid
相关产品推荐
相关产品推荐

