一、背景
最近因为项目需求,需要在虚幻引擎中使用RabbitMQ,并且在Linux平台上进行部署。
因为SimpleAmqpClient需要的库文件和头文件较多,为了方便起见,我选择将AMQP-CPP以插件的形式整合进虚幻引擎。
但当一切功能在引擎里调试完毕后(Windows 平台),在进行Linux交叉编译时,linking的时候会遇到以下报错:
UATHelper: Packaging (Linux): ld.lld: error: undefined symbol: AMQP::ConnectionImpl::ConnectionImpl(AMQP::Connection*, AMQP::ConnectionHandler*, AMQP::Login const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
UATHelper: Packaging (Linux): >>> referenced by connection.h:47
在查阅资料后,发现这个问题主要源于std::__1::basic_string,这个类的定义出自于libstdc++。而UE在交叉编译时,链接的库为libc++,若第三方库编译时链接的为libstdc++,会引起此报错。因此,我们只需要保证第三方库在编译时链接的标准库为libc++即可。
二、解决方法
为了解决上述问题,在Linux中,一般是使用CMake来进行编译,所以我们需要修改CMakeLists.txt文件,来指认编译器和链接库,使之与虚幻引擎一致。
1、修改编译器为 Clang / Clang++
在CMakeLists.txt中添加如下字段,此段内容一定要放在 project() 声明前!
SET (CMAKE_C_COMPILER "/usr/bin/clang")
SET (CMAKE_C_FLAGS "-Wall -std=c99")
SET (CMAKE_C_FLAGS_DEBUG "-g")
SET (CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG")
SET (CMAKE_C_FLAGS_RELEASE "-O4 -DNDEBUG")
SET (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")
SET (CMAKE_CXX_COMPILER "/usr/bin/clang++")
SET (CMAKE_CXX_FLAGS "-Wall")
SET (CMAKE_CXX_FLAGS_DEBUG "-g")
SET (CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
SET (CMAKE_AR "/usr/bin/llvm-ar")
SET (CMAKE_LINKER "/usr/bin/llvm-ld")
SET (CMAKE_NM "/usr/bin/llvm-nm")
SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump")
SET (CMAKE_RANLIB "/usr/bin/llvm-ranlib")
除了上述方法,也可以永久指定Linux默认编译器为Clang,通过下述指令即可(以 Ubuntu 为例),
sudo update-alternatives --config c++
执行后,便可以输入编号选择clang作为默认编译器。
2、指定链接的标准库为libc++
在CMakeLists.txt中添加如下字段,
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -v")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi")
此字段将编译和链接时的标准库都设置为libc++,因此最后的编译结果均与虚幻引擎兼容。
以上步骤设置后,在对应的build文件夹执行
cmake ..
make
便可编译出我们需要的第三方库了。