UE4.27里添加一个google protobuf的库, 这个库需要混合编译生成后用来链接
目标平台, win,linux,android,ios,mac,ps4,ps5

原因:
最近给UE4.27.2版本的Dedicated Server添加了一个TcpSocket的网络代码与服务器通信. 正好用到了linux的库和google protobuf3.19的库. linux下的protobuf库不能拿过去windows上用clang++直接链接, 因为clang++和gcc使用的c++不是一个标准,使用的是libc++, linux下GNU使用的是GCC和libstdc++. 所以必须用clang++使用libc++重新编译(否则链接的时候会报错,也许是ABI的问题)

需要工具:

cmake 3.5+? 我用的3.15, 提示我版本低, 但是也成功了,懒得升级
git 拉取google代码
python 用于让proto文件生成pb.h和pb.cc文件
ninja

一. 安装ninja

  1. git仓库拉取ninja
git clone https://github.com/ninja-build/ninja.git
  1. 进入git目录下切换到release分支
cd ninjia
git checkout release
  1. 在左下角搜索里找到x86 Native Tools Command Prompt for VS 2022 工具打开
    执行
python configure.py --bootstrap
  1. 配置ninja环境路径, 添加到path里(注意不能包含空格,所以Program Files那2个路径直接pass掉, 否则编译的时候就会出错)
    直接把ninja的目录的路径添加到环境环境的path里,windows下都懂的
    测试路径是否安装成功

输出提示的版本号:

> ninja --version
> 1.12.1

ninja安装成功!

二. 配置编译环境

  1. 下载libprotobuf
    创建build/_linux目录
    build/patch下有diff-base-on-3.19.0.diff文件
    build/linux下有 ue4-linux-cross-compile.cmake文件
    libprotobuf/tools下有generate_for_ue4.py文件,用于生成pb.h和pb.cc

配置环境变量 PB_LIBRARY_PATH 为 libprotobuf的路径
配置NINJA_EXE_PATH 为jinja目录下exe的路径, 直接把exe也包含到路径里
配置UE_THIRD_PARTY_PATH 路径为UE4引擎目录下的ThirdParty路径

用于混合编译的链的路径自不必说, 比如我的:

LINUX_ROOT  C:\UnrealToolchains\v19_clang-11.0.1-centos7\x86_64-unknown-linux-gnu
LINUX_MULTIARCH_ROOT  C:\UnrealToolchains\v19_clang-11.0.1-centos7\
NINJA_EXE_PATH  D:/ninja/ninja.exe
UE_THIRD_PARTY_PATH  C:\UnrealEngine4.27\Engine\Source\ThirdParty
UE_ROOT  C:/UNREAL //不是手动加的, UE4原本引擎代码目录
  1. 配置好以后:

在libprotobuf目录下的protobuf-source目录里拉取源代码

https://github.com/google/protobuf //3.19.x版本,实际上是3,19.6版本
  1. 生成cmake文件, 下面是我配置好的Linux 64x86目标平台的版本
cmake -G "Ninja Multi-Config" ^
-DCMAKE_MAKE_PROGRAM="%NINJA_EXE_PATH%" ^
-DCMAKE_TOOLCHAIN_FILE="%PB_LIBRARY_PATH%\build\linux\ue4-linux-cross-compile.cmake" ^
-Dprotobuf_ENABLE_RTTI=ON ^
-Dprotobuf_DISABLE_RTTI=OFF ^
-DUE_THIRD_PARTY_PATH="%UE_THIRD_PARTY_PATH%" ^
-Dprotobuf_DEBUG_POSTFIX="" ^
-DCMAKE_INSTALL_PREFIX="%PB_LIBRARY_PATH%/libprotobuf" ^
-DCMAKE_INSTALL_LIBDIR="lib/linux/$<$<CONFIG:Debug>:Debug>$<$<CONFIG:Release>:Release>" ^
-DCMAKE_INSTALL_CMAKEDIR="lib/linux/cmake" ^
-Dprotobuf_BUILD_TESTS=false ^
-Dprotobuf_WITH_ZLIB=false ^
-Dprotobuf_BUILD_EXAMPLES=false ^
-Dprotobuf_BUILD_PROTOC_BINARIES=false -Dprotobuf_BUILD_LIBPROTOC=false ^
"%PB_LIBRARY_PATH%/protobuf-source/cmake"

^是折行符号, 类似linux下的\符号

检查下 ue4-linux-cross-compile.cmake 路径是否是可以找到的路径
确保 NINJA_EXE_PATH 可以正确的输出版本信息的路径
确保UE_THIRD_PARTY_PATH 路径正确

会使用到build/linux/ue4-linux-cross-compile.cmake 和protobuf-source/cmake/CMakeLists.txt来生成cmake信息
在build/_linux路径下执行,会生成cmake文件一堆

CMakeCache.txt   build-Debug.ninja           install_manifest.txt
CMakeFiles/      build-RelWithDebInfo.ninja  lib/
Debug/           build-Release.ninja         protobuf-lite.pc
RelWithDebInfo/  build.ninja                 protobuf.pc
Release/         cmake_install.cmake

  1. 编译protobuf代码, 生成.a目标文件, 如果不生成, 那可能是protobuf-source/cmake/CMakeList.txt需要修改,一般不需要修改,因为上面的配置里已经配了
cmake --build . --target install --config Debug
cmake --build . --target install --config Release

运行着这二行会在build/_linux/Debug和Release目录生成libprotobuf.a和libprotobuf-lite.a文件

  1. 工具把.proto生成pb.h和pb.cc, 这个就不详细说了

  2. 把google文件放在项目里,然后Build.cs里填上路径
    PublicIncludePaths使用这个添加, 然后路径别写死, 最好使用Path.Combine去粘合, 为啥呢,因为是在windows系统下搞linux代码,使用的路径符号不同, 最好让它来解决
    添加库文件同理

if (Target.Platform == UnrealTargetPlatform.Linux){
    string googlepath = Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "googlepath");//googlepathgoogle文件夹上一层路径, 结合自己的去设置
    PublicIncludePaths.Add(Path.Combine(googlepath, "include"));
    PublicSystemLibraryPaths(Path.Combine(googlepath, "lib","Debug"));
    PublicAdditionalLibraries.Add(Path.Combine(googlepath, "lib", "Debug","libprotobuf.a")); //直接路径指定写死
} else if (Target.Platform == UnrealTargetPlatform.Ps4){

}else if (Target.Platform == UnrealTargetPlatform.Ps5){

}

不同的平台使用不同的链接库即可, 头文件是一样的
7. 编译代码链接protobuf, 可能报错RTTI, 没有找到运行时信息, 或者虚函数啥的
分析下报错的原因, 就是编译的时候没有开启RTTI运行时信息, 需要在CMakeList.txt里修改下,
添加

add_definitions(-DGOOGLE_PROTOBUF_NO_RTTI=0)
unset(protobuf_DISABLE_RTTI CACHE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti")
add_definitions(-DGOOGLE_PROTOBUF_CMAKE_BUILD)

开启运行时信息, 然后执行3和4步骤,重新配置cmake, 然后重新编译, 生成链接库, 再链接,OK了!

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐