Win10+VS2017编译librtmp.lib:从环境配置到链接验证的完整避坑指南
简介:面向需要在 Windows 10 与 VS2017 环境下使用 RTMP 推流能力的 C/C++ 开发者,这份资源提供可直接编译的 librtmp.lib 静态库工程,省去自行移植与配置依赖的麻烦。压缩包共 238 个文件、约 49.12MB,以 163 个头文件为主,配合 28 个 dll、8 个 lib 及少量 c 源文件与工程配置,涵盖 librtmp 源码、openssl-1.0.1c、zlib-1.2.8 等依赖目录,并附带 librtmp.sln 解决方案,结构清晰便于按模块查阅。已有 640 人学习下载,适合需要快速集成 RTMP 协议栈的中高级开发者参考。读者可直接打开解决方案编译出库文件,对照源码理解握手、AMF 编解码与 URL 解析等实现,并借助现成依赖配置排查链接错误,减少环境搭建与依赖适配的试错成本。
1. 在 Win10 上把 librtmp.lib 编出来:为什么我劝你先别急着点“生成”
Win10 + VS2017 编译 librtmp.lib,这套组合在流媒体、播放器二次开发、推流模块对接的场景里出现频率极高,但真正动手的人十个里有八个会在第一次“生成”时翻车。原因不玄学:librtmp 是十多年前的 C 代码,自带一套手写 Makefile 和一批老式头文件依赖,而 VS2017 默认按现代 MSVC 的严格标准走,直接新建一个空项目把源码拖进去,大概率收获一屏 LNK2019 和 C4996。更麻烦的是,很多人拿到的是“包含引用库和源代码、可直接编译”的压缩包,以为双击 sln 就完事,结果发现工程配置里的路径全是别人机器上的绝对路径,一编译就报找不到 zlib.h。这篇笔记就是按我自己在一台干净 Win10 机器上从零走通的顺序写的:先列清环境,再讲工程怎么配,再讲编译参数怎么取舍,最后落到怎么验证这个 .lib 真的能用。适合正在对接 RTMP 推拉流、需要静态库而不是现成 DLL 的开发者,也适合被旧工程迁移折腾过一轮、想看清每个配置项到底在干什么的熟手。
2. 环境准备:VS2017 组件、zlib 依赖和目录结构先摆平
2.1 确认 VS2017 装的是哪一档,别拿 Community 当万能
VS2017 有三个常见版本:Community、Professional、Enterprise。编译 librtmp 这种纯 C 静态库,Community 完全够用,不需要额外授权。真正要盯的是安装时勾选的组件,很多人装完发现没有 C++ 编译器,是因为只勾了“.NET 桌面开发”。打开 Visual Studio Installer,确认“使用 C++ 的桌面开发”这一项已勾选,右侧摘要里至少要包含:
- MSVC v141 - VS 2017 C++ x64/x86 生成工具
- Windows 10 SDK(版本 10.0.16299.0 及以上都行,我一般用 10.0.17763.0)
- C++ 通用 Windows 平台工具(可选,但有些旧工程模板会引用)
v141 这个工具集编号要记住,后面工程属性里“平台工具集”填的就是它。如果你机器上同时装了 VS2015 和 VS2019,默认打开 sln 时可能被更高版本接管,导致工具集被改成 v142,编译出来的 .lib 在只装了 v141 运行库的机器上链接会出问题。常见做法是右键 sln → “重定解决方案目标”,手动锁回 v141。
# 在 Developer Command Prompt for VS 2017 里确认工具集 cl # 输出应包含: Microsoft (R) C/C++ Optimizing Compiler Version 19.16.xxxxx for x86cl后面那行版本号 19.16 对应 VS2017,19.15 是 VS2017 早期版本,19.20 就已经是 VS2019 了。版本对不上,说明你开的命令行窗口不是 VS2017 的,或者 PATH 里混进了别的编译器。
2.2 zlib 是硬依赖,先把它编成同架构的静态库
librtmp 的握手和部分数据处理依赖 zlib,压缩包里如果带了 zlib 源码或预编译 lib,优先用包内的;如果没带,就得自己补一个。关键点只有一个:架构必须和 librtmp 一致。x86 的 librtmp 去链 x64 的 zlib.lib,报错不是“找不到库”,而是一堆莫名其妙的 LNK2001 未解析符号,很容易被误导到源码问题上。
我一般把目录整理成这样,避免路径里出现中文和空格:
D:\build\librtmp\ ├── src\ # 解压出来的 librtmp 源码 ├── zlib\ # zlib 源码或预编译库 │ ├── include\ │ └── lib\ └── output\ # 编译产物放这里zlib 自己编的话,用 VS2017 命令行进到 zlib 的 win32 或 contrib\vstudio 目录,按架构选 Makefile 或 sln。编完确认zlib.lib和zconf.h、zlib.h都在。这一步别偷懒用网上随便下的 zlib.lib,版本和编译选项(尤其是 /MD 还是 /MT)跟 librtmp 对不上,后面链接期会还债。
2.3 检查源码里那几个“老古董”头文件
librtmp 源码里常见#include <sys/time.h>、#include <unistd.h>这类 POSIX 头,Windows 下没有。正规的移植版会用#ifdef _WIN32包起来,但不同来源的源码包处理程度不一样。打开rtmp.h、rtmp_sys.h、handshake.h扫一眼,如果看到裸的sys/time.h没被条件编译包住,就得手动补:
#ifdef _WIN32 #include <winsock2.h> #include <ws2tcpip.h> #else #include <sys/time.h> #include <unistd.h> #endif另外确认源码里有没有#define _CRT_SECURE_NO_WARNINGS,没有的话在工程预处理器里加上,否则strcpy、sprintf这类调用会被 C4996 警告刷屏,虽然不影响生成,但会淹没真正的错误信息。
3. 工程配置:把“可直接编译”翻译成你自己的路径
3.1 新建静态库工程还是直接用包内 sln
压缩包说“可直接编译”,通常意味着里面有一个 .sln 或 .vcxproj。我的建议是:先试着打开包内工程,但不要直接信它的配置。打开后第一件事是看“项目属性 → 常规 → 输出目录”和“中间目录”,如果里面是C:\Users\某某\Desktop\...这种绝对路径,全部改成相对路径$(SolutionDir)output\和$(SolutionDir)obj\。第二件事看“C/C++ → 附加包含目录”,把里面指向别人机器的 zlib 路径删掉,换成你自己的D:\build\librtmp\zlib\include。
如果包内没有工程文件,只有源码,那就新建“Windows 桌面 → 静态库”项目,把 .c 和 .h 全部添加进去。注意 librtmp 的核心文件是这几个,别漏:
| 文件 | 作用 | 是否必须 |
|---|---|---|
| rtmp.c | 协议主逻辑 | 必须 |
| handshake.c | 握手实现 | 必须 |
| amf.c | AMF 编解码 | 必须 |
| hashswf.c | SWF 校验哈希 | 推流校验时需要 |
| log.c | 日志输出 | 建议保留 |
| parseurl.c | URL 解析 | 必须 |
漏掉hashswf.c时编译能过,但运行期做某些鉴权推流会直接失败,而且报错信息很含糊,这是血泪经验。
3.2 平台工具集、字符集、运行库三件套怎么定
项目属性里这三项必须一次定死,后面不再改:
- 平台工具集:Visual Studio 2017 (v141)
- 字符集:使用多字节字符集。librtmp 内部大量
char*和sprintf,改成 Unicode 会引入一堆转换问题,没必要。 - C/C++ → 代码生成 → 运行库:多线程 (/MT) 或多线程 DLL (/MD),取决于你最终调用方的设置。静态库本身不链接运行库,但编译时的 /MT 和 /MD 会影响目标文件里的 CRT 引用方式。我一般跟调用方保持一致,独立工具用 /MT,跟其他 DLL 混编用 /MD。
<!-- 在 vcxproj 里对应这几行,改完记得保存 --> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PlatformToolset>v141</PlatformToolset> <CharacterSet>MultiByte</CharacterSet> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> </PropertyGroup>RuntimeLibrary的值MultiThreaded对应 /MT,MultiThreadedDLL对应 /MD。改完如果链接方报LNK2038: 检测到“RuntimeLibrary”的不匹配项,就是这里和调用方不一致,回来对齐即可。
3.3 预处理器定义和附加依赖项逐条过
“C/C++ → 预处理器 → 预处理器定义”里加上:
_CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE WIN32 _WINDOWS前两个压掉老式 CRT 函数的警告,后两个让源码里的 Windows 分支生效。如果源码里有NO_CRYPTO之类的开关,按包内说明决定要不要加,不加会引入 OpenSSL 依赖,那就不是“只编一个 .lib”的事了。
“链接器 → 输入 → 附加依赖项”填ws2_32.lib;zlib.lib;。ws2_32 是 Winsock,librtmp 做网络连接必须;zlib.lib 路径在“链接器 → 常规 → 附加库目录”里指向D:\build\librtmp\zlib\lib。顺序上 ws2_32 在前问题不大,但 zlib 一定要在,否则inflate、deflate系列符号全部未解析。
3.4 编译前最后一遍检查清单
动手点“生成”之前,按这个顺序扫一遍,能省掉大半返工:
- 解决方案平台选 Win32 还是 x64,和你的 zlib 架构一致;
- 配置选 Release,Debug 版 .lib 带调试信息,发布时别混用;
- 附加包含目录里没有中文路径、没有别人机器的盘符;
- 输出目录存在,或者至少父目录存在,MSBuild 不会自动建多级目录;
- 源码文件编码是 UTF-8 无 BOM 或 GBK,混编码会导致中文注释行报 C2001。
4. 编译与产物核对:.lib 出来了不等于能用
4.1 生成命令与常见输出解读
在 VS2017 里直接“生成解决方案”即可,也可以用命令行复现,方便排查:
# 在 Developer Command Prompt for VS 2017 中,进入工程目录 msbuild librtmp.sln /p:Configuration=Release /p:Platform=Win32 /v:minimal/p:Configuration和/p:Platform必须和你在 IDE 里选的一致,/v:minimal只输出关键信息,报错时改成/v:detailed能看到具体是哪个文件哪一行。生成成功后,输出目录里应该有librtmp.lib,大小通常在几百 KB 量级。如果只有几十 KB,多半是只编进去了一两个 .c,回去检查“解决方案资源管理器”里文件是否都带上了小箭头(表示参与编译)。
4.2 用 dumpbin 验证符号,别等调用方报错才发现
.lib 生成后,第一件事不是拿去用,而是查符号表:
dumpbin /symbols output\librtmp.lib | findstr "RTMP_Init RTMP_Connect RTMP_SendPacket"正常应该能看到这几个符号的External记录。如果RTMP_Init找不到,说明 rtmp.c 没参与编译;如果符号前面带__imp_前缀,说明某个环节把它当成了导入库,检查是不是误把 DLL 的 .lib 混进来了。这一步是黑匣子,能提前把“库是空的”和“库是 DLL 导入库”两种情况区分开。
4.3 写一个最小调用程序做链接验证
光有符号还不够,真正能链上才算数。新建一个控制台空项目,引用这个 .lib,写十行代码:
#include <stdio.h> #include "rtmp.h" int main(void) { RTMP *r = RTMP_Alloc(); /* 分配 RTMP 上下文 */ if (r == NULL) { printf("alloc failed\n"); return 1; } RTMP_Init(r); /* 初始化默认参数 */ printf("librtmp linked ok\n"); RTMP_Free(r); /* 释放,避免泄漏 */ return 0; }链接器附加依赖项填librtmp.lib;ws2_32.lib;zlib.lib;,包含目录指向 librtmp 源码目录和 zlib 的 include。能编过并打印出librtmp linked ok,说明静态库的符号、CRT 设置、依赖库三者都对上了。这一步跑不通,别急着写业务代码,先回来对运行库和架构。
5. 避坑排查:五条我真实踩过的记录
5.1 现象:LNK2019 未解析的外部符号__imp__WSAStartup
原因:只链了 ws2_32.lib 的导入库形式,或者工程里误加了#pragma comment(lib, "ws2_32.lib")但平台选错。更隐蔽的一种是源码里 Winsock 头包含顺序不对,winsock2.h在windows.h之后被包含,导致宏定义冲突。
解决:确保“附加依赖项”里是ws2_32.lib,且源码里#include <winsock2.h>放在#include <windows.h>之前。如果还不行,用dumpbin /symbols查 ws2_32.lib 里到底有没有这个符号,确认你链的是系统库而不是某个同名野库。
5.2 现象:编译通过,运行时报“无法定位程序输入点 inflateEnd”
原因:zlib 用的是 DLL 版导入库,但运行目录里没有 zlib1.dll;或者静态库编译时 /MD,调用方 /MT,CRT 堆不一致导致 zlib 内部状态错乱。
解决:统一用 zlib 静态库(zlibstatic.lib 或自己编的 zlib.lib),并在调用方工程里同样设置 /MT 或 /MD。如果必须用 DLL 版,把 zlib1.dll 放到 exe 同目录,别指望系统路径。
5.3 现象:C4996 警告几百条,真正的错误被淹没
原因:没定义_CRT_SECURE_NO_WARNINGS,MSVC 对strcpy、sprintf、fopen全部告警。
解决:预处理器定义里加上_CRT_SECURE_NO_WARNINGS和_CRT_NONSTDC_NO_DEPRECATE。不建议用#pragma warning(disable:4996)全局压,那样连别的文件的真实告警也一起吞了,排查时更痛苦。
5.4 现象:x64 工程链接 x86 的 zlib,报一堆 LNK2001
原因:架构不匹配时,链接器不会直接说“架构不对”,而是找不到符号,因为 x86 的 .lib 里符号修饰方式和 x64 不同。
解决:用dumpbin /headers zlib.lib | findstr machine看架构,x86 显示14C machine (x86),x64 显示8664 machine (x64)。两边必须一致,不一致就重编 zlib。
5.5 现象:包内 sln 打开后提示“项目不可用”,或工具集自动跳到 v142
原因:sln 里记录的 VS 版本高于本机,或者本机装了更高版本 VS 并设置了默认打开方式。
解决:右键 sln → “重定解决方案目标”,选 v141;如果项目直接不可用,用文本编辑器打开 .vcxproj,把<PlatformToolset>改成v141,把<WindowsTargetPlatformVersion>改成你本机实际安装的 SDK 版本号,再重新打开。
6. 装完怎么验证:三层验证法,从符号到实际握手
6.1 第一层:符号层验证
前面 dumpbin 查符号是最快的一层,但只证明“符号在”。我一般会把关键符号列成一个清单,逐条 grep:
dumpbin /symbols output\librtmp.lib > symbols.txt findstr /C:"RTMP_Alloc" /C:"RTMP_Init" /C:"RTMP_Connect" /C:"RTMP_SendPacket" /C:"RTMP_Free" symbols.txt五条全中,说明核心 API 都编进去了。少任何一条,回去看对应 .c 文件是否在工程里。这一层花不了一分钟,但能挡掉后面 80% 的“库是残的”问题。
6.2 第二层:链接层验证
用 4.3 那个最小程序,分别用 Debug 和 Release、Win32 和 x64 各链一遍。四种组合里至少 Release + 你的目标架构要过。链接时把“链接器 → 常规 → 显示进度”打开,能看到它实际找了哪些库、从哪个路径找的,路径不对一眼就能看出来。如果出现LNK4098: 默认库“MSVCRT”与其他库的使用冲突,就是运行库设置不一致,回 3.2 对齐。
6.3 第三层:运行层验证
真正跑一次 RTMP 连接才算数。找一个可用的 RTMP 服务地址(本地自建或测试环境),写个最小连接程序:
#include "rtmp.h" int main(void) { RTMP *r = RTMP_Alloc(); RTMP_Init(r); if (!RTMP_SetupURL(r, (char *)"rtmp://127.0.0.1:1935/live/test")) { printf("setup url failed\n"); return 1; } RTMP_EnableWrite(r); /* 推流模式,拉流则去掉这行 */ if (!RTMP_Connect(r, NULL)) { printf("connect failed, code=%d\n", RTMP_GetLastError(r)); return 1; } printf("rtmp connected\n"); RTMP_Close(r); RTMP_Free(r); return 0; }RTMP_GetLastError能给出具体错误码,连不上时先看这个,再抓包看握手包有没有发出去。能打印rtmp connected,这个 .lib 才算真正可用。我习惯把这三层验证写成一个批处理,每次重新编库都跑一遍,从那以后再也没有出现过“库编出来了、业务一调就崩”的情况。希望帮到你。
本文还有配套的精品资源,点击获取