
简介面向在 Windows 平台使用 Qt 5.15.2 构建 Cutelyst Web 应用的开发者这份编译产物提供了带 Grantlee 视图支持的 Cutelyst 动态库解决模板引擎集成时缺少现成 Windows 二进制的问题尤其适合希望快速上手 Cutelyst 的 Qt 后端开发者。压缩包共 172 个文件体积紧凑仅 1.31MB涵盖 h 头文件、dll 动态库、lib 导入库、cmake 配置模块与 pc 文件等其中库文件与配置模块覆盖开发期链接、运行期加载及 find_package 接入所需可帮助用户完成 CMake 对接与编译环境校验包内按组件划分的目录结构较为清晰配合少量 exe 工具与示例组件便于按需查阅和二次开发。Cutelyst 作为高性能 C Web 框架配合 Grantlee 服务端模板渲染能够在 Qt 生态中实现 MVC 分层开发使页面逻辑与业务逻辑分离。目前已有 276 人学习下载适合具备 Qt 与 C 基础、希望基于 Cutelyst 搭建动态页面的后端开发者。1. 从“Win10 上给 Cutelyst 加 Grantlee 视图”说起一篇能跑通的编译笔记“win10 Qt5.15.2 编译带有Grantlee视图的Cutelyst动态库”这行字经常出现在 Qt 服务端项目的起步阶段。Cutelyst 是 C 的 Web 框架路由和控制器风格接近 DjangoGrantlee 是它的模板引擎负责把数据渲染成 HTML。在 win10 上用 Qt 5.15.2 把带 Grantlee 视图的 Cutelyst 编译成动态库真正麻烦的地方不在 CMake 本身而在三处CMake 能不能找到 Grantlee 的安装目录MSVC 链接时会不会混入 Debug/MinGW 的库Cutelyst 运行期能不能把 Grantlee 视图插件加载出来。这篇按这三个问题往下拆新手照着命令能编出 DLL熟手可以直接跳到第 5 章对照踩坑。2. 先理清三角关系Qt 5.15.2、Grantlee 与 Cutelyst 各自管哪一段2.1 Grantlee 在 Cutelyst 里的角色它不是“可选组件”而是视图层的支柱Cutelyst 的分层和 Django 很像Controller 收到请求、处理业务逻辑最终把数据塞进 Context剩下的事交给“视图插件”去渲染。Cutelyst 核心本身并不直接处理 HTML 模板它只提供一套视图插件的加载机制。常见的视图插件有两个一个是 QtView做最简单的字符串替换另一个就是 Grantlee提供 Django 风格的{{ variable }}、{% if %}、extends、过滤器这类完整模板语义。如果你只编 Cutelyst 核心库而不开 Grantlee 插件框架照样能跑但所有页面都只能用 QtView 的底层拼接方式渲染真实项目里约等于没有视图层。所以“带 Grantlee 视图的 Cutelyst 动态库”这句话字面上的意思是“Cutelyst 核心库 Cutelyst::Grantlee 视图插件”这俩是两套产物。我们要做的是一件事让 Grantlee 被 Cutelyst 的 CMake 找见再把视图插件编译进安装目录。这里有一个新手最容易误解的细节Cutelyst 的 Grantlee 插件是动态加载的插件 DLL不是静态编进核心库的。也就是说编译完你会看到主库和插件库两个文件部署时俩都得带上。插件动态加载的好处是运行时可以换视图引擎代价就是后面第 5 章要讲的插件目录和环境变量问题。2.2 为什么用 MSVC 而不是 MinGW动态库的 ABI 与插件兼容性Windows 上的 DLL 没有 Linux 那种“换个编译器也能凑合用”的宽松环境。MSVC 和 MinGW 的 C 头文件、标准库实现、异常处理机制都不一样动态库的导出符号只有在 C 接口级别才勉强互通。Cutelyst 把视图做成运行期插件主库、Grantlee 库、插件库三者只要有一个是 MinGW 编的剩下的全用 MSVC 编轻则加载失败重则崩溃。你之前在 Linux 上源码编译 postgresql、cpprestsdk 时那套“换编译器重新来过”的经验在 Windows 上会被放得更严重链接期可能不报错运行期才爆。Qt 5.15.2 官方在 Windows 上提供的是 msvc2019_64 和 mingw81_64 两套预编译包。为了少折腾我会直接用 VS2019 的 MSVC v142 工具链编所有东西Qt、Grantlee、Cutelyst 三者全走同一个生成器。如果你机器上只装了 VS2022也不是不能用但要给 CMake 指定 v142 工具集或者干脆去装“MSVC v142 - VS 2019 C x64/x86 build tools”这个独立组件让 Qt 5.15.2 的预编译二进制和你的编译器版本对齐。2.3 版本组合Win10 下我用的那套稳定组合组件推荐选择理由Qt5.15.2 msvc2019_64官方预编译、LTSCMake 配置信息完整CMake3.16 以上支持-S/-B和 VS 生成器旧版处理分号路径列表容易出错Visual Studio2019 v16.xMSVC v142与 Qt 5.15.2 官方二进制一致Grantlee较新的 5.2/5.3 发行版安装后会自带 GrantleeConfig.cmake方便 Cutelyst 查找Cutelyst当前发行版即可插件开关名以实际源码里的 CMakeLists 为准不要为了“追新”去选 Qt 6 或 VS2022 的默认工具集除非你已经做好给 Cutelyst 和 Grantlee 各打一套补丁的准备。这个组合不是性能最优但它是 Windows 上踩坑最少、搜索结果最多的一条路。3. 编译 Grantleewin10 上用 Qt 5.15.2 从源码构建与安装3.1 准备源码和目录把源码、构建、安装三个目录分开我一般会在D:/deps下建四块grantlee-src放源码grantlee-build放 CMake 缓存和中间文件cutelyst-src、cutelyst-build同理安装目录直接用D:/deps/grantlee和D:/deps/cutelyst。源码和构建目录分开是 CMake 的常规做法但安装目录单独拎出来还有一个实际好处Cutelyst 找 Grantlee 时用的是安装目录不是 build 目录避免 find_package 搜到 CMakeCache 还在的半成品。Grantlee 源码可以直接从官方发布页下载源码包解压也可以 git clone 到本地后切到 tag。如果你是从压缩包解的解压完确认顶层目录有 CMakeLists.txt。不要图省事把源码目录当构建目录用后面 Cutelyst 找不到 Grantlee 的 Config 文件时你连“是没装还是没找对地方”都分不清。3.2 配置 CMake关键参数与一次成功的命令# 在 PowerShell 中执行路径按你的实际情况改 cmake -S D:/deps/grantlee-src -B D:/deps/grantlee-build -G Visual Studio 16 2019 -A x64 -DCMAKE_PREFIX_PATHD:/Qt/5.15.2/msvc2019_64 -DCMAKE_INSTALL_PREFIXD:/deps/grantlee -DBUILD_SHARED_LIBSON -DBUILD_TESTINGOFF这里的参数拆开看-G Visual Studio 16 2019 -A x64生成 64 位 VS2019 工程。-A x64必须和 Qt 的 msvc2019_64 套件位数一致漏了它会默认编 Win32后面几百个链接错误等着你。-DCMAKE_PREFIX_PATH指向 Qt 安装目录的根。Grantlee 的 CMakeLists 里会find_package(Qt5...)CMake 会在这个路径下的lib/cmake里找对应的 Qt5 模块。直接指到根目录最稳不需要精确到lib/cmake。-DCMAKE_INSTALL_PREFIX决定生成的头文件和库最终落到哪里。这里定成D:/deps/grantlee后续 Cutelyst 配置时再把它加进 CMAKE_PREFIX_PATH。-DBUILD_SHARED_LIBSON编动态库生成 DLL 和导入库 .lib。如果设成 OFF 会产出静态库Cutelyst 插件动态加载时会很被动。-DBUILD_TESTINGOFF关掉测试省得拖 Catch2 之类的测试框架进来。如果这个版本的 Grantlee 不认这个选项删掉它再配一次不影响结果。配置成功的标志是最后出现Generating done以及Configuring done。如果卡在找不到 Qt5先检查CMAKE_PREFIX_PATH是否指向 Qt 根目录而不是D:/Qt/5.15.2/msvc2019_64/bin这种子目录。3.3 编译与安装Release 与 install 的正确姿势cmake --build D:/deps/grantlee-build --config Release --parallel 8 cmake --install D:/deps/grantlee-build --config Release--config Release在多配置生成器下必须显式写。VS 生成器默认会编 Debug而 Grantlee 后续要被 Cutelyst 以 Release 方式链接MSVC 的 Debug 运行库和 Release 运行库不能混混了轻则启动告警重则运行期崩溃。我编 Qt 周边库的习惯是只出 ReleaseDebug 留给真正需要断点跟 Grantlee 源码的时候再说。--parallel 8是并行度不是越快越好。如果你机器是 8 核直接写--parallel 8没问题如果是机械硬盘并行度太高反而会让磁盘 IO 成为瓶颈。一般 4 到 8 都行。装完后顺手看一眼产物结构Get-ChildItem D:/deps/grantlee -Recurse -Include *.dll,*.lib | Select-Object FullName你会看到.lib和.dll分处不同目录。.lib是链接期用的导入库Cutelyst 编译时靠它确认 Grantlee 的导出符号.dll是运行期用的真正部署时程序需要的是它。这个“编译期找 .lib、运行期找 .dll”的区分和你之前用 MSVC 编 ffmpeg libx265 时遇到的情况一模一样只要把这两个文件的用途记清楚后面排查会快很多。4. 编译 Cutelyst 动态库把 Grantlee 视图插件显式打开4.1 先找出与 GRANTLEE 相关的 CMake 开关Cutelyst 的插件在源码的plugins目录下主 CMakeLists 会用 option 控制每个子目录是否参与构建。版本不同开关名不完全一样。我见过BUILD_GRANTLEE_PLUGIN也见过直接叫BUILD_GRANTLEE的。不要凭记忆硬填先看代码# 在 Cutelyst 源码根目录搜 GRANTLEE 相关选项 Select-String -Path D:/deps/cutelyst-src/CMakeLists.txt -Pattern GRANTLEE # 顺便看一眼插件目录里有哪些视图插件 Get-ChildItem D:/deps/cutelyst-src/plugins -Directory | Select-Object Name这两个命令的输出会直接告诉你当前这份源码里Grantlee 插件的开关是什么、目录叫什么。有的发行版还会提供BUILD_ALL_PLUGINS这种聚合开关开了它再单独关不需要的插件但没必要为了省事闭着眼开全部Cache、Session 等插件的依赖比你想的多先只开 QtView 和 Grantlee 两个视图插件编译负担最小。4.2 配置命令把 Qt 和 Grantlee 同时递给 CMAKE_PREFIX_PATHcmake -S D:/deps/cutelyst-src -B D:/deps/cutelyst-build -G Visual Studio 16 2019 -A x64 -DCMAKE_PREFIX_PATHD:/Qt/5.15.2/msvc2019_64;D:/deps/grantlee -DCMAKE_INSTALL_PREFIXD:/deps/cutelyst -DBUILD_GRANTLEE_PLUGINON -DBUILD_QTVIEW_PLUGINON -DBUILD_TESTINGOFF这次CMAKE_PREFIX_PATH传的是两个目录中间用分号隔开所以整个值必须用双引号包住。CMake 会依次到这两个前缀目录下的lib/cmake去找Qt5Config.cmake和GrantleeConfig.cmake。分号在 PowerShell 里本身是语句分隔符不加引号的话命令行会被拆断这是 Windows 上配 CMake 最容易翻车的地方之一。BUILD_GRANTLEE_PLUGINON是关键开关它让 Cutelyst 的 CMake 去plugins/grantlee目录编译视图插件。BUILD_QTVIEW_PLUGINON是建议开的QtView 插件编译成本很低而且在排查“Grantlee 模板没生效”时可以临时切回 QtView 做对照确认问题在视图层还是控制器层。如果你之前已经跑过一次没开 Grantlee 的配置CMakeCache.txt 里会残留旧选项。改了-D参数后重配有些项目很老实有些则会因为缓存里的依赖路径没刷新而继续用旧配置。遇到这种玄学问题先删缓存再配Remove-Item D:/deps/cutelyst-build/CMakeCache.txt cmake -S D:/deps/cutelyst-src -B D:/deps/cutelyst-build -G Visual Studio 16 2019 -A x64 -DCMAKE_PREFIX_PATHD:/Qt/5.15.2/msvc2019_64;D:/deps/grantlee -DCMAKE_INSTALL_PREFIXD:/deps/cutelyst -DBUILD_GRANTLEE_PLUGINON -DBUILD_QTVIEW_PLUGINON -DBUILD_TESTINGOFF配置阶段能看到Found Grantlee之类的输出就算第一步过了。4.3 编译与安装确认主库和 Grantlee 插件 DLL 都出现cmake --build D:/deps/cutelyst-build --config Release --parallel 8 cmake --install D:/deps/cutelyst-build --config Release编译时间取决于机器Cutelyst 本体加两个插件一般几分钟内结束。如果中途报错不要直接重跑往上翻第一个error C或者error LNK通常是某个依赖的 include 路径没传进去而不是代码本身的问题。装完检查 DLLGet-ChildItem D:/deps/cutelyst -Recurse -Filter *Cutelyst*.dll | Select-Object FullName你会看到类似两个产物Qt5Cutelyst.dll是 Cutelyst 核心库Qt5CutelystGrantlee.dll是 Grantlee 视图插件。前者是框架本体后者才是“带 Grantlee 视图”的具体体现。插件 DLL 在安装后可能在bin下也可能在lib/plugins或plugins目录下以你机器上实际 install 布局为准后面部署时要用这个路径。5. 避坑清单这 5 个坑占了 Grantlee 视图编译失败的一大半5.1 find_package(Grantlee) 失败缓存里总有一个路径在骗你现象配置 Cutelyst 时CMake 报Could NOT find GrantleeGrantlee_DIR显示为NOTFOUND。原因DCMAKE_PREFIX_PATH指向了 Grantlee 的源码目录或 build 目录而不是安装目录。Grantlee 的GrantleeConfig.cmake只会在cmake --install之后生成源码目录和 build 目录里虽然有部分 cmake 文件但缺少完整的 config 信息。解决先确认 config 文件真的在安装目录里Get-ChildItem D:/deps/grantlee -Recurse -Filter GrantleeConfig.cmake | Select-Object FullName找到后把它的父目录绝对路径记下来用-DGrantlee_DIR...显式指定或者把 CMAKE_PREFIX_PATH 里的路径换成安装目录。改完记得删 CMakeCache.txt 再重配否则 CMake 会拿旧变量一直失败下去。5.2 编译期 C1083找不到 grantlee_core.h现象MSVC 报C1083: Cannot open include file: grantlee_core.h。原因Grantlee 安装后头文件不一定在include根目录下可能在include/Grantlee子目录里。Cutelyst 的 CMake 如果没能正确拿到 Grantlee 的 include 目录就会把头文件路径传丢。解决不要为了省事手动把include/Grantlee里的头文件拷到include根目录那样短期能过编译后续 Grantlee 升级时你会后悔。正确做法是看 CMake 有没有把 Grantlee 的导出目标带进来比如Grantlee::Core。在cutelyst-src/CMakeLists.txt里查 target_link_libraries 对 Grantlee 的引用确保它用的是目标名而不是裸路径。5.3 运行期弹窗找不到 Qt5CutelystGrantlee.dll 或 grantlee_core.dll现象sample 程序编译通过双击 exe 直接报“找不到 Qt5CutelystGrantlee.dll”或“找不到 grantlee_core.dll”。原因链接期 CMake 能找到.lib但运行期 Windows 不认 CMake 的路径。exe 启动时只会从自身目录、系统目录和 PATH 中找 DLL。Grantlee 的 bin 目录和 Cutelyst 的安装目录没有进入 PATH。解决把两个 bin 目录加进当前进程的 PATH或者直接把 DLL 拷到 exe 旁边$env:Path D:/deps/cutelyst/bin;D:/deps/grantlee/bin;$env:Path这个场景跟你编 OpenCV、QScintilla 时一模一样装好了库也得自己处理 DLL 搜索路径Windows 不会自动帮你按 CMake 安装前缀去找 DLL。5.4 视图插件加载失败应用起来了但 Grantlee 视图始终不生效现象exe 能启动访问页面时返回的是错误日志里出现no view或Grantlee view not loaded。原因Cutelyst 的视图插件是运行期动态加载的它不会自动去 exe 目录外扫描。插件安装目录和 exe 不在同一目录时Cutelyst 会找不到Qt5CutelystGrantlee.dll。有的版本还需要环境变量CUTELYST_PLUGIN_DIR来指定插件目录。解决设置环境变量指向插件实际安装目录$env:CUTELYST_PLUGIN_DIR D:/deps/cutelyst/plugins路径以你 install 后实际生成为准。如果你用了 Debug 版本的 Cutelyst插件 DLL 会叫Qt5CutelystGrantleed.dll而 Release 版的 exe 只会找不带d的那个这种情况也会静默失败。5.5 满屏 unresolved external symbol工具链混了链接才翻车现象链接时报几百个 unresolved external symbol状态码 LNK2019 / LNK2001。原因Grantlee 或某个依赖是用 MinGW 编的Cutelyst 却用 MSVC 链接或者 Qt 选的是 mingw81_64 套件CMake 生成器却是 VS2019。C 名称修饰规则不同链接器当然找不到符号。解决统一工具链。Qt 安装时选 msvc2019_64CMake 生成器用 VS2019Grantlee 和 Cutelyst 都用同一套方式编。改完之后把三个 build 目录全部删掉重来不要只删其中一个否则 CMakeCache 里残留的编译器路径会让链接器继续串味。这是我踩过最狠的坑一夜时间就耗在这上面。6. 验证与部署把带 Grantlee 的 Cutelyst 动态库真正跑起来6.1 最小验证找一个 Grantlee 示例编出来跑Cutelyst 源码的 examples 目录下通常会带 Grantlee 视图示例先找到它再单独配置# 找到示例目录路径以你源码实际结构为准 Get-ChildItem D:/deps/cutelyst-src/examples -Recurse -Directory -Filter *grantlee* | Select-Object FullName # 配置并编译 cmake -S D:/deps/cutelyst-src/examples/GrantleeExample -B D:/deps/cutelyst-example-build -G Visual Studio 16 2019 -A x64 -DCMAKE_PREFIX_PATHD:/Qt/5.15.2/msvc2019_64;D:/deps/cutelyst;D:/deps/grantlee cmake --build D:/deps/cutelyst-example-build --config Release如果 examples 里没有现成的 Grantlee 样例随便建一个 Cutelyst 应用然后在视图配置里指定grantlee作为 view 类型也行。验证的标准只有一个应用启动日志里没有“view not found”之类的报错访问页面能输出模板变量。6.2 部署清单Qt、Grantlee、Cutelyst 三层缺一不可组件来源作用Qt5Core.dll、Qt5Network.dll 等windeployqt生成Qt 运行时依赖Qt5Cutelyst.dllCutelyst 安装目录Cutelyst 核心库Qt5CutelystGrantlee.dllCutelyst 插件目录Grantlee 视图插件grantlee_core.dllGrantlee 安装目录Grantlee 模板引擎运行时模板文件目录你自己项目里的 html 模板Grantlee 渲染时的模板源windeployqt 能处理 Qt 自身的运行时但不会管 Grantlee 和 Cutelyst 的 DLL这俩需要手动补。模板目录路径最好在代码里显式传给 Grantlee 视图不要让 Cutelyst 去猜当前工作目录。6.3 一个值得养成的习惯换依赖版本前先把三个 build 目录删干净CMakeCache.txt 是真正的黑匣子。它会把“上次配置成功”的路径记得死死的哪怕你改了-D参数它也可能按缓存里的旧依赖继续找。我现在每换一个 Qt 或 Grantlee 版本就把grantlee-build、cutelyst-build、示例的 build 目录一次性删掉宁可重新配置多花十分钟也不跟缓存猜谜。这个习惯帮我省掉了大量“改了配置却还在用旧变量”的诡异时间。希望帮到你。本文还有配套的精品资源点击获取