UBT如何编译UE4工程代码

流程图

(表格 1)

绘制了一张 compile 和 link 的过程调用关系图。

断点调试UBT

其中Program arguments 是运行UBT的参数,填写:

{你的项目名}Editor Win64 Development {你的项目完整路径}.uproject -waitmutex -log={你想要的日志完整路径}.log

适当地修改项目代码中的任意C++文件,目的是能够断到以下这个位置,给以下这个位置加断点:

// EngineSource\Engine\Source\Programs\UnrealBuildTool\Platform\Windows\VCToolChain.cs
public override CPPOutput CompileCPPFiles()

并且开始调试,很快就会看到:

它的含义是UBT(C#工程)本身编译成功了,而非项目代码编译成功了。随后不久,上面代码处就会被断到。

基于这个调试方法,我学习了UBT的编译、链接的过程。如果再次调试发现没有经过某些方法,则可能是因为本地没有代码变更,导致编译逻辑触发不了,解决方法是适当修改项目代码。

CompileAction

在 UnrealBuildTool.VCToolChain.CompileCPPFiles 的结尾处断点,可以看到

Actions.Add(CompileAction)

这里的CompileAction其实就是调用 cl-filter.exe 的。哟,这不就是我们在UE4 VS编译中常常看到的熟人吗?cl-filter.exe 是会过滤日志信息的C++ compiler,是底层的程序。我找出其中第一条包含 cl-filter.exe 的指令并排版,如下:

G:\St\EngineSource\Engine\Build\Windows\cl-filter\cl-filter.exe 

-dependencies=G:\St\EngineSource\Engine\Intermediate\Build\Win64\UE4Editor\Development\Launch\Module.Launch.cpp.txt 
-compiler="C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.40.33807\bin\HostX64\x64\cl.exe" 
-- "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.40.33807\bin\HostX64\x64\cl.exe"  
@"G:\St\EngineSource\Engine\Intermediate\Build\Win64\UE4Editor\Development\Launch\Module.Launch.cpp.obj.response" 
/showIncludes

又另外找了一条:

G:\St\EngineSource\Engine\Build\Windows\cl-filter\cl-filter.exe 

-dependencies=G:\St\EngineSource\Engine\Intermediate\Build\Win64\UE4Editor\Development\UnrealEd\SharedPCH.UnrealEd.ShadowErrors.NoUndef.h.txt 
-compiler="C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.40.33807\bin\HostX64\x64\cl.exe" 
-- "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.40.33807\bin\HostX64\x64\cl.exe"  
@"G:\St\EngineSource\Engine\Intermediate\Build\Win64\UE4Editor\Development\UnrealEd\SharedPCH.UnrealEd.ShadowErrors.NoUndef.h.pch.response" 
/showIncludes

它们其实就是一种能用windows batch运行的简单指令,一次完成“编译动作”中的一小个步骤。其中真正执行编译的是指令中提到的 cl.exe 。这种由 cl.exe 完成的指令,就是编译的指令,也就是 CompileAction 。

LinkAction

继续在以下位置断点,我们看看什么是LinkAction。

UnrealBuildTool.VCToolChain.LinkFiles

LinkActions如下,也是熟人。

G:\St\EngineSource\Engine\Build\Windows\link-filter\link-filter.exe - -- "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.40.33807\bin\HostX64\x64\link.exe" @"G:\St\EngineSource\Engine\Intermediate\Build\Win64\UE4Editor\Development\UE4Editor-Cmd.exe.response"

link-filter.exe 就是链接器的意思。link.exe会滔滔不绝输出日志,而link-filter.exe则是一道封装,把开发者需要关注的信息过滤出来。这就是 LinkAction 了

最终,CompileAction 和 LinkAction 的集合,以及一些林林总总的指令,加起来,就是Actions了,也就是表格1 中的Actions了。

Response文件

上面这些指令里提到了 .response 。随便举一个实际的  .response  文件 G:\St\EngineSource\Engine\Intermediate\Build\Win64\UE4Editor\Development\UE4Editor-Cmd.exe.response  来理解它的含义:

/MANIFEST:NO
/NOLOGO
/DEBUG
/errorReport:prompt
/MACHINE:x64
/SUBSYSTEM:CONSOLE
/ENTRY:WinMainCRTStartup
/FIXED:No
…… // 省略很多
"dwmapi.lib"
"imm32.lib"
"ThirdParty//Superluminal/Lib/PerformanceAPI_MD.lib"
"uiautomationcore.lib"
"G:\St\EngineSource\Engine\Intermediate\Build\Win64\UE4Editor\Development\Core\UE4Editor-Core.lib"
"G:\St\EngineSource\Engine\Intermediate\Build\Win64\UE4Editor\Development\CoreUObject\UE4Editor-CoreUObject.lib"

了解编译原理的开发者,应该看得出来,前面的很多都是控制编译过程的参数字段,例如说是否处在 DEBUG 等等,后面的则是实际引用关联的 lib 库等。

如果没有Response文件,这些参数就需要硬生生地传给 cl-filter.exe 或 link-filter.exe,非常麻烦。因此 Response 文件的作用,就是将编译参数“沉淀”下来,方便地传递给 cl

Response文件的创建见 CreateIntermediateTextFiles() 方法前后。

实际执行编译

最终实际执行编译如表格1中的 ActionGraph.ExecuteActions ,这里就是将所有的任务执行完成的地方,用的是 C# 的ActionGraph,这是C#自带的任务执行系统,其实就是不断地调用 Thread 。最终就能够看到我们熟悉的日志:

[bk_ubt_tool] [121/137] link-filter.exe @G:\S\EngineSource\Engine\Intermediate\Build\Win64\ShaderCompileWorker\Development\Json\ShaderCompileWorker-Json.dll.response
[bk_ubt_tool] [122/137] link-filter.exe @G:\S\EngineSource\Engine\Intermediate\Build\Win64\ShaderCompileWorker\Development\FileUtilities\ShaderCompileWorker-FileUtilities.dll.response
[bk_ubt_tool] [123/137] link-filter.exe @G:\S\EngineSource\Engine\Intermediate\Build\Win64\ShaderCompileWorker\Development\ImageCore\ShaderCompileWorker-ImageCore.dll.response

代码位于

Log.TraceInformation("[{0}/{1}] {2}", NumCompletedActions, InputActions.Count, CompletedAction.LogLines[0]);

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值