news 2026/10/13 9:04:55

旧版Telegram Desktop源码编译指南:Qt 5.3.1工具链配置与避坑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
旧版Telegram Desktop源码编译指南:Qt 5.3.1工具链配置与避坑

简介:这是一份针对Telegram桌面版在Windows环境下的编译实战笔记,重点面向有一定C++基础、想从源码自行构建该开源即时通讯软件的开发者,也适合需要了解Qt 5.3.1静态库编译流程的读者。作者基于Visual Studio 2013,梳理了所需依赖组件的准备过程,包括OpenSSL、LZMA、zlib、libexif以及Qt等;其中Qt虽未能完整编译,但主要核心库已经生成,并说明了与另一份半成品库合并的做法。文档详实记录了编译期间常见的头文件路径错误、语法兼容问题、静态库缺失等故障,逐一给出原因分析和可行的处理方式,比如调整附加包含目录、修改源码引用语句、手动编译OpenSSL来生成需要的库文件。同时,作者结合亲测经验,整理了完整的OpenSSL编译命令、Qt插件安装注意事项和排错顺序,能帮助后来者快速定位同类问题、减少尝试成本。资源以单个doc文件封装,压缩包大小约二十九KB,内容精炼但信息密度高。目前已吸引五百六十九人学习下载,适合作为二次开发或环境搭建的实用参考。

1. 从源码编译 Telegram Desktop:为什么卡在 Qt 5.3.1

从源码编译 Telegram Desktop 这件事,最大的门槛其实不在 Telegram 本身,而在它锁定的那一套旧工具链——Qt 5.3.1。如果你手上是这个版本的源码包,直接拿新版 Qt 去编,会在 qmake 阶段就被卡死,因为 Telegram 旧版大量依赖 Qt 5.3 时代的 QML API 和私有补丁。这份资源解决的就是这条完整链路:Qt 5.3.1 编译、QScintilla 第三方控件编译、Telegram 主程序构建,以及过程中所有能让你摔键盘的报错。适合两种人:一是想研究 Telegram 早期架构、需要复现旧版 UI 的从业者;二是手里有老工程、被 Qt 版本锁定折磨到想换电脑的维护者。新版本 Telegram 走的是 CMake 新流程,不在这篇范围内。

2. 编译前置环境:工具链、依赖清单与路径规划

2.1 为什么必须用 MSVC 2013:编译器与 Qt 包的匹配规则

Qt 5.3.1 官方 Windows 安装包只提供三套编译配置:msvc2013、msvc2012、mingw482。Telegram 旧版构建脚本里的 QMAKESPEC 写死为 win32-msvc2013,这意味着你大概率要装 Visual Studio 2013(VS12.0)。用 VS2015 或更新的版本打开这个工程,qmake 会直接报找不到匹配 mkspec,虽然可以手动往 Qt 的 mkspecs 目录塞新编译器配置,但后面 MOC、RCC 中间文件的兼容性会变成玄学,我不建议这么干。

这里有一个基础判断:Qt 二进制包和编译器是绑定的,MSVC 2013 编译出的 Qt 库,只能被 MSVC 2013 编译的工程链接。混用编译器是最常见的翻车源头,而且报错时机不定,有时候编译过了,运行起来才闪退。下表是几个常见组合的实际表现:

编译器组合结果
MSVC 2013 + Qt 5.3.1 (msvc2013)正常,Telegram 官方脚本按此验证
MinGW 4.8.2 + Qt 5.3.1 (mingw482)可编译,但 Telegram 旧版脚本未覆盖,第三方库需要全部重编
MSVC 2015+ + Qt 5.3.1 (msvc2013)qmake 识别不了,强行配置后链接期 LNK2038 频发
MSVC 2013 + Qt 5.6+Telegram 旧版 QML 代码大面积不兼容,私有补丁失效

我给的建议是:不要想着一套工具链通吃所有项目,这个资源是给旧版 Telegram 用的,你就老老实实把 VS2013 装好,它是整个编译链路里最省心的一环。

2.2 依赖清单与版本锁定:OpenSSL、zlib、libexif 各司其职

Telegram 的主程序编译不是只依赖 Qt,它还牵扯到几个第三方库。最常被忽略的是 QScintilla,它是 Telegram 旧版里文本输入组件用到的 Qt 封装控件,这个库的编译顺序错了,后面主程序 100% 报头文件找不到。资源包里已经按版本配好了这些依赖,但你需要知道每个库是干什么的,否则报错时只能干瞪眼:

依赖版本参考在 Telegram 里的作用编译不出来时的典型报错
OpenSSL1.0.1r加密通道,链接 libcrypto/libssl链接期 LNK2019,符号 _SSL_new 找不到
zlib1.2.8数据压缩,图片传输和缓存都要用头文件 zlib.h 找不到
libexif0.6.21读取图片 EXIF 拍摄参数不致命,但图片发送功能会异常
QScintilla2.8.x文本编辑控件封装C1083 找不到 qsciscintilla.h
Perl5.xQt configure 脚本依赖configure 直接报错退出

注意 QScintilla 的版本。2.8.x 是对应 Qt 5.3 时代的老版本,你要是图省事下了最新版 QScintilla,它内部用了 Qt 5.15 的 API,编译期会有一堆成员变量找不到的报错。资源包里带了一份,我建议直接用包里那份,别自己去官网下新的。

2.3 QTDIR/PATH/QMAKESPEC:环境变量一次配对

环境变量配错是所有编译问题的第一嫌疑。常见的做法是先把 VS2013 的编译环境拉起来,再设置 Qt 相关变量。在 VS2013 的 x86 命令行下逐行执行:

set QTDIR=C:\Qt\Qt5.3.1 set PATH=%QTDIR%\bin;C:\Python27;C:\jom;%PATH% set QMAKESPEC=win32-msvc2013

这段的作用:QTDIR 告诉所有构建脚本 Qt 装在哪,PATH 里把 qmake、Python 2.7、jom 都塞进去,QMAKESPEC 强制指定编译规范。Python 2.7 别漏,Telegram 旧版构建脚本里有一段代码生成步骤是靠 Python 跑的,少它会报Can't find Python。

这里有个血泪经验:如果你机器上装有 Anaconda 或新版 Python 3,一定要保证 PATH 里的 Python2.7 排在前面。Telegram 那段生成脚本用的是 Python 2 的 print 语法,一旦被 Python 3 接管,报错是 SyntaxError,你排查半小时都想不到是 Python 版本问题。

3. 源码目录与第三方库:先看清要吃下多少依赖

3.1 先从仓库拿到主源码与 ThirdParty

拿到 Telegram 旧版源码包后,先别急着编译,把目录结构过一遍,确认第三方库是齐全的。这个项目的第三方库不是用包管理器拉取的,而是直接以源码目录形式放在仓库里或资源包里。缺失任何一块,后续编译都会走到一半才报错,而且报错位置很迷惑。

我拿到源码时看到的结构大概是这样:

Telegram/ ├── SourceFiles/ # 主程序源码与构建入口 │ ├── telegram.pro # qmake 工程文件 │ ├── build.bat # Windows 构建入口脚本 │ ├── Debug/ # 中间产物目录 │ └── Release/ ├── Telegram/ # QML 界面资源 │ ├── Resources/ # 图标、翻译、主题文件 │ └── SourceFiles/ # QML 前端源码 ├── ThirdParty/ # 第三方依赖源码 │ ├── qscintilla/ # 文本编辑控件 │ ├── libexif/ # EXIF 信息读取 │ └── zlib/ # 压缩库 └── QtStatic/ # Qt 补丁与构建配置 └── patches/ # Telegram 对 Qt 的私有补丁

我一般会先核对三个关键目录:SourceFiles、ThirdParty、QtStatic。QtStatic 最容易被忽略,但它其实是 Telegram 对 Qt 的定制补丁集,作用是在 Qt 的 QPA 层加上 Telegram 需要的窗口行为。直接编译官方原版 Qt 也能过,但编译出来的 Telegram 运行起来窗口行为会异常,表现是窗口闪烁、失焦后无法恢复绘制。这不是你代码的问题,是补丁没打上。

3.2 目录树里有哪些关键路径:构建脚本怎么找东西

构建脚本对路径的假设非常死板。build.bat 内部会拼接相对路径去找 ThirdParty 里的库,你如果把 Telegram 源码目录改名或者挪到深层路径,脚本拼接出来的路径就会断掉。旧版脚本还有一层对盘符的硬编码,我拿到的这个版本里写的是D:\Telegram,如果你的工程放在 C 盘,需要改脚本或保持路径一致。

一个稳妥做法是把所有依赖放在同一层目录下,然后确保路径无空格。Visual Studio 对空格路径的支持一直有历史遗留问题,qmake 生成的 Makefile 里如果出现Program Files这类路径,jom 会把路径截断,报错非常难查。

3.3 版本锁定:tag、子模块与补丁同步

如果你是从 Git 仓库拉的源码而不是资源包,注意旧版 Telegram 用的是 tag 管理版本,例如 v0.9.5 这类标签。拉取时要用递归方式把子模块带下来,命令是:

git clone --recursive https://github.com/telegramdesktop/tdesktop.git git checkout v0.9.5

浅克隆(--depth 1)在这个项目上不适合,因为子模块没有完整历史时,git submodule update会拿不到正确提交点。资源包里是已经同步好的完整目录,你只需要核对版本号一致。这里务必检查 QtStatic/patches 目录里的补丁文件是否和 Qt 源码版本对应,补丁打错位置在 patch 阶段就会失败,那是最早的一颗雷。

4. 把 Qt 5.3.1 和 QScintilla 编译出来:configure 参数与并行构建

4.1 configure 参数详解:-no-icu -nomake tests -mp 这些开关怎么权衡

Qt 5.3.1 的 configure 是整个链路里最考验耐心的环节。别用 Qt 官方安装包偷懒,Telegram 的补丁需要打在源码上,必须从源码编译。先进入 Qt 源码目录,执行:

cd C:\Qt\src\qt-5.3.1 configure -opensource -confirm-license ^ -prefix C:\Qt\Qt5.3.1 ^ -platform win32-msvc2013 ^ -release -no-icu -no-openssl ^ -nomake examples -nomake tests ^ -mp

逐项说含义。-opensource -confirm-license是跳过授权交互,商业授权和开源授权在这个分支上没有功能差异,选开源即可。-prefix指定安装位置,我习惯让安装目录和源码目录分开,方便后面重编源码时不用清空安装目录。-release表示只编 release 版,Telegram 旧版构建脚本默认链接 release 库,只编这一种能把时间砍掉近一半。-no-icu关掉 ICU 支持,Telegram 的字符串处理不依赖它,开着反而多编译几百个文件。-no-openssl是让 Qt 自身不带 SSL 后端,Telegram 链接的是自己那份 OpenSSL 1.0.1r,两个 SSL 后端混在一起会打架。-nomake examples -nomake tests是不编示例和测试,纯粹省时间。-mp开启 MSVC 的多进程编译,配合 jom 才能把 CPU 吃满。

注意-no-openssl是给 Qt 省事的,不是给 Telegram 省事。Telegram 自己链接 OpenSSL,所以这条关闭不影响最终程序。

4.2 jom 并行编译与 install:nmake 慢在哪儿

configure 完成后,源码目录里会生成 Makefile。用 nmake 也能编,但 nmake 是单进程的,8 核机器跑起来 CPU 利用率不到 15%,Qt 全量 release 编译大概要两个小时。jom 是 Qt 官方的并行 make 工具,和 nmake 兼容同一个 Makefile,但能按 CPU 核数并行:

jom -j8 jom install

-j8根据 CPU 核心数调整,不用开满,留两个核给系统避免卡死。jom install 会把编译产物安装到 configure 时指定的 prefix 目录。这里有个容易误会的点:jom 不是替代 qmake 的,它替代的是 nmake,作用和命令格式都很像。如果你装了多个 Qt 版本,确保 PATH 里的 jom 是 Qt 5.3.1 同目录带的那个,旧版本 jom 解析新版 Makefile 偶尔会报无效指令。

如果编译中途失败,可以先用jom -k -j1单进程跑一遍,把所有错误完整输出,再回来看。并行编译失败时的报错是乱序的,单进程能让你看清第一个根因。

4.3 QScintilla 2.8 配合 Qt 5.3.1 的编译顺序

QScintilla 的编译在整个链路里有特殊地位,因为它生成的头文件和库会被 Telegram 主程序直接引用。源码在 QScintilla 目录下,工程文件在 Qt4Qt5 子目录里,这个目录名容易让人误会,但其实它同时兼容 Qt4 和 Qt5,qmake 会自动识别当前 Qt 版本:

cd ThirdParty\qscintilla\Qt4Qt5 qmake "CONFIG+=release" qscintilla.pro jom -j8 jom install

为什么要在qmake后面手动指定CONFIG+=release?因为 QScintilla 的 pro 文件默认会生成 debug 和 release 两套配置,install 时两个版本都装,但链接顺序稍有不慎就会让 Telegram 的 release 工程链上 debug 版 Qt 库,触发 LNK4098 警告,运行时崩溃。手动限定 release 能少踩这个坑。

安装完成后确认头文件目录的位置。QScintilla 的 install 默认把头文件装到include\Qsci目录,但 Telegram 工程里部分版本的 INCLUDEPATH 引用的是qscintilla目录名,两个目录对不上就是 C1083 报错。解决办法是把Qsci目录复制一份改名成qscintilla:

xcopy /E /I C:\Qt\Qt5.3.1\include\Qsci C:\Qt\Qt5.3.1\include\qscintilla

这是个笨办法但很有效,Telegram 那些老工程的路径假设就是不一样,你顺着它改不如直接让它两处都找得到。

4.4 一个小工程验证 Qt 可用:qmake 与 qmlscene

Qt 和 QScintilla 都装好之后,先别急着进 Telegram 主工程,用一个最小验证确认环境是活的:

qmake -v qmlscene --version

qmake -v 输出里要能看到 Qt 5.3.1 字样。如果输出的版本不是 5.3.1,说明 PATH 里前面还有另一个 Qt,调整环境变量把 C:\Qt\Qt5.3.1\bin 提到最前。qmlscene 存在的话,可以手动加载 Qt 自带 QML demo 检查渲染链路,这一步能提前暴露 OpenGL 或 ANGLE 的问题,避免把锅甩给 Telegram 工程。

5. 主程序构建与避坑:build.bat 改造、nmake 与五条踩坑记录

5.1 build.bat 里的硬编码:Qt 路径与第三方库路径

Telegram 主程序的编译入口是 SourceFiles/build.bat,但我不建议直接跑它,因为它内部有硬编码路径。常见做法是先打开脚本看一遍,把下面两个变量改成你自己的实际路径:

set QT_PATH=C:\Qt\Qt5.3.1 set QSCINTILLA_PATH=C:\Qt\Qt5.3.1

QT_PATH指向 Qt 安装目录,QSCINTILLA_PATH指向 QScintilla 安装目录,这个脚本里如果写的是D:\Qt\Qt5.3.1,你在 C 盘装的就必炸。改完路径后,在 VS2013 x86 命令行里执行:

call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86 cd /d D:\work\Telegram\SourceFiles nmake /f telegram.mk

为什么必须用 x86 的 vcvarsall?旧版 Telegram 的第三方库全是 32 位编译的,你切到 x64 模式后,链接器找不到任何 32 位库,报错清一色是 LNK2019。这一点你不踩一次很难记住:不是你的代码有问题,是命令行环境切错位了。

nmake /f telegram.mk这条命令是构建主程序的核心,telegram.mk是 qmake 生成出来的 Makefile。如果 build.bat 跑通了,你也可以直接跑它,但环境变量不全会提示找不到 cl.exe。我的习惯是手动执行 nmake,能看到每一条编译命令和完整报错,出问题时好定位是哪个源文件。

5.2 常见错误排查:C1083、U1077、栈溢出与链接冲突

这一节是这份资源里最有价值的部分,全部是我自己踩过或者帮别人查过的真实记录,按现象到原因到解决一条条说。

现象 1:fatal error C1083: 无法打开包含文件: "qscintilla/qsciscintilla.h"

原因:QScintilla 的头文件没被安装到 Telegram 能找到的 include 路径下。最常见的是 QScintilla 的 install 步骤没执行,或者头文件被装在include\Qsci但 Telegram 引用的是include\qscintilla。解决:回到 4.3 节,确认 jom install 执行过,并且include\qscintilla目录存在。还找不到的话,在 telegram.mk 里手动加一行INCLUDEPATH += C:\Qt\Qt5.3.1\include\qscintilla。

现象 2:NMAKE : fatal error U1077: 'rc.exe' : return code '0x1'

原因:rc.exe 是 Windows SDK 里的资源编译器,不在 PATH 里。直接开普通 CMD 执行 nmake 时,SDK 工具链没有加载,资源编译必定失败。解决:不要用普通 CMD,必须先用 vcvarsall.bat 拉起完整 VS 环境,如上文 5.1 节所示。这个坑的特点是报错时间早,几乎一进资源编译就报,挺好定位。

现象 3:链接期 LNK2005 或 LNK2038 冲突,符号重定义

原因:混合了不同版本或不同配置的库。典型场景是 Qt 用 MSVC 2013 编译,但某个第三方库是用 MSVC 2015 编的。LNK2038 会明确提示_MSC_VER不匹配,解决办法只有一个:所有第三方库统一用同一套编译器重编,没有捷径。我见过有人试图用#pragma忽略这个错误,运行后必崩,这是标准的错误排除方式。

现象 4:编译到一半栈溢出,报 stack overflow

原因:Telegram 旧版有一部分代码是脚本生成的,生成出来的 C++ 源文件模板套模板,MSVC 默认 1MB 栈不够用。这个报错看起来像死循环,但实际是你编译器栈太小。解决:Release 模式下给链接器加扩容参数,在 telegram.mk 里把QMAKE_LFLAGS加上/STACK:0x4000000,4MB 栈基本够用。也可以切到 Release 配置,Debug 模式下的额外检查会更早触发栈溢出。

现象 5:编译成功但运行报缺少 msvcr120.dll

原因:目标机器上没装 VS2013 的 VC 运行库。Telegram 编译产物依赖 msvcr120.dll 和 msvcp120.dll。解决:在运行目录放这两个 dll,或者安装 VC redist 2013 x86。注意是 x86 版本,64 位系统上只装 x64 的 VC 库覆盖不到 32 位程序的需求。

6. 验证编译产物:windeployqt、版本号确认与一个进阶习惯

编译完的 Telegram.exe 在 SourceFiles\Release 目录下。老手可能直接双击跑,但我建议先走一遍资源部署,否则运行时会因为缺 Qt 的 dll 报错。Qt 5.3.1 的 bin 目录里已经有 windeployqt 工具,一行命令把依赖拉齐:

cd /d D:\work\Telegram\SourceFiles\Release C:\Qt\Qt5.3.1\bin\windeployqt.exe Telegram.exe --no-opengl-sw

--no-opengl-sw会跳过软件 OpenGL 组件,Telegram 用的是 ANGLE 方案,这个参数能省掉两个大文件的拷贝。执行完后检查是否生成了 platforms 目录,里面要有 qwindows.dll,这是 Qt 在 Windows 上的窗口插件,缺了它程序会报could not find or load the Qt platform plugin "windows"。然后把 Telegram\Resources 和源码包里的 Resources 目录同步到 exe 同级,否则图标和语言文件会丢,界面显示异常。

验证版本号可以帮助确认你编的是哪个分支。在 exe 目录执行Telegram.exe --version,正常会输出一串版本字符串和 git build 标识。这一步不是走形式,它能帮你快速区分机器上是官方二进制还是你编出来的产物,避免后面测了一下午发现是在测旧程序。

这里我想分享一个从这次折腾里沉淀出来的习惯:每次动手编译这类旧工具链项目之前,先创建一个 build_note.txt,把 configure 参数、vcvarsall 调用顺序、环境变量三个东西原样贴进去。半年后你重装系统或者换机器,看到这份笔记,可以省掉一半的排查时间。我上一次就是因为没留记录,重装后把 QMAKESPEC 忘了配,qmake 自动识别到了错误的编译器规范,报错晦涩到让我怀疑 Qt 源码本身有问题,最后才发现是环境变量丢了。从那以后,我每次动这个工程都把配置记录写进 README,先跑一遍最小验证再进主工程。这份资源里踩过的坑和路径调整,我都按上面的顺序重新走了一遍,希望你照这个流程操作时能少走几段弯路,一次把 Qt 5.3.1 和 Telegram 都编干净。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/13 9:04:54

MapBox WebGL截图原理与高精度导出实战

/* 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 9:04:36

计算机专业毕业设计选题指南与实战建议

1. 为什么计算机专业毕业设计选题如此重要?毕业设计是计算机专业学生大学四年的终极考验,它不仅是对所学知识的综合检验,更是展示个人能力的重要窗口。我见过太多学生因为选题不当而陷入困境:有的选题过于宏大导致无法完成&#x…

作者头像 李华
网站建设 2026/10/13 9:03:55

卷积神经网络热度图可视化:Grad-CAM原理与实战指南

/* 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 9:03:33

HashMap负载因子0.75:从概率、源码到扩容调优的完整解析

/* 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 9:03:20

51单片机计时器实战:数码管显示与定时器中断配置

/* 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 9:03:20

跨模态行人重识别:共享-特有特征迁移(SSFT)技术解析

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

作者头像 李华