Qt QJson 编译避坑指南:从 CMake 配置到链接报错全解析
1. 为什么还要折腾 QJson 编译这件事QJson 是一个基于 Qt 的轻量级 JSON 解析库它的定位很明确把 JSON 数据映射成 QVariant 对象或者反过来把 QVariant 序列化成 JSON 文本。相比 Qt 自带的 QJsonDocumentQJson 在易用性和类型转换的灵活性上有自己的优势尤其在老项目中经常能见到它的身影。但问题也恰恰出在这里——QJson 的代码库年代久远最后一次活跃更新已经是很多年前的事了用现代编译器和新版 Qt 去编译它几乎必然会踩坑。我自己最近在一个维护性的项目里需要重新编译 QJson前后折腾了大半天遇到了从 CMake 配置报错、头文件路径找不到、到链接阶段符号缺失等一系列问题。网上能搜到的教程要么太老要么语焉不详很多关键步骤被一笔带过。所以这篇文章的目的很直接把编译 QJson 的完整流程拆开揉碎把每一个可能踩的坑提前标出来让你能一次性编译通过。这篇文章适合几类人一是需要在项目中集成 QJson 但不想用包管理器直接装的开发者二是想学习老式 CMake 项目如何适配新环境的同学三是单纯被 QJson 编译报错折磨过、想搞清楚背后原因的人。不管你是刚接触 Qt 的新手还是用了多年 Qt 的老手下面的内容应该都能帮你省下不少时间。2. 编译前的环境准备与方案选型2.1 编译器与 Qt 版本的选择逻辑QJson 的源码对 C 标准的要求并不高基本上 C98 就能跑但这不意味着你可以随便选编译器版本。我实测下来用 GCC 9 以上或者 MSVC 2019 以上问题都不大真正需要注意的是 Qt 版本。QJson 最初是为 Qt 4 设计的后来有人做了 Qt 5 的适配。如果你用的是 Qt 5.15 或 Qt 6.x直接拿原始源码编译大概率会报错因为 Qt 6 移除了一些 Qt 5 中已经标记为废弃的 API。我的建议是如果你在用 Qt 5.x优先选 Qt 5.12 到 Qt 5.15 这个区间兼容性最好。如果你在用 Qt 6.x需要额外打一些补丁后面我会具体说改哪里。如果你还在用 Qt 4那基本可以原样编译但 Qt 4 本身已经很少见了。选 Qt 版本的时候还有一个容易被忽略的点qmake 和 CMake 的版本要匹配。QJson 同时提供了 .pro 文件和 CMakeLists.txt两条路都能走但踩的坑不一样。我个人的建议是走 CMake因为 CMake 的错误信息更清晰而且后续集成到现代项目里更方便。2.2 源码获取与目录结构确认QJson 的源码可以从多个渠道获取但不同渠道的代码质量参差不齐。我建议直接拿官方仓库的源码不要用来路不明的 fork 版本因为有些 fork 改了一半反而引入了新的问题。拿到源码后先别急着编译花两分钟看一下目录结构。典型的 QJson 源码目录长这样qjson/ ├── CMakeLists.txt ├── qjson.pro ├── src/ │ ├── CMakeLists.txt │ ├── qjson_export.h │ ├── qjsonobject.cpp │ ├── qjsonobject.h │ ├── qjsonparser.cpp │ ├── qjsonparser.h │ ├── qjsonserializer.cpp │ ├── qjsonserializer.h │ ├── qjsonvalue.cpp │ └── qjsonvalue.h └── tests/关键文件是src/目录下的那几个 .cpp 和 .h以及顶层的 CMakeLists.txt。如果你发现源码里缺少qjson_export.h那说明你拿到的版本不完整需要重新下载。注意有些打包版本会把qjson_export.h放在别的目录编译时会报找不到头文件。遇到这种情况手动把这个文件复制到src/目录下即可。2.3 构建工具链的版本要求CMake 的最低版本要求是 3.5但我建议用 3.16 以上因为新版本 CMake 对 Qt 的自动检测支持更好。如果你用的是 CMake 3.20 以上还可以用qt_standard_project_setup()这类新命令简化配置不过 QJson 的老 CMakeLists.txt 用不上这些。编译器方面GCC 建议 9.0 以上Clang 建议 10.0 以上MSVC 建议 2019 以上。低于这些版本不是不能编译而是可能会遇到一些奇怪的模板推导错误排查起来很费时间。还有一个容易忽略的点确保你的 Qt 开发环境是完整的。有些同学只装了 Qt 的运行时库没装开发头文件和 CMake 配置文件编译时就会报Qt5Config.cmake找不到。检查方法很简单在命令行里执行qmake --version如果能正常输出版本信息说明 Qt 环境基本没问题。如果报命令找不到那就需要先把 Qt 的 bin 目录加到 PATH 里。3. 核心编译流程与关键配置拆解3.1 CMake 配置阶段的参数详解进入源码目录后第一步是创建构建目录。我强烈建议不要在源码目录里直接构建而是单独建一个 build 目录这样清理起来方便也不会污染源码。mkdir build cd build接下来是 CMake 配置。最基本的命令是cmake .. -DCMAKE_PREFIX_PATH/path/to/qt这里的CMAKE_PREFIX_PATH指向你的 Qt 安装路径。比如在 Linux 上可能是/opt/Qt/5.15.2/gcc_64在 Windows 上可能是C:/Qt/5.15.2/msvc2019_64。这个参数非常关键如果不指定CMake 可能找不到 Qt或者找到错误的 Qt 版本。除了CMAKE_PREFIX_PATH还有几个参数值得关注参数作用建议值CMAKE_BUILD_TYPE构建类型Release 或 DebugCMAKE_INSTALL_PREFIX安装路径自定义默认是 /usr/localBUILD_SHARED_LIBS是否构建动态库ON 或 OFFQJSON_BUILD_TESTS是否构建测试OFF除非你要跑测试我一般会这样配置cmake .. \ -DCMAKE_PREFIX_PATH/opt/Qt/5.15.2/gcc_64 \ -DCMAKE_BUILD_TYPERelease \ -DCMAKE_INSTALL_PREFIX/usr/local \ -DBUILD_SHARED_LIBSON \ -DQJSON_BUILD_TESTSOFF这样配置的好处是构建类型明确安装路径可控而且不会浪费时间编译测试代码。3.2 源码中需要手动修改的几处地方如果你用的是 Qt 5.15 或 Qt 6.x直接编译大概率会报错。根据我的经验主要有以下几个问题需要手动修复第一个问题QString::split的返回值处理在老版本 Qt 中QString::split返回的是QStringList可以直接用下标访问。但在新版本中某些重载的返回值类型变了导致编译报错。修复方法是显式指定返回类型// 修改前 QStringList parts str.split(,); // 修改后 const QStringList parts str.split(,);第二个问题QRegExp的废弃QJson 的解析器里用到了QRegExp这个类在 Qt 5 中已经被标记为废弃在 Qt 6 中直接被移除了。如果你用的是 Qt 6需要把QRegExp替换成QRegularExpression。这个改动比较大因为两者的 API 不完全兼容。// Qt 5 及以前 QRegExp re(^\\s*); // Qt 6 QRegularExpression re(^\\s*);第三个问题qjson_export.h的生成QJson 使用了一个qjson_export.h文件来管理符号导出。这个文件在源码里可能是一个模板需要 CMake 生成。如果你发现编译时报qjson_export.h找不到检查一下 CMakeLists.txt 里有没有generate_export_header相关的配置。实操心得修改源码之前先复制一份原始文件做备份。我吃过亏改到一半发现改错了想回退都回不去。3.3 编译与安装的完整命令序列配置完成后编译和安装就相对简单了# 编译-j 后面的数字根据你的 CPU 核心数调整 cmake --build . -j8 # 安装 cmake --install .如果你用的是 Makefile 生成器也可以直接用 makemake -j8 make install编译过程中如果报错先看错误信息的第一行那通常是最根本的原因。后面的错误往往是连锁反应不用一个个去解决。安装完成后你会在CMAKE_INSTALL_PREFIX指定的路径下看到include/和lib/目录里面分别是头文件和库文件。集成到项目里的时候把这两个路径加到编译器的搜索路径中即可。4. 常见报错与排查技巧实录4.1 CMake 配置阶段的典型报错报错一Could not find a package configuration file provided by Qt5这个报错说明 CMake 找不到 Qt5 的配置文件。原因通常是CMAKE_PREFIX_PATH没设置对或者 Qt 安装不完整。解决方法是确认 Qt 安装路径下确实有lib/cmake/Qt5/Qt5Config.cmake这个文件然后重新设置CMAKE_PREFIX_PATH。报错二CMake Error: The current CMakeCache.txt directory is different这个报错通常是因为你在不同的目录之间移动了构建目录或者之前用不同的路径配置过。解决办法很简单删掉 build 目录重新来一遍rm -rf build mkdir build cd build报错三No CMAKE_CXX_COMPILER could be found这说明 CMake 找不到 C 编译器。检查一下你的编译器是否安装以及是否在 PATH 里。Linux 上可以用which g确认Windows 上需要确保 Visual Studio 的编译工具链已经安装。4.2 编译阶段的典型报错报错一qjson_export.h: No such file or directory这个前面提过是导出头文件没有生成。检查 CMakeLists.txt 里是否有include(GenerateExportHeader)和generate_export_header(qjson)这两行。如果没有手动加上。报错二QRegExp: No such file or directory这是 Qt 6 移除了 QRegExp 导致的。如果你不想大改代码最简单的办法是降级到 Qt 5。如果必须用 Qt 6那就得把 QRegExp 替换成 QRegularExpression涉及的文件主要是qjsonparser.cpp。报错三undefined reference to QJson::Parser::parse这是链接阶段的报错说明库文件没有正确链接。检查一下你的项目里是否链接了 QJson 的库以及库文件的路径是否正确。在 CMake 中应该有这样的配置target_link_libraries(your_target PRIVATE qjson)4.3 链接与运行阶段的典型报错报错一error while loading shared libraries: libqjson.so.0: cannot open shared object file这个报错说明运行时找不到 QJson 的动态库。解决办法是把 QJson 的 lib 目录加到LD_LIBRARY_PATH里或者把库文件复制到系统库目录export LD_LIBRARY_PATH/usr/local/lib:$LD_LIBRARY_PATH报错二symbol lookup error: undefined symbol这个报错通常是因为库的版本不匹配比如你编译时用的是 Qt 5.15运行时却链接到了 Qt 5.12 的库。解决办法是确保编译和运行时用的是同一套 Qt。报错三程序崩溃在QJson::Parser::parse里这个比较隐蔽通常是因为传入的 JSON 字符串格式不对或者编码有问题。QJson 对 UTF-8 的支持比较好但如果你的字符串是 GBK 编码的就可能出问题。解决办法是确保传入的字符串是 UTF-8 编码。4.4 常见问题速查表问题现象可能原因解决方法CMake 找不到 Qt5CMAKE_PREFIX_PATH 未设置指定正确的 Qt 安装路径qjson_export.h 缺失CMake 未生成导出头检查 generate_export_header 配置QRegExp 报错Qt 6 移除了 QRegExp降级 Qt 5 或替换为 QRegularExpression链接时报符号缺失库未正确链接检查 target_link_libraries运行时找不到动态库LD_LIBRARY_PATH 未设置添加库路径或复制库文件解析时崩溃字符串编码问题确保传入 UTF-8 编码的字符串避坑技巧编译之前先把 Qt 版本、CMake 版本、编译器版本记录下来。出问题的时候这些信息能帮你快速定位是不是版本兼容性问题。5. 集成到实际项目中的注意事项5.1 静态库与动态库的选择QJson 默认构建的是动态库但你可以通过BUILD_SHARED_LIBSOFF来构建静态库。两者各有优劣动态库的优点是体积小多个程序可以共享同一份库文件缺点是部署时需要带上 .so 或 .dll 文件而且可能遇到版本冲突。静态库的优点是部署简单直接编进可执行文件里缺点是体积大而且如果多个库都依赖 QJson可能会有符号冲突。我个人的建议是如果是内部工具用动态库方便调试如果是要分发给别人的产品用静态库省事。5.2 头文件包含路径的配置QJson 的头文件安装后通常在include/qjson/目录下。在项目里包含头文件时有两种写法// 写法一带目录前缀 #include qjson/qjsonobject.h // 写法二不带前缀但需要在 CMake 里加 include 路径 #include qjsonobject.h写法二需要在 CMake 里加target_include_directories(your_target PRIVATE /usr/local/include/qjson)我倾向于写法一因为路径更明确不容易和其他库的头文件冲突。5.3 与 Qt 自带 JSON 模块的共存问题Qt 5 开始自带了 QJsonDocument、QJsonObject 等类这些类和 QJson 库的类名很像但完全不是一回事。如果你在同一个项目里同时用了两者很容易搞混。我的建议是如果项目里已经用了 Qt 自带的 JSON 模块就尽量不要引入 QJson 了除非有明确的理由。如果必须同时用在包含头文件时一定要写全路径避免歧义。实操心得我遇到过一个问题项目里同时包含了 QJson 和 Qt 的 JSON 头文件结果编译器报了一堆重定义错误。后来发现是因为两个库都有 QJsonObject 这个类名。解决办法是用命名空间或者改包含顺序但最根本的办法还是避免同时用两个功能重叠的库。5.4 跨平台编译的差异处理QJson 在 Linux、Windows、macOS 上的编译流程基本一致但有几个细节需要注意Linux 上主要是动态库路径问题前面已经说过。Windows 上需要注意的是MSVC 编译出来的库和 MinGW 编译出来的库不兼容如果你的项目用的是 MinGW那 QJson 也必须用 MinGW 编译。macOS 上需要注意的是默认可能编译成 .dylib如果你需要 .framework得额外配置。还有一个跨平台的坑是路径分隔符。QJson 内部处理文件路径的地方不多但如果你在项目里用到了记得用/而不是\因为/在所有平台上都能用。6. 一些个人体会和后续扩展思路编译 QJson 这件事说难不难说简单也不简单。难点不在于代码本身有多复杂而在于它是一个老项目和新环境的适配需要一些手动调整。我自己的体会是遇到报错不要慌先看错误信息的第一行然后对照这篇文章里的排查表大部分问题都能解决。如果你编译成功了后续还可以做几件事一是把编译好的库打包成 Conan 或 vcpkg 的包方便在其他项目里引用二是给 QJson 写一个 CMake 的 config 文件这样其他项目可以用find_package(QJson)来引用三是如果你有精力可以把 QJson 的代码现代化一下比如把 QRegExp 全部替换掉让它原生支持 Qt 6。最后分享一个小技巧编译之前先跑一遍cmake .. --debug-output把详细的配置信息输出到日志里。出问题的时候翻日志比瞎猜快得多。这个习惯我在编译各种老项目的时候都用得上屡试不爽。

相关新闻

vSphere 8.0 安装卡在配置管理网络?ESXi 8.0 U3 驱动定制与网络激活实战指南

vSphere 8.0 安装卡在配置管理网络?ESXi 8.0 U3 驱动定制与网络激活实战指南

简介:本资源是面向Windows/Linux系统管理员及虚拟化工程师的VMware vSphere 8.0实战指南,聚焦ESXi 8.0安装、初始配置、性能优化与故障排查全流程,解决数据中心虚拟化环境搭建中的核心实操难题。内容覆盖硬件兼容性校验、多种安装方式&#x…

2026/10/13 23:43:35 阅读更多 →
Docker深度学习环境构建:CUDA隔离、镜像治理与GPU容器实战

Docker深度学习环境构建:CUDA隔离、镜像治理与GPU容器实战

1. 为什么我宁愿花三小时配Docker环境,也不直接pip install一切 “用Docker跑深度学习?太重了吧,我conda activate一下不就完事了?”——这是我在某次技术分享会上听到最多的一句反问。当时台下坐着二十多位正在调试YOLOv8模型的…

2026/10/13 23:43:35 阅读更多 →
OpenMAIC:开源多智能体平台,让课堂AI从工具孤岛走向协同编排

OpenMAIC:开源多智能体平台,让课堂AI从工具孤岛走向协同编排

做教育信息化这几年,我越来越觉得课堂上的AI工具不是太少,而是太散。老师手里捏着两三个对话框,学生那边又用一个答题器,学情数据散落在不同后台里,根本没法串成一条线。所以我动手做了OpenMAIC——一个开源的、面向交…

2026/10/13 23:42:35 阅读更多 →

最新新闻

微信小程序原生课程表开发:周视图与本地存储实战

微信小程序原生课程表开发:周视图与本地存储实战

简介:这份资源是面向微信小程序初学者与前端练手者的原生课程表项目源码,基于微信小程序原生框架实现,可帮助读者快速理解并搭建一个查看、管理每周课程安排的小工具,适合学生、教师及想熟悉小程序开发流程的开发者参考。压缩包为…

2026/10/14 0:32:51 阅读更多 →
C++ std::string 从入门到精通:C++20新特性与性能优化实战

C++ std::string 从入门到精通:C++20新特性与性能优化实战

1. 从C风格字符数组到string:为什么我们不再用char*刚入行那会儿,我接手过一个日志解析模块,满屏都是char buf[1024]和strcpy、strcat。有一次线上崩溃,查了两天才发现是某条日志超长导致缓冲区溢出,把相邻内存踩了。那…

2026/10/14 0:32:51 阅读更多 →
Python turtle绘图从入门到进阶:十几行代码玩转几何分形与随机图形

Python turtle绘图从入门到进阶:十几行代码玩转几何分形与随机图形

别人问我Python入门学什么图形库好,我基本都会先劝一句:别急着上那些花哨的可视化框架,先把turtle玩明白。这个库是Python自带的标准库,装好Python就能用,不需要额外依赖,打开IDLE就能敲出第一张图。虽然它…

2026/10/14 0:32:51 阅读更多 →
AI论文写作工具:查重与润色的高效解决方案

AI论文写作工具:查重与润色的高效解决方案

1. 论文写作的痛点与AI工具的价值写论文最头疼的莫过于查重和润色了。记得我研究生时期,为了把重复率从30%降到10%以下,整整熬了三个通宵手动改写。现在AI工具已经能帮我们解决这些问题,而且效果远超人工操作。目前主流的AI论文工具主要解决三…

2026/10/14 0:32:51 阅读更多 →
Higgsfield AI:短视频爆款的确定性生成引擎

Higgsfield AI:短视频爆款的确定性生成引擎

1. 这不是“AI一键生成”,而是用Higgsfield AI做爆款视频的实战路径最近在几个内容创作群和剪辑师私聊里,反复被问到一个问题:“那个叫Higgsfield AI的工具,真能做出播放量破百万的短视频?”说实话,第一次看…

2026/10/14 0:32:51 阅读更多 →
研发管理系统选型指南:敏捷协作与成本效益分析

研发管理系统选型指南:敏捷协作与成本效益分析

1. 研发管理系统选型困境与测评价值早上开周会时,技术总监又把茶杯重重砸在会议桌上——这已经是本月第三次因为任务进度不透明引发的争执。市场部抱怨需求响应慢,开发团队吐槽需求变更频繁,QA团队则苦于没有统一的测试用例管理平台。这种场景…

2026/10/14 0:31:51 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →