C++链接最新V8库时名称修饰不一致引发未定义引用报错
问题根因
两个目标文件中NewDefaultPlatform函数的修饰名差异,本质是C++标准库实现的ABI不匹配:
- 你自己编译生成的
app.cc.o引用的是全局命名空间下的标准std::unique_ptr,对应修饰名片段是St10unique_ptr - V8提供的
libv8_libplatform.so编译时使用了Chromium定制的带内联命名空间隔离的libc++实现,其中std::unique_ptr实际位于std::__Cr内联命名空间下,对应修饰名片段是NSt4__Cr10unique_ptr
Chromium/V8默认开启定制libc编译选项,目的是避免和系统自带C标准库产生符号冲突,但如果你的项目编译时没有对齐V8的标准库编译参数,哪怕用V8自带的clang编译器,默认还是会调用系统的C++标准库头文件、链接系统标准库,最终导致两边的std类型符号修饰不一致,触发未定义引用错误。
日志里的DWARF error: invalid or unhandled FORM value: 0x25是独立警告,原因是系统自带的ld(binutils包提供)版本过旧,无法识别新版clang生成的高版本DWARF调试格式,不是导致链接失败的原因。
修复方案
二选一即可,优先推荐第一种对齐V8编译参数的方案,避免重新编译V8的耗时:
- 方案1:编译自有项目时对齐V8的C标准库配置
编译阶段添加以下参数,指定使用V8自带的定制libc头文件,替换系统标准库头文件:
链接阶段添加以下参数,指定链接V8附带的定制libc++、libcabi库,不链接系统默认C标准库:-nostdinc++ -isystem /home/vahvarh/try_teajs/v8_things/v8/third_party/libc++/src/include -isystem /home/vahvarh/try_teajs/v8_things/v8/third_party/libc++abi/src/include
如果使用CMake构建,可以通过-nostdlib++ -L/home/vahvarh/try_teajs/v8_things/v8/out/x64.debug -lc++ -lc++abitarget_compile_options和target_link_options把上述参数加到你的tea目标上即可。 - 方案2:重新编译V8,关闭定制libc++选项
如果你不想修改自有项目的编译参数,可以在配置V8的gn构建参数时加入以下两个配置:
配置完成后重新编译V8,此时生成的V8库会使用系统C++标准库,和你项目默认编译配置的ABI对齐,替换原有V8库文件后即可正常链接。use_custom_libcxx=false use_custom_libcxx_for_host=false
如果需要消除日志里的DWARF警告,要么升级系统的binutils包到新版本,要么在自有项目的编译参数里加-gdwarf-4,指定生成兼容旧版ld的DWARF v4格式调试信息即可。
内容的提问来源于stack exchange,提问作者Vladimir Olenin
相关产品推荐
相关产品推荐

