资讯详情

资讯详情

VLC 2.0.4 Windows编译全攻略:MSYS+MinGW环境搭建与打包实战

简介VLC 2.0.4 Windows 编译手册是一份面向希望在 Windows 平台下从源码编译 VLC 的开发者的实操指引。VLC 是 VideoLAN 开源项目旗下的跨平台流媒体服务器和多媒体播放器支持 WMV、ASF、MPG、AVI、H.264 等多种格式手册以资源包内单个 doc 文档共 1 个文件267KB完整记录了编译环境搭建、组件安装和源码编译的关键步骤。内容依次覆盖 Msys、MSYS-DTK、MinGW、Git、wget 等工具链的版本选择与安装位置Lua 库编译VLC 源码下载以及 configure 文件修改、contrib 配置等核心环节并标注了各组件来源便于对照操作。目前已有 322 人学习/下载对于不熟悉开源项目交叉编译的开发者可将这份文档作为从零搭建环境的参考显著减少中间环节的踩坑时间。1. 为什么 VLC 2.0.4 的 Windows 编译值得自己跑一遍很多人卡在 VLC 2.0.4 的 Windows 编译上是因为它并不只是点一下编译这么简单VLC 的构建系统由 autotools 驱动configure 脚本需要 POSIX shell、perl、m4 这一整个工具链而 Windows 原生环境给不了这些。这份编译手册的价值在于它把散落在 SourceForge 各处的依赖包、版本号、目录约束串成了可复现步骤从安装 MSYS 到生成 vlc-x.x.x 目录中间每一步都给了明确改法。我自己在 Windows 7 上完整走过一遍改过三个源码文件、动过四处打包脚本最终产出了一个可以拷走就用的免安装绿色版。它适合正在研究 VLC 源码、想裁剪模块或者需要交付定制播放器的人新手按顺序执行能跑通熟手则能从这里看出 2.0.4 时代工具链的边界在哪里。2. 编译环境搭建MSYS、MinGW 与工具链版本匹配的几个硬约束先花两分钟理解这套环境为什么长这样后面踩坑会少很多。VLC 2.0.4 的 configure 脚本需要 POSIX shell 来做功能探测需要 perl 来跑 autotools 辅助脚本需要 m4 来展开宏这些在 Windows 的 cmd 里都不存在。MSYS 1.0 提供一个轻量 POSIX 运行层MinGW 提供 Windows 原生编译器两者组合起来configure 才能在 Windows 上生成 Makefile 并交给 gcc 编译。当年社区选这条路而不是 Cygwin是因为 Cygwin 生成的二进制会依赖 cygwin1.dll而 MSYS MinGW 产出的程序是真正原生的 Win32 程序可以直接分发。2.1 MSYS、MSYS-DTK、TDM-GCC 安装顺序与目录强制约束安装顺序是 MSYS 1.0.11 → MSYS-DTK 1.0.1 → TDM-GCC 4.7.1-2 → mingw-utils 0.3顺序不能乱。MSYS 1.0.11 是基础安装向导走到最后一步会弹出一个 DOS 命令行窗口那是 MSYS 自带的 bash 环境后续所有操作都在它里面做。DTK 1.0.1 是 MSYS 的开发工具包bison、flex、gperf 都在里面安装目录必须与 MSYS 完全一致原因很简单DTK 会把文件直接合并进 MSYS 的目录树路径不一致等于白装工具链根本找不到这些命令。TDM-GCC 4.7.1-2 是当时 MinGW32 社区常用的集成发行版比裸装 MinGW 省去一堆手工配置。安装时目标目录要指向 C:\MSys\1.0\mingw这样 MSYS 里的 /mingw/bin 才能直接看到 gcc 和 g而 VLC 的 configure 会在路径里按这个名字找编译器。mingw-utils 0.3 是个 tar.gz 包解压后把 bin 目录整体复制到 Msys\1.0 下里面提供的是 strip、ar 等二进制工具的运行时contrib 的 libtool 脚本会额外调用它们。注意MSYS 1.0 是 32 位运行环境。你的操作系统是 64 位也没关系但它内部按 32 位路径处理安装路径和用户目录不能有空格也不能有中文。2.2 Git、wget、AutoTools、Glib 与 pkg-config 的放置位置这节本质上是在回答一个问题configure 的功能检测会调用哪些外部命令这些命令必须提前躺在 MSYS 能找到的位置。Git 要装到 Msys\1.0\mingw\Git因为后续 contrib 拉取源码时 git.exe 的路径几乎写死在这里。wget 1.11.4-1 装到 Msys\1.0\mingw——手册在这一步原文写的是将 Git 程序安装到实际是 wget 的笔误wget 的作用是 contrib 预编译包缺失时自动下载 tarball。AutoTools 这边需要六个文件autoconf-2.68-1、automake-1.11.1-1、libtool-2.4-1、libcrypt-1.1_1-2、perl-5.8.8-1、m4-1.4.14-1全部解压合并到 Msys\1.0。版本不能换新的原因很现实2.0.4 的 configure.ac 用的是 automake 1.11 时代的旧语法新版 automake 会把 AM_INIT_AUTOMAKE 的参数校验直接变成 fatal errorlibtool 2.4 与 MSYS 运行时的配对也是当年测试过的组合升级 libtool 容易引入 libltdl 加载异常。Glib 和 pkg-config_0.23-3、gettext-runtime_0.18.1.1-2 同样解压到 Msys\1.0。pkg-config 是 VLC 插件系统找 glib、gtk、libxml2 的 .pc 文件的入口没有它 configure 会跳过一大堆插件的检测。下表是完整的环境清单照着版本号找文件就对了。组件手册使用版本放置位置作用MSYS1.0.11C:\MSysPOSIX 运行层MSYS-DTK1.0.1C:\MSysbison/flex 等开发工具TDM-GCC4.7.1-2C:\MSys\1.0\mingwC/C 编译器mingw-utils0.3Msys\1.0strip/ar 等二进制工具autoconf2.68-1Msys\1.0生成 configureautomake1.11.1-1Msys\1.0生成 Makefile.inlibtool2.4-1Msys\1.0共享库链接机制perl5.8.8-1Msys\1.0autotools 运行依赖m41.4.14-1Msys\1.0宏展开器pkg-config0.23-3Msys\1.0解析 .pc 文件2.3 手工补件whoami、coreutils、libiconv 与 msys.bat 的 PKG_CONFIG_PATH这一个环境里有三个必须手工补的小零件缺一个 configure 都会莫名其妙断掉。第一个是 whoami在 C:\MSys\1.0\bin 下新建一个无扩展名的文件名字就叫 whoami里面只有一行内容echo username把username替换成你当前的 Windows 用户名。configure 在生成 config.h 时要取用户名拼进 VLC_COMPILED_BY 常量而 MSYS 基础包没有完整的 whoami 实现于是手册用一个假命令顶替。注意单引号要保留这样 echo 输出时不会把用户名当参数解析。第二个是 coreutils、libiconv、libintl 三个 MSYS 扩展包从 SourceForge 的 MSYS/BaseSystem 页面下载对应版本解压后把文件复制到 Msys\1.0\bin。libintl 缺失是 configure 阶段最常见的 cannot find libintl 元凶iconv 缺失则会在编译某些 access 模块时出现链接错误。第三个是修改 msys.bat。在if %1 GOTO: goto %2这一行上面加上一行环境变量设置set PKG_CONFIG_PATH/home/jb/vlc-2.0/contrib/i586-mingw32msvc/lib/pkgconfig这行代码的作用是每次启动 MSYS 时自动把 pkg-config 的搜索路径指向后面要解压的 contrib 预编译库。注意这里用的是正斜杠路径由 MSYS 内部转换成 Windows 路径pkg-config 自己能处理。不要把它加进 Windows 系统环境变量因为这是 MSYS 风格路径放进系统变量会干扰其他 Windows 程序对 PKG_CONFIG_PATH 的解析。3. 源码接进 MSYScontrib 预编译库与三个必改文件VLC 的依赖库都是靠 contrib 体系管理起来的。2.0.4 有两条路让 contrib 自动下载每个依赖的源码并现场编译或者直接用官方预编译包 vlc-contrib-i586-mingw32msvc-latest.tar.bz2。手册走的是后者省掉几十个依赖库的源码编译时间但代价是路径非常挑剔下面的每个修改都是为预编译包铺路。3.1 contrib 目录规划与 bootstrap/Makefile 路径改写先规划目录在 /home/jb 下创建 vlc-2.0 目录把 VLC 源码解压进去再把 vlc-contrib-i586-mingw32msvc-latest.tar.bz2 复制到 contrib 目录下如果 contrib 目录里没有这个压缩包bootstrap 阶段会自动下载。用户目录之所以必须是 jb是因为手册第 11 步的 bootstrap 和后面一批 Makefile 都硬编码了 /home/jb 这个路径换成别的用户名会拉到不存在的位置。修改 contrib 下的 bootstrap 文件两处# 文件: /home/jb/vlc-2.0/contrib/bootstrap BUILDi586-mingw32msvc # 将文件中所有 ../../contrib/ 替换成 ../contrib sed -i s#../../contrib/#../contrib/#g bootstrap这里的 BUILD 指定 MinGW 三元组决定后面 Makefile 生成的目标目录名sed 替换把两层的相对路径引用改成单层是因为手册把 contrib 从源码树内移到了与源码根目录平级的位置。不改的话bootstrap 去找 tarballs 时路径不存在make prebuilt 会直接失败。执行./bootstrap生成 Makefile 之后打开 Makefile 再改一段路径配置TOPSRC ? ../contrib TOPDST ? .. SRC : $(TOPSRC)/src TARBALLS : $(TOPSRC)/tarballs PATH : $(abspath ../extras/tools/build/bin):$(PATH)TOPSRC 和 TOPDST 决定依赖源码包和 tar 包的位置SRC、TARBALLS 是 contrib 内部约定的两个子目录PATH 把 extras/tools/build/bin 提前是为了让 contrib 构建能找到 perl、wget 等工具。这三处与 bootstrap 里的修改是配套的改完执行make prebuilt解压预编译 contrib 并打印处理记录看到 completed 信息即可继续。3.2 三个必改文件vlc_windows_interfaces.h、configure.ac、configure.sh这三个文件不改configure 阶段也能蒙混过去但会在编译中段或链接阶段炸出来。第一个是源码里的 include/vlc_windows_interfaces.h在#include objbase.h下面加一行#include objbase.h #undef small原因是 Windows SDK 的 windef.h 把small定义成了宏而 VLC 源码里 small 是普通变量名宏展开后编译器会报expected unqualified-id before small。这个文件被大量模块间接 include所以要在 objbase.h 之后统一取消宏让宏先定义再被取消顺序不能反。第二个是 configure.ac。找到这行AC_DEFINE_UNQUOTED(VLC_COMPILE_HOST, hostname -f 2 /dev/null || hostname, [host which ran configure])改成AC_DEFINE_UNQUOTED(VLC_COMPILE_HOST, hostname, [host which ran configure])GNU 环境下的 hostname 支持-f取 FQDNMSYS 自带的 hostname.exe 不支持-f参数会让命令返回错误。AC_DEFINE_UNQUOTED 会把这个值写进 config.h 作为 VLC_COMPILE_HOST不改不影响编译但生成的版本信息里会带一条诡异字符串。这个问题的隐蔽之处在于 configure 是交叉编译环境不会因为 hostname 失败中止。第三个是 extras/package/win32/configure.sh。在--disable-dirac行下面追加三行--hosti586-pc-mingw32msvc --with-contribcontrib/i586-mingw32msvc --disable-nls--host告诉 configure 我们是在给 32 位 Windows 目标生成代码--with-contrib把预编译 contrib 的 i586-mingw32msvc 目录暴露给 configure 的库探测--disable-nls先跳过 gettext 的多语言构建省掉一大批国际化和编码问题。想在产物里带中文语言包后期可以单独把 nls 打开重跑 configure不建议第一次就开。3.3 change_prefix.sh 执行时机与 libpng 软链接修复make prebuilt 完成后进入 contrib\i586-mingw32msvc 目录修改 change_prefix.sh在文件处理循环里加一行打印echo processing: $file这个脚本是跨平台的。在 macOS 上if 分支里的 otool 和 install_name_tool 用来改写 Mach-O 二进制里的动态库路径在 Windows/MSYS 上这两个命令不存在实际生效的是 elif 分支对扩展名是 .pc 和 .la 的文本文件做前缀替换。预编译包在其他机器上生成时库路径是写死的change_prefix.sh 做的事就是路径归一化。echo 那行加在 for 循环体开头只是让我们在长达一两小时的执行过程中能看到进度属于无副作用的安全修改。执行sh change_prefix.sh耐心等。期间如果出现mv: cannot move ./change_prefix.sh.tmp to ./change_prefix.sh: Permission denied属于 Windows 下临时文件被句柄占用的假阳性忽略即可中断了重跑一次 sh 会继续处理剩余文件。最后一步修复版本差异进入 contrib\i586-mingw32msvc\lib把 libpng15.a 和 libpng15.la 重命名为 libpng.a 和 libpng.la。原因是预编译包里的 libtool 按带版本号规则命名但 VLC 源码树里有模块的 Makefile 直接写-lpng链接器按 libpng15 找不到匹配项改名是为了让-lpng能命中。4. 编译实操bootstrap、configure 与打包前必须动的 Makefile环境补齐、源码文件改完终于进入真正的编译阶段。但别急着 make编译前还有一次文件准备以及两处 Makefile 修补否则 make 会在很后面才崩浪费几个小时。4.1 从 bootstrap 到 configure 的命令序列与参数编译源码之前要把一批可执行文件复制到 Msys\1.0\binGit.exe、moc.exe、rcc.exe、uic.exe、7z.exe或 zip.exe、msys-intl-8.dll其中 moc.exe、rcc.exe、uic.exe 这三个在源码树 contrib\i586-mingw32msvc\bin 目录下。复制完后把 contrib\i586-mingw32msvc\bin 下不带后缀的 moc、rcc、uic 三个文件改名为 moc1、rcc1、uic1。这个操作背后的逻辑是configure 生成的 Makefile 里写的是 Unix 风格无后缀的 moc、rcc、uic 命令而 Windows 下同目录同时存在无后缀文件和有后缀 .exe 文件时shell 的解析顺序会不确定。改名保留原文件让两边各司其职。都做完建议重启一次系统把 MSYS 进程持有的文件句柄锁清干净再往下走。正式命令序列cd /home/jb/vlc-2.0 PATH/home/jb/vlc-2.0/contrib/i586-mingw32msvc/bin:$PATH cd vlc ./bootstrap sh extras/package/win32/configure.sh第一条进入工作区第二条把 contrib 预编译库的 bin 目录提前到 PATH 最前面保证 configure 探测 Qt、glib 等库时能找到刚复制进来的 exe第三条进入源码根目录第四条执行 bootstrap 生成 configure 脚本第五条通过官方 win32 配置脚本跑 configure它内部已经带上 3.2 节加的三个参数。如果想追加自定义选项直接在 configure.sh 后面附加例如--disable-lua、--disable-upnp。--disable-lua在 Windows 构建里很实用2.0.4 的 Lua 扩展经常因为 Lua 头文件路径问题失败不做二次开发就关掉。--disable-upnp同理UPnP 的 SDK 探测很挑版本失败会导致 configure 阶段警告甚至中止。4.2 access 模块与根 Makefile 的四处修改configure 跑完后先别急着重启 make打开两个 Makefile 修补再编译。第一处modules/access/Makefile搜索DLOPEN_LDFLAGS并删除。2.0.4 的 access 模块 Makefile 里这个占位符没有对应的 configure 变量定义链接时 gcc 会把DLOPEN_LDFLAGS当一个输入文件名传给 ld报错No such file or directory。删掉后 access 模块的链接命令恢复干净。第二处根目录 Makefile 的package-win-common:目标一共四处修改。第一处是 sed 命令# 原sed -i.orig -e s%share/osdmenu%osdmenu%g -e s%/%\\%g $$file; \ # 改sed -e s%share/osdmenu%osdmenu%g -e s%/%\\%g $$file; \-i.orig表示原地修改并生成 .orig 备份但打包阶段输入的只读文件会触发Text file busy改用sed -e输出到标准流就绕开了这个权限问题。第二处是 manifest 路径# 原cp $(top_builddir)/npapi-vlc/npapi /npvlc.dll.manifest $(win32_destdir)/ # 改cp $(top_builddir)/npapi-vlc/npapi/package/npvlc.dll.manifest $(win32_destdir)/npvlc.dll.manifest 实际位于 npapi/package 子目录原路径少了一层。第三处是 gcc 运行时库的拷贝# 原cp $${gcc_lib_dir}/libstdc-6.dll $${gcc_lib_dir}/libgcc_s_sjlj-1.dll $(win32_destdir)/ ; true # 改cp /mingw/bin/libstdc-6.dll /mingw/bin/libgcc_s_sjlj-1.dll $(win32_destdir)/ ; truegcc_lib_dir这个变量在 2.0.4 的 Makefile 里没有赋值展开后是空串/mingw/bin是 TDM-GCC 在 MSYS 里的固定位置直接写死比猜变量稳。第四处是 activex SDK 文件# 原cd $(top_builddir)/npapi-vlc cp activex/README.TXT share/test.html $(win32_destdir)/sdk/activex/ # 改cd $(top_builddir)/npapi-vlc cp activex/README.TXT share/test/test.html $(win32_destdir)/sdk/activex/test.html 在源码树里的实际位置是 share/test/ 下的子目录。4.3 编译与打包make、package-win32 系列命令前面全部就位后执行make首次编译耗时很长日志刷屏是正常的。失败时先看第一条 error通常是某个模块的库路径不对。两个最常见的自救手段回到预编译 contrib 章节换最新包或者在 configure 阶段加--disable-upnp后make clean make。UPnP 检测是 2.0.4 在 Windows 上最容易挂的点没有硬需求就关掉。编译通过后打包命令按需求选命令产物适用场景make package-win32-commonvlc-x.x.x/ 目录自用、拷贝分发make package-win32-zipzip 压缩包网络分发make package-win32-7zip7z 压缩包网络分发make package-win32NSIS 安装程序需 NSIS 在默认安装位置make package-win32-common-debug带调试符号的目录gdb 调试注意 1.2 分支这些目标名略有变化运行grep : Makefile | grep package-win32看看当前 Makefile 实际提供了哪些目标再决定用哪个。5. 避坑指南路径、权限与链接问题的 5 条血泪经验整个流程我完整跑过好几遍下面这几条是每次换机器都会再犯的。每条按现象 → 原因 → 解决写照着排查即可。5.1 configure 报 cannot find libintl现象configure 进行到 gettext 检测时中断提示 libintl 找不到。原因gettext-runtime 没解压进 Msys\1.0\bin或者 msys.bat 里 PKG_CONFIG_PATH 指到了不存在的目录。解决重新解压 gettext-runtime_0.18.1.1-2 和 libiconv 对应版本到 Msys\1.0\bin确认 msys.bat 里的 set PKG_CONFIG_PATH 路径拼写正确。改完重开 msys.bat先执行pkg-config --list-all | grep glib确认能列出内容再继续。5.2 编译中段报 expected unqualified-id before small现象modules/access 等目录编译到某个 cpp 文件时突然崩掉。原因Windows 头文件里small被定义为宏展开后破坏了 VLC 源码里的合法变量名。解决确认 vlc_windows_interfaces.h 里#undef small加在#include objbase.h之后。顺序很重要宏要先定义再取消。5.3 change_prefix.sh 中途 Permission denied现象mv 临时文件到 change_prefix.sh 时失败脚本中断。原因Windows 文件被其他进程句柄占用或者杀毒软件扫描拦截了 rename 操作。解决假阳性忽略并重跑sh change_prefix.sh脚本会继续处理剩余文件。注意必须在 msys.bat 打开的窗口里执行在 cmd 里直接调 sh 的权限模型不对同样会触发该问题。5.4 package-win32-common 找不到 npvlc.dll.manifest 或 test.html现象make 进入打包阶段时报 manifest 文件不存在。原因打包脚本写的路径是旧目录结构。解决按 4.2 节的第 2、4 处修改。改完直接重跑make package-win32-common不会重新编译全部源码只重做打包阶段。5.5 username 以 u 或 x 开头时 config.h 的 VLC_COMPILED_BY 无效现象vlc.exe 能编译出来但版本信息乱码或启动异常。原因C 字符串里\u、\x是转义序列。configure 把用户名写进 VLC_COMPILED_BY 常量时没做转义处理编译器按转义符解析出了不可读字符。解决手工打开 config.h找到 VLC_COMPILED_BY把里面的单反斜杠全部改成双反斜杠\\保存后重新 make不用整个工程重来。注意MSYS 安装路径和用户目录不要有空格和中文。configure 里有大量路径拼接依赖 shell 分词空格会直接翻车。6. 验证产物与二次进阶确认编译成功后再裁剪6.1 产物验证与绿色版使用make package-win32-common 完成后源码目录下会出现 vlc-2.0.4 这样的子目录里面 vlc.exe、libvlc.dll、plugins 目录都在。第一件事是验证主程序./vlc.exe --version能看到版本号和编译时间就说明主程序正常。然后再看 plugins 目录里有没有上百个 .dll——VLC 的插件是按需加载的缺了某个 dll 编译时不会报错运行到对应功能才失败所以列表里文件的完整性比单个 exe 能否启动更重要。这个目录本身就是免安装版本拷到其他 Windows 机器直接运行 vlc.exe不写注册表。官方没有单独的 portable 包自编译的目录恰好可以当绿色版用这也是很多人自己走编译流程的直接动机。6.2 二次进阶调试版与裁剪调试用make package-win32-common-debug生成的目录保留符号文件在 MSYS 里跑gdb vlc.exe就能看到崩溃栈。裁剪则回到 configure 阶段追加--disable-lua、--disable-upnp等参数缩小插件体积不需要 Qt 界面就把 modules/gui/qt 整个排除掉依赖越少后续升级维护越省心。从那以后我每次编译 VLC都会强制走一遍先检查 config.h 的用户名转义、再跑 make package-win32-common、最后执行 vlc.exe --version这三步检查。改配置比改代码更容易翻车稳定复现比追求新版本重要。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →