使用clangd在UE项目中阅读Unreal Engine源代码 🔗
本文介绍了如何为clangd生成Unreal引擎源代码的compilation database。
工欲善其事必先利其器,让我们使用clangd打造高效的UE代码环境吧。
Why 🔗
安装引擎时同时也会安装源代码。
- 此时使用Visual Studio打开一个C++ UE 项目,在Engine部分能够查看源代码,大部分代码可以跳转与阅读,但是比较缓慢。少部分代码标红,一些宏定义完全是错误的。
- 此时使用clangd配置的VSCode打开一个C++ UE 项目,UE5会以Workspace的一个文件夹的形式打开,此时引擎中的头文件以及源代码充斥着大量的错误,跳转完全无法工作。
clangd虽然功能强大,但特别依赖配置,clangd对于项目所需要知道的信息,和能成功编译项目的编译器所需要知道的信息是一样多的。这也是解释了为什么compile_commands.json可以被叫做compilation database。UE引擎这样的大型项目,又没有使用cmake这类构建工具,很难有开箱即用的通用自动化工具生成compilation database。所以还是需要求助于U++自己的自动化工具。
U++代码的特殊性在于:
- UE的引擎代码包含Cpp文件与一部分header的Private部分,也包含全部由header组成的Public部分。两部分依赖的头文件路径不同。
- 不同的引擎组件,不同的内置plugin,依赖的头文件也不同,不能让所有的文件都是用同一套include路径。
- UE中的源代码只是U++的源代码,需要经过Unreal Header Tool处理,自动生成类型信息后才是完整的C++代码。这些生成的代码是
.generate.h
与.gen.cpp
等。 - Unreal Build Tool还为不同的组件在不同配置下生成了不同的定义文件,定义宏开关,控制条件编译下的代码。
由于笔者对Visual Studio的配置不够熟悉,所以本文不会探究为什么Visual Studio打开的C++ UE 项目能够基本可用的阅读UE引擎代码。 但是综上所属,想要让clangd知晓的信息像(能完整编译引擎的)编译器一样多,开箱的情况下差的很远。
How 🔗
下面介绍的如何配置,基于Linux环境下的Unreal Engine。( 所以为什么我一定要用VScode做C++ UE 项目的编辑器呢?:)
- clone同版本tag的引擎源码,注意添加–depth=1,否则会拉下来大量的历史commit。
- Run
Setup.sh
andGenerateProjectFiles.sh
, 让项目变得完整。(这里需要下载20G的文件,缓存在.git/ue-gitdeps中,可以复制出去,当传家宝共享给其他版本的引擎代码) - (Windows) .\Engine\Build\BatchFiles\RunUBT.bat -mode=GenerateClangDatabase -Target=UnrealEditor Development Win64
- (Linux) ./Engine/Build/BatchFiles/RunUBT.sh -mode=GenerateClangDatabase -Target=UnrealEditor Development Linux
上一步生成了很多文件,跟踪新建的文件并分析:
- 其中所有新产生的UnrealEditorGCD文件夹都是Epic预编译版没有的,对于代码补全,我们只关心其中新生成的.h .cpp .rsp文件
- 在目录
^./Engine/(Plugins|Intermediate)
生成了很多^.*(generated\.h|gen\.cpp|Classes\.h|gen\.h|Definitions\.h)$
文件,这些都是让U++变为完整C++所需要的。 - 对比上一条新生成的文件列表,在Linux版预编译release的引擎中,有几十个中间生成文件在预编译release版也存在。而在Windows下的通过Epic Launcher安装预编译release版引擎,有上万个被保留下来的中间生成文件。(可能这也是Visual Studio用来阅读引擎代码能够刚刚好能用的原因?)
- 最重要的一点是,观察生成的rsp文件、以及引用rsp文件的compile_commands.json里的编译命令,全部使用了相对目录表示。这个相对目录是相对于compile_commands.json给编译指令指定的directory属性的。
- 最终,compile_commands.json本身是使用绝对目录表示的。但仅限于directory属性以及源代码路径。
经过上面的分析,补全U++到C++的所需要的生成文件模式很统一。我们是可以把这些补全信息搬运到release版的引擎中的!
上bash代码
# make sure in UE source dir
cd /media/store/UnrealEngineOfficial/UnrealEngine
# set up TARGET_ROOT, generated files will be put here
TARGET_ROOT=/media/store/UnrealEngineOfficial/UE5_CompilationDatabase
#UE_ROOT=/media/store/UnrealEngineOfficial/Linux_Unreal_Engine_5.4.2
# generate Required Intermediate Files
./Engine/Build/BatchFiles/RunUBT.sh -mode=GenerateClangDatabase -Target=UnrealEditor Development Linux
# copy compile_commands.json
mkdir -p "${TARGET_ROOT}/.vscode"
cp compile_commands.json "${TARGET_ROOT}/.vscode"
# patch absolute path
sed "s#$(pwd)#${TARGET_ROOT}#g" -i "${TARGET_ROOT}/.vscode"/compile_commands.json
# generate clangd config
cat > "${TARGET_ROOT}/.clangd" <<EOF
CompileFlags:
#Compiler: /usr/bin/g++
CompilationDatabase: .vscode
Add:
- -std=gnu++20
- -stdlib=libstdc++
EOF
# only copy files we interested
while read; do cp --parent -vn "$REPLY" "${TARGET_ROOT}"/; done < <(
find ./Engine/Plugins/ ./Engine/Intermediate/ -type f -name '*generated.h' -or -name '*gen.cpp' -or -name '*Classes.h' -or -name '*gen.h' -or -name '*Definitions.h' | grep -v UnrealEditorGCD;
while read; do find "$REPLY" -name '*.h' -or -name '*.cpp' -or -name '*.rsp'; done< <(find -name UnrealEditorGCD -type d)
)
然后就可以将UE5_CompilationDatabase打包了,使用的时候只需要再次替换compile_commands.json里的绝对路径,然后覆盖到预编译版本引擎中即可。 如此不需要自己编译引擎也能够获得完整的clangd体验。由于windows下引擎安装位置固定,这一步还可以更“自动”一点。
还需注意的一点是,Windows下不要随意的覆盖Compiler配置,clangd会根据使用的是clang++.exe还是clang-cl.exe解析rsp文件中编译器指令采取哪个平台的格式。
产物 🔗
下面的连接包含按照上述步骤打包好的clangd compilation database以及需要的中间文件,包含Linux与Windows两个平台可用的版本。
https://1drv.ms/f/s!AgkXMslnDVNlumVlSLbVONthimwd?e=w6c7ID
也可以从下面的本站链接下载:
5.4.2
5.4.3
5.4.4
最后推荐一个VSCode下增强UE开发体验的插件unreal clangd。
Update 🔗
update 2024/11/08 🔗
更新了5.4.4的编译产物
update 2024/11/09 🔗
关于UE4的clangdb生成
- 4.24版本开始的UBT才添加了GenerateClangDatabase
- 早期的UBT不会调用UHT生成header,要完整编译后才有生成的相关header
- 早期的UBT在windows下会固定使用默认安装路径下的外部clang作为工具链,
而非使用Visual Studio安装的clang。
推荐使用VS2022安装“Clang C++编译器”与“LLVM (clang-cl)工具集”,
然后管理员cmd运行mklink /J "C:\Program Files\LLVM" "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm"
,创建联接。 - Windows下UBT编译需要安装指定版本的.net SDK。
- Linux下需要手动给
GenerateClangDatabase.cs
打这个补丁pr8663,
然后运行GenerateProjectFiles.sh
重新编译UBT。
PS: GenerateClangDatabase模式在UE5.0才将Linux与Mac支持加入。 - Windows直接调用UBT,使用如下命令生成clangdb
cmd:Engine\Binaries\DotNET\UnrealBuildTool.exe -mode=GenerateClangDatabase UE4Editor Linux Development
Linux下需要使用build.sh自动配置mono环境
./Engine/Build/BatchFiles/Linux/Build.sh -mode=GenerateClangDatabase UE4Editor Linux Development