其他分享
首页 > 其他分享> > 使用FASTBuild加速Unreal Engine编译

使用FASTBuild加速Unreal Engine编译

作者:互联网

前言

FASTBuild 原理简介

这个部分将会依据个人理解简单地介绍 FASTBuild 进行分布式编译的原理, 部分术语可能与官方不一致.

当我们编译大型项目的时候, 会有很多独立的编译单元(unit, 或者可以简单地理解为很多个cpp文件). 如果我们只用一台16核的机器, 同一时间最多只能够有16个unit被编译; 但是如果我们将 unit 发送到不同的机器上, 那么同一时间就可以编译 5 倍, 甚至 10 倍的编译单元. FASTBuild 正是通过使用多台机器同时编译多个 unit, 从而达到加速编译的目的.

FASTBuild架构

在这里插入图片描述

FASTBuild 系统中, 可执行文件分为FBuildFBuildWorker. 运行FBuild的机器(本地机器)则负责发出分布式编译的任务, 将编译单元发送给不同的主机. 而运行了 FBuildWorker 的主机(远程机器)负责执行编译任务.

为得知所有可以参与编译的 Worker, FASTBuild 需要一个所有机器都有读写权限的网络位置FASTBUILD_BROKERAGE_PATH. 远程机器在该位置下创建一个文件用于表示本机在线, 并且可以执行编译任务; 本地机器通过读取该位置下的所有文件, 获取所有远程主机, 并将编译单元发送至不同的Worker.

分布式编译

FASTBuild使用.bff文件指定编译操作, 其作用与CMakeLists.txt, Makefile类似. 不同的是.bff文件还用于保证编译环境的一致. .bff文件使用一种FASTBuild自带的语法, 并在其Compiler()等函数中定义了编译环境. 下面是UE源码相应的FBuild.bff, 可以看见其中包含了编译用到的exedll文件.

Compiler('UECompiler') 
{
	.Root = 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\bin\HostX64\x64'
	.CLFilterRoot = 'C:\UnrealEngine\Engine\Build\Windows\cl-filter'
	.Executable = '$CLFilterRoot$\cl-filter.exe'
	.ExtraFiles =
	{
		'$Root$/cl.exe'
		'$Root$/c1.dll'
		'$Root$/c1xx.dll'
		'$Root$/c2.dll'
		'$Root$/msvcp140_atomic_wait.dll'
		'$Root$/vcruntime140.dll'
		'$Root$/vcruntime140_1.dll'
		'$Root$/1033/mspft140ui.dll'
		'$CLFilterRoot$/1033/clui.dll'
		'$Root$/mspdbsrv.exe'
		'$Root$/mspdbcore.dll'
		'$Root$/mspft140.dll'
		'$Root$/msobj140.dll'
		'$Root$/mspdb140.dll'
		'$Root$/msvcp140.dll'
		'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC/Redist/MSVC\14.28.29910/x64\Microsoft.VC142.CRT/vccorlib140.dll'
		'$Root$/tbbmalloc.dll'
	}
	.CompilerFamily = 'msvc'
}

完成编译环境的定义后, FASTBuild 会根据.bff文件, 将编译依赖发送至所有主机上, 保证了一致的编译环境.

Cache

FASTBuild 提供了缓存功能, 能够将编译结果缓存至FASTBUILD_CACHE_PATH中. 这样下次编译的时候, 就可以直接从缓存中获取编译结果. 另外, 如果缓存位置为网络位置, 局域网中的其他人也能够使用缓存. 下面是 FASTBuild 作者对 Cache 的测试结果.

网络

由于编译时需要大量地发送和接收文件, 因此网络很容易成为编译时的性能瓶颈. FASTBuild 作者推荐在 1000M 的局域网下进行分布式编译, 个人测试 100M 也勉强凑合. 当然, 如果你所在的网络并不是局域网, 那么就需要慎重考虑了, 因为这很有可能会导致编译减速…

准备工作

环境变量

编译FASTBuild

由于后续需要修改 FASTBuild 源码, 我们首先尝试编译FASTBuild, 这里以 Windows 和 VS2019 为例.

首先是版本号的获取方法:

然后根据上一步获取的版本号修改bff文件:

完成修改后进入Code目录, 执行命令FBuild.exe All-x64-Release -dist -clean, 应当能够看见 FASTBuild 成功编译.

分布式编译FASTBuild

注意事项:

配置本地主机

本地主机执行分布式编译需要:

配置远程主机

分布式编译

完成配置后, 进入Code/目录, 继续执行FBuild.exe All-x64-Release -dist -clean, 应当能看见:

使用FASTBuild分布式编译Unreal Engine源码

修改IP地址

原始的 FASTBuild 默认通过主机名称寻找远程主机, 这里修改为使用主机IP地址.

代码修改比较简单, 可以参考这次Commit.

适应Unreal官方FASTbuild.cs

Unreal 官方修改了 FATSBuild, 并以二进制可执行文件的方式放在了引擎源码目录Engine/Extras/ThirdPartyNotUE/FASTBuild中, 另外还提供了FASTBuild.cs用于生成bff文件. 官方修改的思路是在bff文件中, 为Unreal编译器添加额外的Compiler. Engine/Extras/ThirdPartyNotUE/FASTBuild/fbuild_0.99.diff中记录了修改的内容, 需要参考该文件修改 FASTBuild 源码. 也可以参考这次Commit.

压缩编译结果

根据《腾讯游戏开发精粹》, 此阶段的性能瓶颈应当出现在网络部分, 这是因为FASTBuild只压缩编译单元, 没有压缩编译结果. 所以这里对编译结果进行压缩, 然后再传输和解压.

修改的内容不多, 可以参考这次Commit.

分布式编译 Unreal 源码

Compiler('UEResourceCompiler') 
{
	.Executable = '$WindowsSDKBasePath$/bin/10.0.18362.0/x64/rc.exe'
	.CompilerFamily  = 'custom'
}

Compiler('UECompiler') 
{
	.Root = 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\bin\HostX64\x64'
	.CLFilterRoot = 'C:\UnrealEngine\Engine\Build\Windows\cl-filter'
	.Executable = '$CLFilterRoot$\cl-filter.exe'
	.ExtraFiles =
	{
		'$Root$/cl.exe'
		'$Root$/c1.dll'
		'$Root$/c1xx.dll'
		'$Root$/c2.dll'
		'$Root$/msvcp140_atomic_wait.dll'
		'$Root$/vcruntime140.dll'
		'$Root$/vcruntime140_1.dll'
		'$Root$/1033/mspft140ui.dll'
		'$CLFilterRoot$/1033/clui.dll'
		'$Root$/mspdbsrv.exe'
		'$Root$/mspdbcore.dll'
		'$Root$/mspft140.dll'
		'$Root$/msobj140.dll'
		'$Root$/mspdb140.dll'
		'$Root$/msvcp140.dll'
		'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC/Redist/MSVC\14.28.29910/x64\Microsoft.VC142.CRT/vccorlib140.dll'
		'$Root$/tbbmalloc.dll'
	}
	.CompilerFamily = 'msvc'
}

使用FASTBuild分布式编译项目

// Interesting flags for FASTBuild:
// -nostoponerror, -verbose, -monitor (if FASTBuild Monitor Visual Studio Extension is installed!)
// Yassine: The -clean is to bypass the FASTBuild internal
// dependencies checks (cached in the fdb) as it could create some conflicts with UBT.
// Basically we want FB to stupidly compile what UBT tells it to.
string FBCommandLine	= $"-j16 -monitor -summary {DistArgument} {CacheArgument} {IDEArgument} -clean -config \"{BffFilePath}\" {NoStopOnErrorArgument} {ForceRemoteArgument}";

使用FASTBuild分布式编译Shader

分布式编译Shader需要修改引擎编译工具源码, 基本的思路是将XGE的编译方式修改为FASTBuild. 可以参考这次Commit. 注意我将ShaderCompilerFASTBuild.cppFASTBuild_CachePath硬编码为了F:\\Cache, 你应当修改为正确的路径.

完成这些步骤后, 在%TEMP%\FASTBuild\FASTBuildLog.Log中能够看见Shader编译成功.

可能出现的问题

参考文献

  1. 《腾讯游戏开发精粹》
  2. 保姆式教你使用FASTBuild对UE4进行联机编译
  3. FASTBuild 文档
  4. Shader编译参考

标签:Engine,exe,修改,dll,编译,Unreal,FASTBuild,Root
来源: https://blog.csdn.net/cjw_soledad/article/details/117362397