ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Piccolo引擎编译全攻略:从CMake配置到第三方依赖排查

Piccolo引擎编译全攻略:从CMake配置到第三方依赖排查 第一次接触 Games104 的 Piccolo 引擎时我心里想的是这套课讲得这么细一个教学用的小引擎编译应该不会太难吧。结果 CMake 配置阶段就卡了半个多小时后面编译又连续撞上几堵”看似不相关“的报错墙兜兜转转才把编辑器跑起来。回头看真正源自引擎自身代码逻辑的错误非常少几乎全是工具链、第三方依赖、路径和构建配置这些“工程问题”在捣乱。这篇文章把我自己在几台不同机器上反复编译后整理的思路写出来也参考了社区里常见反馈。内容是围绕 Piccolo 引擎源码从拉取到编译通过的完整排查方案目标读者是刚接触 Games104、准备自己编译引擎的新手或者已经在报错里熬了一晚上、想快速找到出口的同学。读完你至少能明白报错从哪里来、按什么顺序查、每一步要怎么改。1. 动手编译前先把环境底子打好很多人一上来就 clone 源码然后打开 CMake结果一大堆红字其实大部分问题在环境准备阶段就可以避免。环境没搭好后面每一步都会像多米诺骨牌一样连续倒而且报错方式千奇百怪排查起来特别消耗耐心。所以这个阶段值得多花十分钟。1.1 工具链准备版本决定了很多报错的长相Piccolo 是教学项目不是说必须用最新版工具但版本跨度不能太大。我自己踩过的教训是编译器太老项目里某些 C17 甚至更新的写法会直接编译失败CMake 太老则可能识别不了较新版本的 Visual Studio 生成器。Windows 平台上基础组合建议是这样的组件推荐版本注意事项操作系统Windows 10/11 x64路径尽量纯英文避免中文用户名Visual Studio2022 17.6 或更高安装时必须勾选“使用 C 的桌面开发”CMake3.21 或更高安装时勾选加入系统 PATH或手动配置Git2.40 或更高Windows 下建议开启开发者模式利于符号链接创建Vulkan SDK1.3.x 最新稳定版装完整 SDK不是只装 runtimePython33.10 或更高部分资源处理脚本会调用需要加入 PATH这里重点说几个容易忽略的地方。Visual Studio 的 C 工作负载必须完整安装否则可能 CMake 配置阶段没问题到了编译阶段才报找不到 Windows SDK 头文件。Windows SDK 版本不用特别纠结跟随 VS 安装器默认安装即可。Vulkan SDK 这个坑相当隐蔽。如果只装了显卡驱动自带的 runtime而没有装 LunarG 的完整 SDKCMake 执行find_package(Vulkan)时就会提示找不到或者即使强制生成工程后编译器也找不到vulkan/vulkan.h。解决办法是到 LunarG 官网下载并安装完整 SDK安装完成后必须重新打开终端或重启 VS让VULKAN_SDK环境变量生效。还有一条很多教程都没提整个仓库所在路径不能有中文、空格或者特殊符号。C:\Users\张三\Desktop\Piccolo这种路径表面看不会影响阅读但 MSVC 对不同编码路径的支持时好时坏C 头文件包含、脚本调用、资源加载都会变得极其不稳定。我见过有人在中文路径下缺了vulkan.h把项目挪到D:\dev\Piccolo后干净构建一次问题直接消失。这种事听起来玄学但实际概率并不低宁可一开始就避开。1.2 submodule 与第三方依赖八成报错从这里来如果说环境是地基那第三方依赖就是承重墙。Piccolo 源码里大量使用的第三方库是通过 Git submodule 方式挂在仓库里的简单说就是“仓库里记录了另一个仓库的引用但 clone 时并不会默认把那个仓库内容一起拉下来”。如果你直接点了页面上的下载 ZIP或者 clone 时漏掉了递归参数那 ThirdParty 相关目录就会是空的或者半空的。正确的拉取依赖方式有两种。第一种clone 时直接带递归参数git clone --recursive Piccolo仓库地址 Piccolo第二种已经 clone 了但当时没带参数cd Piccolo git submodule update --init --recursive如果你不确定当前状态是否完整可以检查一下git submodule status如果某一行输出的开头是-比如-abcdef1234567890 ThirdParty/imgui就说明这个子模块还没有真正检出到本地必须重新执行 update。如果输出开头没有-基本可以认为子模块状态正常。另外在 Windows 上拉取子模块时经常遇到 “unable to create symlink” 的提示。原因通常是当前进程没有创建符号链接的权限。解决办法是在 Windows 设置里打开“开发者模式”或者用管理员权限的终端重试。这个细节不处理后期会出现文件缺失的报错而且报错位置千奇百怪很难联想到是这里的 symlink 失败了。1.3 为什么不要“缺什么就自己装什么”有些同学在编译遇到缺少某个库时会直接去网上搜一个同名最新版装进系统然后在 CMake 里改路径指向那个库。这个操作在普通应用项目里或许可行但在 Piccolo 这种强依赖固定版本的项目里往往会引入新的 ABI 不兼容问题。打个比方你的项目是按某个版本的“积木接口”拼好的现在你换了一套外形相似但卡扣位置不一样的积木拼到一半必定滑丝。尤其是 assimp、glfw、imgui 这类库新老版本之间接口差异可能很大不仅可能编译不过就算编译过了也可能在运行时出现内存布局不匹配导致的崩溃。所以我的建议是除非 README 明确说支持系统安装版否则一律使用仓库内置的第三方依赖。下载源码后先检查 ThirdParty 目录是否完整不完整就重新拉取子模块不要自己瞎换库。2. 编译报错的底层原因与排查思路环境准备好了依然可能报错。这时候别急着把错误日志复制到搜索引擎先学会判断这个报错发生在哪个阶段。阶段不同排查策略完全不一样。2.1 把报错分成三阶段configure、build、link一次从源码到可执行程序的构建严格来说要经历三个阶段。第一阶段是配置阶段也就是执行cmake -S . -B build的时候。CMake 会检查各种依赖是否存在、编译器是否可用、第三方库路径是否正确。这个阶段报错通常长这样Could NOT find Vulkan、Could NOT find Python3或者干脆CMake Error: The source directory does not contain a CMakeLists.txt file。这类报错直白基本告诉你“某个零件我找不到”。第二阶段是编译阶段也就是真正调用编译器的阶段。MSVC 风格的报错以C开头比如C1083: Cannot open include file: vulkan/vulkan.h、C2065: xxx: undeclared identifier。这类报错发生在你把源码变成目标文件的过程中。第三阶段是链接阶段报错以LNK开头比如LNK2019: unresolved external symbol、LNK1104: cannot open file vulkan-1.lib。这类报错发生在所有目标文件已经生成、需要把它们合成一个可执行程序的时候。为什么要区分阶段因为同一个根因在不同阶段会表现出不同症状。比如 submodule 没拉全在 configure 阶段可能整个 CMakeLists 都找不到如果强行生成工程编译阶段就会报找不到某个第三方头文件再往后走可能还会出现一堆无法解析的外部符号。如果你不看根因只盯着最后一个LNK报错去搜可能搜半天都搜不到真正答案。2.2 多数编译报错的共同触发点我整理过几台机器上遇到的报错发现真正高频的触发点就几个第三方依赖不完整。这是最常见的一个占比可能超过一半。路径问题包括中文路径、过长的路径、带有同步盘特殊属性的路径。机器上并存了多个版本的 Vulkan SDK 或第三方库CMake 找到了错误的那个。Visual Studio 的 C 工作负载或 Windows SDK 组件不完整。内存不足编译过程中直接out of heap space。杀毒软件或系统文件锁导致文件无法访问。其中最后一个很容易被忽略。我自己遇到过编译中途大量文件报“Access denied”的情况排查了很久才发现是云同步盘把构建目录当成同步目录底层不断在读写文件导致编译器访问冲突。把仓库移到本地普通目录并排除杀毒软件白名单后问题就消失了。这里还有一个容易被新手误解的地方VS 的“错误列表”里经常塞满了 IntelliSense 的“伪错误”这些红色波浪线看着吓人但可能编译实际是成功的。真正要看的是“输出”窗口里的“生成”选项卡那里才是编译器真实输出的日志。很多人被误导到错误的方向就是因为看错了信息源。2.3 从日志里快速定位问题的方法日志一多就容易慌。我的习惯是先看第一个 error不要被海量后续错误带着跑。因为 C 头文件是层层包含的一个头文件缺失可能导致几百个编译错误但只要把第一个报错对应的文件补上后续几百个会瞬间消失。看错误的时候要多看几行上下文。比如fatal error C1083: Cannot open include file: imgui.h: No such file or directory这里给出的文件名已经很有线索重点要去看是哪个.cpp文件触发的 include。如果触发点是一个第三方库封装文件那大概率是第三方依赖本身没有正确加载。如果错误量大到难以阅读可以把输出重定向到文件里再搜索关键词cmake --build build --config Release build_log.txt 21然后在文件里搜索error C、error LNK、fatal error这些关键字比在 VS 输出窗口里翻滚动条高效得多。Windows PowerShell 下同样支持重定向。把握住一点错误日志里真正需要关注的只有最上游的“因”后面的几百行多数是“果”。找到那个因你就已经解决一多半问题了。3. 实操记录一套比较稳的完整编译流程理论说再多不如看一套完整命令。下面是我试过多次、在不同机器上都能顺利跑通的流程每一步解释一下为什么这么写。3.1 从空目录到生成工程的一条龙命令首先保证当前目录干净然后执行git clone --recursive Piccolo仓库地址 Piccolo cd Piccolo git submodule update --init --recursive三次命令其实是保险措施第二次 clone 通常已经把子模块拉下来了但网络抖动或中断可能让个别子模块不完整再执行一次 update 能把缺失的补上。执行完git submodule status检查确认没有输出-开头的内容这一步就结束了。接下来配置构建目录cmake -S . -B build -G Visual Studio 17 2022 -A x64-S .指定源码根目录-B build指定构建输出目录。-G指定生成器Visual Studio 2022 对应的生成器名称就是Visual Studio 17 2022。如果用的是 VS2019需要改成Visual Studio 16 2019。-A x64指定目标平台为 64 位这一点很重要。很多人配置阶段喜欢直接cmake ..不加参数结果默认生成了 Win32 工程。Win32 工程遇上绝大多数第三方库的 x64 版本会产生架构不匹配的链接错误那种报错很难看懂。所以生成器参数最好一次写对。配置成功后正常情况下会生成build/Piccolo.sln和一堆 CMake 中间文件。如果配置阶段报错不要继续往下走回到上一节的方法去解决依赖问题。3.2 编译时到底选哪个目标在大型的 VS 工程里ALL_BUILD会编译所有目标既慢又容易引入无关错误。更推荐的做法是只编译实际需要的主程序目标。Piccolo 作为引擎通常会有 Editor 和 Runtime 之类的目标但不同版本命名不一定一致。最稳妥的确认方式是用命令列出所有目标cmake --build build --target help运行后会输出一长串可构建的目标名称找到类似PiccoloEditor或者对应编辑器程序的那个名字。如果实在不确定直接查找仓库根目录 CMakeLists 里add_executable行看第一个参数是什么那个就是目标名。例如主目标是PiccoloEditor编译命令就是cmake --build build --config Release --target PiccoloEditor --parallel 8--config Release指定编译配置--parallel 8让 CMake 在编译时用 8 个并行任务。如果你的 CPU 核心数比较少可以改成--parallel 4甚至更低避免内存不够时整机卡死。如果并行编译导致内存被吃满可以先把 VS 里占用资源的大工程全部关掉或者暂时调大系统虚拟内存。不要硬扛硬扛的结果往往是一堆莫名其妙的编译器崩溃根本定位不到真实原因。3.3 编译过程中的几个现场记录我在实际编译时遇到过几次比较典型的故障这里记录一下当时的处理过程。第一次是配置阶段就报Could NOT find Vulkan。我当时以为装了 Vulkan runtime 就够了后来才意识到缺的是完整 SDK。而且安装 SDK 后没有立刻生效因为终端里的环境变量还是旧值。重启终端再执行 CMake 后问题解决。第二次是编译阶段报了一堆cannot open source file imgui.h。我当时已经执行过 clone 的递归参数但检查后发现 ThirdParty 目录里 imgui 文件夹是空的原因是子模块拉取时网络中断git 没有报错只是留下了不完整状态。执行git submodule update --init --recursive修复后重新编译就通过了。第三次是链接阶段出现大量LNK2019当时一头雾水。后来发现自己同时在系统里装了一个旧版本的 glfw而 Piccolo 内置的 ThirdParty 目录根本没有被优先使用。CMake 默认的搜索顺序里系统库路径排在项目本地路径前面导致链接时找到的是不匹配的库文件。清理掉系统里的旧版开发库后让 CMake 只认本地 ThirdParty问题迎刃而解。这几个例子说明编译报错的原因往往不在代码本身而是工程管理层面的问题。遇到类似情况时优先怀疑依赖完整性、路径、版本冲突这三件事。4. 高频报错速查与避坑笔记为了方便以后快速排查我把整理过的高频错误做成了一张速查表。遇到报错时先对照一下大概率能少走不少弯路。4.1 高频报错对照表报错或现象大概率的根因解决动作Could NOT find VulkanVulkan SDK 未安装或环境变量未刷新安装完整 LunarG SDK重启终端C1083: cannot open include file: vulkan/vulkan.hSDK 头文件路径没传给编译器确认VULKAN_SDK变量存在删除 build 目录重配LNK1104: cannot open file vulkan-1.lib链接器找不到 Vulkan 库确认 SDK 已装、目标平台是 x64LNK2038: RuntimeLibrary mismatchDebug/Release 混编或运行库设置不一致清理后统一使用相同配置重新编译fatal error C1060: compiler is out of heap space内存不足降低并行数量关闭其他高内存程序C1083: cannot open include file: imgui.hsubmodule 未拉全执行git submodule update --init --recursiveCMake Error: source directory does not contain CMakeLists.txt子模块目录为空或不完整检查 ThirdParty 目录重新拉取子模块CMake 识别不了 VS2022CMake 版本过老升级 CMake 到 3.21 以上编译过程大量出现 Access denied文件被占用或同步盘锁文件关闭 OneDrive 同步、杀毒软件实时扫描重启 VS程序生成时报 MSB3073 返回码 1某个自定义构建步骤失败看具体输出通常是 Python 或 shader 编译步骤出错特别注意这些报错不是孤立存在的一条错误可能同时伴随多个连锁反应。比如C1083报找不到某个头文件之后后面几百条错误全是“未定义的标识符”。这时别去逐条分析后面的错误先把头文件缺失问题解决后面会一并消失。4.2 复制报错去搜索前先做的自查清单很多人在群里贴出一大段报错日志之前其实可以先花一分钟做几项检查这样问题通常就自己水落石出了。工程目录是否放在纯英文路径下如果不是先挪目录再试。是否确认过git submodule status没有-前缀如果没确认先确认。Vulkan SDK 是否安装在最新稳定版环境变量是否在当前终端里生效用的是全新的 build 目录吗如果残留了以前的 CMake 缓存先删掉build目录重新配置。看的是 VS 输出窗口里的“生成”日志还是错误列表里的波浪线后者可能只是 IntelliSense 的干扰项。机器是否开了 OneDrive 或其它云同步盘并且把代码目录放进了同步目录这个原因隐蔽但影响巨大。尤其最后一条现在很多 Windows 机器默认开启了 OneDrive桌面和文档目录都在同步范围内。如果你把源码放在桌面或者文档里编译时大量文件被同步进程锁定就会出现间歇性的文件访问失败。这种问题只看报错文本很难定位因为错误看起来是访问冲突实际是同步软件在后面搞事。把项目挪到D:\dev这类本地目录后一切恢复正常。4.3 几个只是“看着吓人”的提示不是所有红字都代表失败。有些内容是警告或者信息性输出如果分不清会浪费很多时间。比如 MSVC 的warning C4996通常只是说某个函数被标记为 deprecated不影响生成结果。CMake 输出里的Found Vulkan: ...也不是错误只是告诉你拿到了某个版本。还有大量warning LNK4098往往只是运行库和某个库的默认设置不同只要没有产生链接错误不一定需要处理。判断标准只有一个最后有没有生成你想要的.exe文件。如果文件生成了过程中有些 warning 完全可以忽略。如果没生成再去找 error 级别的日志。5. 编译通过之后还有几个容易误判的点很多人以为编译通过了就万事大吉结果双击 exe 跑不起来又开始怀疑是不是“另有隐藏报错”。其实大部分情况不是编译问题而是运行环境和目录结构的问题。5.1 别急着把 exe 拷出来单独运行Piccolo 这类引擎在运行时要加载大量资源文件、shader、配置文件它对这些文件的定位通常是相对于“工作目录”的。如果你从资源管理器双击build/bin/Release/PiccoloEditor.exe工作目录会是 exe 所在目录但资源文件并不在那里于是程序会在启动阶段报找不到文件甚至直接崩溃。正确做法是在工程目录根目录下启动程序或者在 IDE 里配置工作目录为资源根目录。用 Visual Studio 调试运行的话在项目属性里的“调试”选项卡里把“工作目录”设置为项目根目录再启动就能正确加载资源。我自己很多时候以为是编译不全或者代码 bug回来一看就是这个工作目录的问题。这个知识点在官方文档里通常一句话带过但实操中影响极大。5.2 编译成功后启动崩溃优先查显卡和驱动如果排除了工作目录问题启动时还是闪退或者报 Vulkan 相关错误先检查显卡驱动是否更新、GPU 是否支持 Vulkan 1.2 以上特性。有的集显或者较旧的独显硬件上确实跑不了这个引擎这属于硬件层面的运行问题不是编译问题。有一种易混淆的场景在远程桌面或虚拟机里运行渲染设备能力不足程序同样可能在创建渲染上下文时失败。如果你是在虚拟机里编译建议只在虚拟机里验证编译是否通过实际运行最好换到真实物理机上。5.3 改完代码想快速验证用增量编译而不是全量重建引擎项目源码量不小每次修改代码都重建整个工程会很痛苦。大多数情况下你只是改了一两个类只需要执行cmake --build build --config Release --target PiccoloEditor --parallel 8CMake 和 MSBuild 会自动检测文件变更只重新编译受影响的源文件再执行链接通常几秒钟到十几秒钟就能完成一次验证。如果改了 CMakeLists 里的依赖关系或编译选项则需要重新执行 CMake 配置命令让构建系统知道这一步变化再继续 build。这个工作流熟练之后整个编译-调试循环会顺畅很多。我自己在多次折腾后的体会是这类编译报错十有八九不是你的 C 能力问题更多是几个固定环节的工程配置问题。把环境清单从头到尾过一遍再用干净的 build 目录重新构建一次绝大多数问题都能解决。至少我后来在另一台电脑上从 clone 到跑起来整个流程十分钟内就完成了和第一次卡一下午的体验完全不同。
返回列表