ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Zstandard 的 CMake 构建指南:从零编译 libzstd 到 FetchContent 与库集成实践

Zstandard 的 CMake 构建指南:从零编译 libzstd 到 FetchContent 与库集成实践 Zstandard 的 CMake 构建指南从零编译 libzstd 到 FetchContent 与库集成实践【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit本指南以 zstd 1.5.7 官方 CMake 构建说明 为主体系统讲解 Zstandard 压缩库在 CMake 体系下的完整构建流程包括 out-of-source 与 in-source 两种构建方式、全部可配置构建选项、Apple Framework 打包、以及通过 FetchContent 将 libzstd 嵌入第三方项目的标准做法。读完本文你将掌握libzstd_static/libzstd_shared目标的由来与取舍并能像 Fluent Bit 一样把 zstd 作为静态子库集成进自己的工程。仓库中的 zstd 源码位于 lib/zstd-1.5.7CMake 构建入口为 build/cmake/CMakeLists.txt库目标定义在 build/cmake/lib/CMakeLists.txt。本文所有命令与路径均以该仓库为准。一、准备工作构建方式与目录约定zstd 的 CMake 工程不支持cmake clean这类清理命令CMake 本身也没有官方 clean 子命令因此官方 README 强烈推荐采用out-of-source源码外构建把构建产物、CMake 缓存全部放在独立目录中需要清理时直接删除该目录即可不会污染源码树。1.1 Out-of-source 构建推荐cd lib/zstd-1.5.7/build/cmake mkdir builddir cd builddir cmake .. makemkdir builddir新建独立构建目录cmake ..以build/cmake为源码目录生成构建系统make执行编译。清理缓存只需删除构建目录rm -rf build/cmake/builddir1.2 In-source 构建可选也可以在build/cmake目录内直接构建CMake 会就地生成缓存与产物cd lib/zstd-1.5.7/build/cmake cmake . make这种方式会把CMakeCache.txt、CMakeFiles/等中间产物写入源码目录之后若要彻底清理只能手动删除这些生成文件不如 out-of-source 方式干净故仅建议快速验证时使用。1.3 查看全部构建选项cd build/cmake/builddir cmake -LH ..-LH会列出当前工程所有可配置的 CMake 缓存选项L表示 listH表示 help包括选项名、类型、默认值与说明文字是快速了解 zstd 构建能力的最直接途径。从 build/cmake/CMakeLists.txt 源码可以看到顶层入口首先通过 GetZstdLibraryVersion.cmake 从 lib/zstd.h 中解析出版本号再以project(zstd VERSION ...)声明工程随后用option()逐一声明各开关。1.4 通过命令行开关配置选项布尔选项统一使用-D[option]ON/OFF语法传递cd build/cmake/builddir cmake -DZSTD_BUILD_TESTSON -DZSTD_LEGACY_SUPPORTOFF .. makeZSTD_BUILD_TESTS控制是否编译测试套件ZSTD_LEGACY_SUPPORT控制是否携带 v01~v07 旧格式解压支持详见下文选项表格。选项可多次叠加未指定的选项保持默认值。二、zstd CMake 构建选项全解析所有与库本身相关的选项集中定义在 build/cmake/lib/CMakeLists.txt 的option()声明中顶层 build/cmake/CMakeLists.txt 则负责工程级开关。核心选项整理如下选项默认值作用ZSTD_BUILD_STATICON是否构建静态库libzstd_staticZSTD_BUILD_SHAREDON是否构建共享库libzstd_sharedZSTD_BUILD_COMPRESSIONON是否编译lib/compress/压缩模块源码ZSTD_BUILD_DECOMPRESSIONON是否编译lib/decompress/解压模块源码ZSTD_BUILD_DICTBUILDERON是否编译lib/dictBuilder/字典构建模块ZSTD_BUILD_DEPRECATEDOFF是否编译lib/deprecated/已废弃 API 源码ZSTD_LEGACY_SUPPORTON是否支持 v01~v07 旧格式解压对应lib/legacy/zstd_v0*.cZSTD_MULTITHREAD_SUPPORTONAndroid 为 OFF多线程压缩支持编译时定义ZSTD_MULTITHREAD并链接 pthreadZSTD_BUILD_PROGRAMSON是否构建 zstd CLI 可执行程序ZSTD_BUILD_TESTS跟随BUILD_TESTING是否构建测试套件依赖静态库ZSTD_BUILD_CONTRIBOFF是否构建 contrib 下的贡献代码ZSTD_PROGRAMS_LINK_SHAREDOFFCLI 程序链接共享库而非静态库ZSTD_FRAMEWORKOFF仅 Apple 平台是否以 Apple Framework 形式打包库2.1 模块化编译按需裁剪源码从 lib/CMakeLists.txt 的实现可以看到库的源码集合是按模块动态拼装的common/与所有头文件始终参与编译打开ZSTD_BUILD_COMPRESSION才追加compress/*.c打开ZSTD_BUILD_DECOMPRESSION才追加decompress/*.c在 x86_64 且支持noexecstack时还会追加汇编文件huf_decompress_amd64.S否则定义ZSTD_DISABLE_ASM打开ZSTD_BUILD_DICTBUILDER才追加dictBuilder/*.c打开ZSTD_BUILD_DEPRECATED才追加deprecated/*.c打开ZSTD_LEGACY_SUPPORT才追加legacy/zstd_v01.c~zstd_v07.c七个历史版本源码。因此一个仅解压、无字典、无旧格式的精简 libzstd可以只保留commondecompress两个目录的源码显著减小二进制体积——这也是嵌入式与日志代理场景常用的裁剪手段。2.2 静态 / 共享二选一与 INTERFACE 别名目标lib/CMakeLists.txt中通过add_library(libzstd_shared SHARED ...)与add_library(libzstd_static STATIC ...)分别生成两个真实目标并根据选项组合额外生成一个INTERFACE 别名目标libzstd仅ZSTD_BUILD_SHARED时libzstd转发到libzstd_shared仅ZSTD_BUILD_STATIC时libzstd转发到libzstd_static两者都开启时由全局BUILD_SHARED_LIBS决定转发方向。同时无论静态还是共享库只要打开多线程支持ZSTD_MULTITHREAD_SUPPORT目标都会追加编译定义ZSTD_MULTITHREAD在 Unix 上链接${THREADS_LIBS}通过find_package(Threads)解析HP-UX 有专门的处理函数。MSVC 平台还会追加ZSTD_HEAPMODE0、_CRT_SECURE_NO_WARNINGS等定义并把静态库输出名改为zstd_static以避免与导入库冲突。2.3 顶层约束与 clean-all / uninstall 目标顶层 build/cmake/CMakeLists.txt 中有几处硬性约束值得注意想构建 zstd CLI 程序ZSTD_BUILD_PROGRAMSON必须先构建静态库或共享库 ZSTD_PROGRAMS_LINK_SHARED否则SEND_ERROR直接报错想构建测试套件ZSTD_BUILD_TESTSON同样必须存在静态库工程额外提供了clean-all自定义目标等价于make clean 删除构建目录与uninstall目标工程会生成并安装 CMake 包配置文件zstdConfig.cmake、zstdConfigVersion.cmakeSameMajorVersion兼容策略与带zstd::命名空间的zstdTargets.cmake并安装libzstd.pcpkg-config 文件供下游find_package(zstd)使用。三、Apple Framework 构建在 Apple 平台iOS/macOS上zstd 支持直接打包成Apple Framework形式便于 Xcode 工程引用。官方 README 建议iOS 派生平台尽量使用 CMake 3.14 以上版本此时可借助 CMake 内建 toolchain 能力直接交叉编译cmake -S. -B build-cmake -DZSTD_FRAMEWORKON -DCMAKE_SYSTEM_NAMEiOS若 CMake 版本低于 3.14则需借助第三方 iOS-CMake toolchain 文件配合 Xcode 生成器cmake -B build -G Xcode -DCMAKE_TOOLCHAIN_FILEPath To ios.toolchain.cmake -DPLATFORMOS64 -DZSTD_FRAMEWORKON从 lib/CMakeLists.txt 的实现看ZSTD_FRAMEWORKON会为目标设置FRAMEWORK TRUE、FRAMEWORK_VERSION、PRODUCT_BUNDLE_IDENTIFIERgithub.com/facebook/zstd与MACOSX_FRAMEWORK_IDENTIFIER等属性并关闭代码签名CODE_SIGNING_ALLOWED NOPUBLIC_HEADER指向lib/目录下的全部公共头文件最终 Framework 会随install目标安装到${CMAKE_INSTALL_LIBDIR}。四、通过 CMake FetchContent 集成到第三方工程对于不希望预先安装 zstd 的工程官方 README 推荐使用FetchContent在配置期自动下载并构建 libzstd。完整示例来自 READMEinclude(FetchContent) set(ZSTD_BUILD_STATIC ON) set(ZSTD_BUILD_SHARED OFF) FetchContent_Declare( zstd URL https://github.com/facebook/zstd/releases/download/v1.5.5/zstd-1.5.5.tar.gz DOWNLOAD_EXTRACT_TIMESTAMP TRUE SOURCE_SUBDIR build/cmake ) FetchContent_MakeAvailable(zstd) target_link_libraries( ${PROJECT_NAME} PRIVATE libzstd_static ) # On windows and macos this is needed target_include_directories( ${PROJECT_NAME} PRIVATE ${zstd_SOURCE_DIR}/lib )要点拆解set(ZSTD_BUILD_STATIC ON)/set(ZSTD_BUILD_SHARED OFF)必须在FetchContent_MakeAvailable之前设置因为选项在子工程project()阶段就被读取SOURCE_SUBDIR build/cmake指示 FetchContent 以build/cmake为实际 CMake 源码根zstd 仓库根目录下还有 Makefile 构建体系CMake 入口在build/cmake链接目标名libzstd_static来自 lib/CMakeLists.txt 中的add_library(libzstd_static STATIC ...)若同时构建共享库也可链接libzstd_shared或直接链接 INTERFACE 别名libzstdWindows 与 macOS 上需要手动补充target_include_directories指向${zstd_SOURCE_DIR}/lib这是因为静态目标仅通过$BUILD_INTERFACE:...暴露头文件路径跨平台传递并不总是可靠。若选择先安装 zstd 再以find_package(zstd)使用则依赖上一步生成的zstdConfig.cmake与zstd::命名空间导出目标见 zstdConfig.cmake.in 与顶层 CMakeLists 的install(EXPORT zstdExports ...)。五、仓库实战Fluent Bit 如何静态集成 libzstd本仓库Fluent Bit正是把 zstd 作为第三方静态子库集成的典型实例其集成方式与上文 FetchContent 思路一致但改用了随源码一起 vendored 的 add_subdirectory 方案。Fluent Bit 的 zstd 接入配置位于 cmake/zstd.cmake# zstd cmake set(ZSTD_BUILD_STATIC ON) set(ZSTD_BUILD_SHARED OFF) set(ZSTD_BUILD_COMPRESSION ON) set(ZSTD_BUILD_DECOMPRESSION ON) set(ZSTD_BUILD_DICTBUILDER OFF) set(ZSTD_BUILD_DEPRECATED OFF) include_directories(${FLB_PATH_ROOT_SOURCE}/${FLB_PATH_LIB_ZSTD}/lib) add_subdirectory(${FLB_PATH_LIB_ZSTD}/build/cmake EXCLUDE_FROM_ALL) set(LIBZSTD_LIBRARIES libzstd_static)该文件展示了 zstd 各选项在真实项目中的裁剪策略只构建静态库ZSTD_BUILD_STATICON、ZSTD_BUILD_SHAREDOFF避免引入动态库部署负担压缩、解压模块全开关闭字典构建ZSTD_BUILD_DICTBUILDEROFF与废弃模块ZSTD_BUILD_DEPRECATEDOFF控制体积通过include_directories将 lib/zstd-1.5.7/lib 加入头文件搜索路径用add_subdirectory(... EXCLUDE_FROM_ALL)挂载 zstd 子工程EXCLUDE_FROM_ALL保证只构建被显式依赖的目标最终将链接目标统一记为LIBZSTD_LIBRARIESlibzstd_static供上层使用。zstd 在 Fluent Bit 中的实际调用位于 src/flb_zstd.cflb_zstd_compress()通过ZSTD_compressBound()预分配缓冲区后调用ZSTD_compress()flb_zstd_uncompress()先用ZSTD_getFrameContentSize()判断帧大小未知大小时走ZSTD_decompressStream()流式解压缓冲区从 64 KB 起步、按 2 倍扩容并设有 100 MB 上限保护相关封装被 src/flb_compression.c、src/flb_http_common.c 与 src/aws/flb_aws_compress.c 复用用于 HTTP 报文压缩与 AWS 数据压缩等场景。可见裁剪选项 静态链接 封装 API正是大型 C 项目集成 zstd 的标准姿势。六、为 zstd 贡献 CMake 配置风格规范zstd 官方欢迎社区向build/cmake贡献配置改进并提出了明确的CMake 代码风格约定详见 README CMake Style Recommendations 一节主要包含三条6.1 正确缩进所有块体以下命令的块体必须正确缩进if/else/endifforeach/endforeachwhile/endwhilemacro/endmacrofunction/endfunction缩进使用空格推荐 2、3 或 4 个与文件其余部分保持一致禁止使用 Tab。6.2 大小写规范最重要的一条是同一文件内保持大小写风格一致。整体上优先采用全小写风格。推荐写法add_executable(foo foo.c)不推荐写法ADD_EXECUTABLE(bar bar.c) Add_Executable(hello hello.c) aDd_ExEcUtAbLe(blub blub.c)同时 README 也提示命名习惯应匹配现代 CMake2.6 及以上惯例——命令用小写、变量用大写。6.3 空参数结束命令为提升可读性endforeach()、endif()、endfunction()、endmacro()、endwhile()一律使用空参数写法else()同样留空推荐if(FOOVAR) some_command(...) else() another_command(...) endif()不推荐在结尾重复变量名if(BARVAR) some_other_command(...) endif(BARVAR)七、小结围绕 zstd 1.5.7 的 CMake 构建文档本文完整覆盖了out-of-source 与 in-source 两种构建流程、cmake -LH查看选项、-D开关配置、全部构建选项的语义与源码级来源、Apple Framework 打包、FetchContent 集成范式以及以 Fluent Bit 为代表的 vendored 静态集成实战。无论你是要单独编译 zstd CLI、按需裁剪 libzstd 模块还是在自己的 CMake 工程中嵌入 zstd都可以直接参考文中的命令与选项表后续若计划向 zstd 贡献 CMake 改动请务必遵守第六节的风格规范。【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表