前面笔者的博文MSYS2 MinGW64使用Protobuf新版本踩坑,有提到使用最新的Clang 19.1.4版本在MinGW下无法正常链接使用了Protobuf 28.3的项目,因为MinGW下的项目默认都是使用GCC来编译的,所以如果开发者使用Clang编译器,必然会出现链接MinGW下的这些GCC编译的库。其实该问题同样存在于Linux下,Linux下的库默认也是使用GCC来编译的。
笔者在遇到问题时,喜欢知其然,也要尽量知其所以然!笔者查了一下资料,Clang编译器从18开始为了更好地支持C++20,对ABI进行了一些修改,特别是概念相关的命名冲突,就导致了一些函数的ABI发生了变化,原文如下:
Between Clang 17 and Clang 18, we implemented an ABI fix to resolve mangled name collisions, but unfortunately that changes the manglings of a small number of functions such as this one (which previously was a case where mangling collisions between different functions could happen). The ABI change fixed a longstanding bug, but we finally reached sufficient motivation to fix it due to some C++20 changes, primarily the addition of concepts, which made these kinds of symbol collisions more likely to occur in practice in the future. This was just an all-round bad situation, and sadly we didn’t have a path forward that supported C++20 well and had no risk of breaking anything.
为了使用Clang也能正确链接到GCC编译的库,针对Clang 18+,可以使用命令行参数-fclang-abi-compat=17
来解决这个问题。对于CMake而言,在顶层CMakeLists.txt中添加:
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-fclang-abi-compat=17)
endif()
即可。
据说Clang编译器开发人员在考虑添加[[clang::abi_compat(17)]]
属性来从代码层面解决此类问题。因为前面也说了,修改ABI的主要原因是为了更好的支持C++20,如果项目中有使用C++20的概念相关代码,又有absl此类问题的代码,那项目全部使用-fclang-abi-compat=17
也会出现问题,所以局部解决是最好的,期待Clang的更新~~~,也期待GCC与Clang的ABI能尽快再次统一!!
如果本文对你有帮助,欢迎点赞收藏!!