Carla 0.9.15源码编译中zlib-1.2.13的安装与对接全攻略
简介面向Carla 0.9.15仿真平台开发者的zlib 1.2.13编译压缩包解决在Carla项目中快速获得数据压缩/解压缩库支持的问题也可作为学习zlib源码与构建流程的样例。压缩包类型为zip仅1.61MB共247个文件既有C/C源码(.c/.h/.cpp)和Visual Studio工程文件(.vcxproj/.sln)也包含.configure、Makefile等跨平台构建脚本以及Ada语言绑定文件(.adb/.ads)方便在Windows/Linux等环境直接使用或重新编译。目前已有374人学习浏览适合Carla开发者以及需要为仿真环境集成压缩功能的工程师。整包将预先编译好的zlib、完整源码、构建工程和文档集中打包省去自行收集与编译的麻烦其中还带有命令行解压工具与手册页既能作为Carla项目的现成依赖也能帮助理解zlib在Windows/Linux下的编译集成方式与调用细节。 最近在折腾 Carla 0.9.15 的源码编译卡了几天之后发现真正让我反复返工的居然不是 UE4 的构建过程而是依赖链里一个不起眼的小包zlib-1.2.13.zip。zlib 是几乎所有 C/C 项目都会碰到的压缩库Carla 在数据记录、传感器流处理和部分通信逻辑里都会用到它官方在第三方依赖列表里也把它列成了必选项。如果你打算在 Windows 或 Linux 下自己编译 Carla而不是直接下载官方 release 包那你迟早要和这个文件打交道。这篇文章把我编译 zlib-1.2.13.zip 并接入 Carla 0.9.15 的过程、遇到的问题和解决办法完整梳理一遍适合正在编译 Carla、做自动驾驶仿真二次开发或者想搞明白 CMake 怎么找第三方库的朋友参考。1. 为什么Carla 0.9.15编译会卡在zlib上1.1 zlib在Carla的构建链里到底干什么很多刚开始接触 Carla 的人会有一个误区Carla 是基于 UE4 的那压缩相关的库应该由 UE4 自己带好了。事实是UE4 确实自带了一份 zlibCarla 的 LibCarla、RPC 通信层以及 Recorder 回放系统也会单独引用一份 zlib。也就是说整个构建链里会同时出现两份 zlib一份给引擎用一份给 Carla 自身模块用。Carla 0.9.15 的构建脚本期望的第三方库版本就是 zlib-1.2.13如果系统里只有旧版或者你从网上下了一个源码包但没编译成正确的库文件后续会在链接阶段冒出一堆奇怪错误。从实际用途来看zlib 在 Carla 里承担的工作大概有三块一是 Recorder 录制回放时对世界状态做压缩录制文件可以小很多二是传感器数据在跨进程或跨机器传输前的压缩处理三是 RPC 协议栈里部分数据帧的压缩逻辑。这些场景对压缩率没有极致要求但要求库稳定、跨平台行为一致所以 Carla 没有自己造轮子直接选了 zlib。1.2 为什么偏偏是1.2.13这个版本zlib 的版本演进非常慢1.2.11 用了很多年一直到 2022 年才推出 1.2.12。但 1.2.12 发布后不久又暴露出 deflate 相关的边界问题于是 zlib 官方在同年补发了 1.2.13。Carla 0.9.15 把 zlib-1.2.13 作为第三方依赖大概率是看重它同时兼顾稳定性和安全性。如果你是从更老的 Carla 版本迁移过来的比如之前用 0.9.13 或 0.9.14项目里可能已经缓存了老版本的 zlib。这时候不要直接沿用旧库Carla 的 CMake 脚本里如果写明了 ZLIB_VERSION_STRING版本不匹配会有警告虽然有时不会直接失败但这种半新半旧的组合最容易出隐蔽问题。我自己踩过一次deflateInit_调用正常但压缩出来的数据用新版解压库却解不开最后发现就是老版本 zlib 的 ABI 兼容性问题。1.3 什么时候需要自己编译zlib如果你只是把 Carla 当工具用直接从官方下载编译好的 release 包Setup 脚本会自动拉取第三方依赖根本不需要手动碰 zlib。需要手动编译的场景通常有以下几种公司或实验室有离线构建环境不能访问官方预编译包下载地址需要把依赖提前准备好。你对 Carla 做了源码级修改需要完整从源码编译并且希望所有第三方库的版本都由自己控制。官方下载的预编译 zlib 和你本机的编译工具链不兼容比如 Windows 下官方包用的是某个 MSVC 版本而你的 UE4 是用另一个工具链编译的。你需要对 zlib 做 patch或者想把它静态链接进最终产物避免运行时 DLL 缺失。我的建议是除非纯离线环境必须手动编译否则优先用官方预编译包能省不少事。但无论哪种方式理解 zlib 怎么编译、怎么被 Carla 找到遇到问题都能少走弯路。2. 编译前准备源码包内容与目录规划2.1 打开zlib-1.2.13.zip后你会看到什么zlib-1.2.13.zip 解压后核心源码文件是adler32.c、compress.c、crc32.c、deflate.c、inflate.c、zutil.c这些头文件最关键的是zlib.h和zconf.h。除此之外里面还有 CMakeLists.txt、configure 脚本、makefile 等构建入口。很多人拿到 zip 后直接把它当作“源码包”这是对的但要注意 zlib 本身不提供 CMake 的find_package配置文件即没有zlib-config.cmake所以 Carla 那边通常是通过find_package(ZLIB)来找 zlib 的。如果你想手动指定路径不能用CMAKE_PREFIX_PATH指向一个目录就完事还需要让ZLIB_INCLUDE_DIR和ZLIB_LIBRARY这两个变量能被正确找到。2.2 不同平台的构建产物差异这是很多人容易搞混的地方。zlib 在不同平台、不同构建方式下生成的库文件名不一样。平台构建方式静态库名动态库名备注WindowsCMake MSVCzlibstatic.libzlib1.dll导入库是 zlib.libWindows官方 Makefile.msczlib.libzlib1.dll早期脚本路径较少用到Linuxconfigure makelibz.alibz.so系统默认名称是 libzLinuxCMakelibz.a / libzstatic.alibz.so取决于 BUILD_SHARED_LIBSmacOS任意方式libz.alibz.dylib和 Linux 类似Carla 的 CMake 在 Windows 上默认倾向于找zlib.lib而这个文件只有在 CMake 构建动态库时才会以“导入库”形式出现。如果你只编译了静态库zlibstatic.lib需要显式把库路径告诉 Carla否则很容易出现“找到了头文件但链接时找不到库”的情况。2.3 接入Carla的三种方式接入方式取决于你是用 Setup 脚本走官方流程还是自己手动配置 CMake。第一种是“替换官方预编译包”。Carla 源码里的Util/DownloadPrebuilt.py会维护一张依赖下载表里面记录了第三方库的下载地址。离线环境下可以把 zlib-1.2.13.zip 放到本地路径把这张表里的 URL 改成file:///...的形式Setup 脚本就能按原流程解压不需要改动其他构建脚本。第二种是“手动指定 CMake 路径”。如果你已经编译好了 zlib并且希望 Carla 构建时直接使用你指定的版本可以在 Carla 的 CMake 配置阶段传入-DZLIB_ROOT...或-DCMAKE_PREFIX_PATH...同时在ZLIB_INCLUDE_DIR和ZLIB_LIBRARY上做精确指定。第三种是“把构建产物直接铺进 Carla 的第三方目录”。Carla 源码里通常会有类似ThirdParty/或Util/InstallersA/的目录你可以把 zlib 的头文件和库文件按“include/lib”结构放进去让构建脚本自动发现。这种方式最接近官方预编译包的使用方式但对目录结构要求比较严格放错位置会直接找不到。3. Windows下编译zlib-1.2.13并接入Carla的完整流程3.1 用CMake生成VS工程并编译Windows 下推荐用 CMake 而不是直接跑 nmake。原因很简单CMake 能生成你当前已安装的 VS 版本对应的工程并且可以通过-A x64明确指定架构避免 32 位和 64 位库混用的问题。先打开“x64 Native Tools Command Prompt for VS2019”或 VS2022看你的 UE4 工具链要求解压 zlib 源码后进入目录执行cmake -S . -B build -A x64 -DCMAKE_INSTALL_PREFIXD:/carla-thirdparty/zlib-1.2.13 -DCMAKE_BUILD_TYPEReleaseCMAKE_INSTALL_PREFIX非常重要它决定install阶段把头文件安装到哪里。如果你希望后续被 Carla 找到建议把这个路径设成一个带有明显版本标识的独立目录不要直接 C 盘默认路径。然后编译并安装cmake --build build --config Release --target install执行完成后D:/carla-thirdparty/zlib-1.2.13下面会出现 include 和 lib 两个目录。include 里是zlib.h、zconf.hlib 里则根据你在 CMake 中是否开启BUILD_SHARED_LIBS而有不同产物。3.2 静态库还是动态库这是 Windows 编译 zlib 时最核心的一个选择。如果你希望最终 Carla 运行时不用拷贝 DLL或者你是在做封闭场景的二次开发建议使用静态库。生成静态库的方式是在配置时指定-DBUILD_SHARED_LIBSOFF产物会是zlibstatic.lib。但要注意Carla 某些模块在查找库时可能仍然寻找zlib.lib这个名字一个笨办法是编译完成后把zlibstatic.lib复制一份改名成zlib.lib。这个操作不优雅但确实有效。如果你选择动态库CMake 配置时保持BUILD_SHARED_LIBSON最终会生成zlib1.dll和导入库zlib.lib。这种情况下运行时zlib1.dll必须能被系统找到。我建议把 DLL 拷贝到 Carla 最终可执行文件目录或者在环境变量 PATH 中加入对应目录否则 Carla 能构建成功但启动时会报“找不到 zlib1.dll”。从稳定性的角度我更推荐静态库。Carla 本身模块很多动态库版本冲突一旦出现排查成本远高于编译时的链接错误。3.3 让Carla的构建系统找到这套zlib编译好 zlib 只是第一步关键是怎么让 Carla 0.9.15 用上它。如果你走的是 Setup 脚本流程最简单的办法是修改Util/DownloadPrebuilt.py把 zlib 下载项替换成本地文件# 原内容类似 zlib_url https://some-server/zlib-1.2.13.zip zlib_url file:///D:/carla-thirdparty/zlib-1.2.13.zip这样 Setup 解压时会把你手动准备的 zip 包当成官方包处理。但前提是你的 zip 包内部目录结构和官方预编译包一致通常是解压后直接是 include、lib 等目录。如果你只是把官方源码包放上去Carla 找不到编译好的库文件依旧会报错。如果你是直接通过 CMake 构建 Carla可以传参cmake -S . -B build -DZLIB_ROOTD:/carla-thirdparty/zlib-1.2.13 -DZLIB_LIBRARYD:/carla-thirdparty/zlib-1.2.13/lib/zlib.lib -DZLIB_INCLUDE_DIRD:/carla-thirdparty/zlib-1.2.13/includeZLIB_ROOT是一种快捷指定但不同 CMake 版本对ZLIB_ROOT的识别程度不同最稳妥的还是把ZLIB_LIBRARY和ZLIB_INCLUDE_DIR两个变量显式传进去。传错一个变量不至于编译失败但链接时会非常痛苦。3.4 写个最小测试程序验证在被 Carla 折腾之前我习惯先写一个最简单的程序验证 zlib 是否可用。新建一个test_zlib.cpp#include zlib.h #include cstdio int main() { z_stream strm {}; if (deflateInit(strm, Z_DEFAULT_COMPRESSION) ! Z_OK) { return 1; } printf(zlib version: %s\n, zlibVersion()); deflateEnd(strm); return 0; }Windows 下用 VS 的 cl 命令编译cl test_zlib.cpp /I D:/carla-thirdparty/zlib-1.2.13/include /link /LIBPATH:D:/carla-thirdparty/zlib-1.2.13/lib zlib.lib能输出zlib version: 1.2.13说明库和头文件版本一致链接正常。这个版本号验证一定要做很多奇怪问题就出在“头文件是 1.2.13库文件却是 1.2.11”这种版本错位上。4. Linux下用zlib源码编译并接入Carla4.1 系统自带libz和源码编译怎么选Ubuntu 等 Linux 发行版默认会带libz-dev或者zlib1g-dev很多场景下直接用系统库就够了。但 Carla 源码编译有两个特殊要求一是版本要精确到 1.2.13系统源里的版本不一定匹配二是 Carla 通常希望第三方库放在自己源码目录下形成“可控、可复现”的构建环境。如果你只是跑最新的 Ubuntu LTS用系统的 libz 也许能过但一旦你的 Carla 是定制分支或者需要在多个机器上复现同一构建系统库的差异就会被放大。所以我更推荐在 Carla 的源码树下单独编译一份 zlib并固定路径。这样无论是切换分支还是迁移构建机都不受影响。4.2 configure/make方式编译与安装zlib 源码自带的 configure 脚本在 Linux 下非常稳定。解压后进入目录依次执行./configure --static --prefix/opt/carla-thirdparty/zlib-1.2.13 make -j$(nproc) make install--static会生成静态库libz.a--prefix指定安装目录。这样make install后/opt/carla-thirdparty/zlib-1.2.13下会有 include 和 lib 目录。如果你不确定系统里是不是已经有另一个 zlib 在“捣乱”可以用下面命令查看链接器会找到哪个ldconfig -p | grep libz如果发现系统里存在多个libz.so就需要格外小心 Carla 的CMAKE_PREFIX_PATH是否真的指向你刚安装的目录否则链接器很可能优先去找系统路径下的库。4.3 CMake方式编译与集成Linux 下同样可以用 CMake 编译 zlib这种方式和 Windows 流程更接近也更容易让 Carla 的 CMake 逻辑识别cmake -S . -B build -DCMAKE_BUILD_TYPERelease -DCMAKE_INSTALL_PREFIX/opt/carla-thirdparty/zlib-1.2.13 cmake --build build -j$(nproc) cmake --install build然后配置 Carla 时传入cmake -S . -B build -DCMAKE_PREFIX_PATH/opt/carla-thirdparty/zlib-1.2.13如果你希望 Carla 一定使用静态 libz.a可以额外指定-DZLIB_LIBRARY/opt/carla-thirdparty/zlib-1.2.13/lib/libz.a。不过要注意Carla 依赖链里还有其他库如果它们是在动态库模式下编译的强制静态链接 zlib 可能会导致-fPIC相关报错。遇到这类问题可以在编译 zlib 时加CFLAGS-fPIC也可以认命改用共享库看具体需求了。Linux 下编译 zlib 整体比 Windows 省事真正的坑往往不在 zlib 本身而在 Carla 构建系统的第三方库搜索顺序上。我的经验是少用环境变量多用 CMake 变量的显式指定这样每次构建的可复现性都更高。5. 常见问题与排查技巧实录5.1 经常碰到的几个报错速查把我在 Windows 和 Linux 两套环境下遇到的典型问题整理成一张速查表以后碰到可以直接对号入座。报错信息可能原因解决办法Could NOT find ZLIB (missing: ZLIB_LIBRARY)库路径没传给 CMake或只传了 include显式设置ZLIB_LIBRARY指向实际 lib 文件unresolved external symbol deflateInit_头文件和库版本不匹配或链接顺序错误确认都指向 1.2.13把 zlib 放到链接参数末尾cannot find -lzLinux 下找不到libz.so或libz.a确认安装路径并在CMAKE_PREFIX_PATH指定运行时提示缺少zlib1.dll动态库编译后未拷贝到可执行目录拷贝 DLL 到 Carla 输出目录或用静态库deflateInit_ failed但链接和编译都通过库版本和头文件版本不一致用zlibVersion()验证实际链接到的库版本libz.a: error adding symbols: File format not recognized32 位和 64 位库混用统一用-A x64或-m64重新编译5.2 关于“多个zlib副本”的链接污染这是 Carla 编译里最具迷惑性的问题。前面提到UE4 自带一份 zlibCarla 又依赖一份 zlib如果两份库同时进入链接阶段会发生“链接污染”。最常见的现象是编译正常CMake 也报告找到了 zlib但运行时数据压缩表现异常比如 Recorder 写的文件无法被回放或者传感器数据流偶发损坏。排查思路是先确认最终可执行文件到底链接了哪个 zlib。Windows 下可以用 dumpbindumpbin /imports CarlaUE4.exe | findstr zlibLinux 下更好查ldd CarlaUE4 | grep libz如果你发现自己编译的 zlib 根本没被链接进去那说明 Carla 实际使用的是 UE4 内置的旧版本。这种情况下解决办法不是去改 UE4而是调整链接顺序让 Carla 自己的第三方库优先。具体操作往往是在 Carla 的 CMakeLists 里把 zlib 的 target 放在依赖列表底部让链接器在解析符号时才认到你的库。5.3 我排查第三方依赖的固定顺序最后分享一个我排查这类第三方依赖问题的固定顺序。第一步确认版本。先用cmake --find-package或者直接写个小程序输出zlibVersion()确保编译器和链接器用的是同一个 1.2.13。第二步确认路径。把 CMakeCache.txt 里所有含 zlib 的变量都看一遍重点看ZLIB_LIBRARY和ZLIB_INCLUDE_DIR是否有残留旧路径。第三步确认架构。Windows 下最容易犯的错是用 64 位 Carla 搭配 32 位 zlib链接阶段各种怪错。第四步确认运行依赖。动态库编译时DLL 是否在 PATH 或目标目录。这套顺序在 0.9.15 上帮我解决了不少问题。很多人一遇到编译报错就怀疑 Carla 代码出问题其实基础库版本不对才是最常见的坑。如果你正被某个第三方库卡住不妨先从 zlib 开始排查这种最底层的小库一旦出问题后面的构建过程每一步都会很别扭。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →