简介:CMake 3.24.0 源码包面向C/C++开发者与构建系统研究者,是一份跨平台开源构建工具资源。它解决多编译器、多平台环境下项目构建文件难以统一的问题,尤其适合需要从源码定制安装CMake,或想深入理解其内部模块与编译流程的读者。压缩包共收录2000个文件,总大小9.91MB;文件类型以txt说明文档、cmake模块、rst文档、c/cxx/cpp/h/hpp等源码为主,并包含大量测试用例、构建脚本与配置文件,目录结构清晰,便于按模块检索。目前已有426人学习下载。从内容预览可见,包内覆盖zstd压缩、libarchive归档、nghttp2会话等第三方依赖模块;丰富的.cmake与C++代码也可帮助读者掌握CMakeLists编写、模块扩展、语法分析及测试框架组织方式,适合作为深入研读和二次开发的完整源码包。
1. 拿到 cmake-3.24.0.tar.gz,先别急着解压
看到一个cmake-3.24.0.tar.gz安装包,很多人的第一反应是tar -zxvf解压然后./configure && make && make install三连。这套流程对大多数开源软件没问题,但 CMake 自己是个特殊的存在——它不仅要编译出来,还要能在后续的构建环境里被反复调用。如果你的工作流是「下载-解压-编译-装完收工」,那 3.24.0 这个版本号大概率会让你少走点弯路,但也可能让你在装完后发现系统里同时躺着三四个不同版本的 CMake,哪个先被 PATH 命中完全看运气。
这篇笔记不聊虚的,核心就三件事:3.24.0 到底带回了什么值得你手动编译的新能力,从源码把它装到自定义前缀的完整步骤与参数取舍,以及我在多套环境里踩过的坑——尤其是那些让cmake --version显示的版本和你预期完全不符的玄学时刻。我用的方案不一定是最优解,但每一条都是拿实际构建任务验证过的。
2. 为什么要自己编译 CMake 3.24.0:版本选型先想清楚
2.1 系统包管理器里的 CMake 为什么不够用
先别急着折腾源码包。你需要先确认一个事实:你的系统包管理器里有没有 CMake,装的是哪个版本。Ubuntu 20.04 自带的 CMake 是 3.16.3,CentOS 8 是 3.20.2,Debian 11 是 3.18.4。这些版本日常编个小项目问题不大,但一旦遇到下面这些场景就会翻车:
- 项目里用了
cmake_minimum_required(VERSION 3.21),而系统是 3.16,直接报CMake 3.16.3 does not exist或Compatible CMake version not found; - 需要
FindPython3的Python3_EXECUTABLE缓存变量语义变化,旧版本拿到的是损坏的路径; - 想用 preset 文件(
CMakePresets.json)做 CI 和本地构建的配置统一,这个特性要到 3.19 才引入,3.21 才完整支持include和condition; - 编译器是 AppleClang 12 或 Intel oneAPI,旧 CMake 的编译器检测逻辑根本不认识它们。
说到底,CMake 本身是构建工具链的地基,地基版本太老,上面的项目再新也跑不顺。3.24.0 属于 3.24 系列的第一个正式版,在稳定性和新特性之间取了个中间值:它把cmake --fresh这种断开缓存重配的方式正式扶正,也补了不少对 Clang 15、GCC 12 的识别规则。为了某个特定项目去编译一个旧版本,不如直接上 3.24 这条线。
2.2 3.24.0 本身带来了什么:三个值得手动装的理由
3.24.0 不是那种改动翻天覆地的版本,但它有几个变化直接影响了日常构建习惯。最值得提的是预设文件里支持了environment字段的展开——这听起来不算什么,但配合 IDE 和 CI 配置文件,能在不改CMakeLists.txt的前提下把环境变量按构建类型切分。其次是file(GENERATE)的输出现在可以写到构建目录之外的绝对路径了,我之前为了把生成的配置头文件放到源码树里,得写一堆COPY_ONLY和configure_file的绕路脚本,3.24 直接给堵上了这个口子。
再有一个在 AI 推理框架落地时特别有用的变化:对 CUDA 的--expt-relaxed-constexpr支持更稳了。搞过算子编译的人都知道,NVCC 的 constexpr 展开历来就是坑,旧 CMake 需要人肉给CUDA_NVCC_FLAGS加参数,3.24.0 让CMAKE_CUDA_STANDARD和 relaxed constexpr 的配合顺了不少。对于做视觉模型部署、想把颜色转换或归一化直接写进 CUDA kernel 的工程来说,这一个理由就够换版本了。
2.3 从源码编译的适用边界:什么时候别自己 build
自己编译 CMake 不是万能的,我见过最典型的翻车场景是嵌入式交叉编译环境的宿主机。比如你用的是某个国产 RISC-V 工具链,它的sysroot里自带了一份老版本 CMake,而你的构建脚本又依赖宿主机的 CMake 去解析CMAKE_SYSROOT。这种情况盲目编个 3.24 装到/usr/local反而会干扰工具链自己的查找逻辑,因为编译器检测脚本会优先用CMAKE_C_COMPILER指向的编译器去跑检测程序,不认你新装的 CMake。
还有一类场景是自己编译划不来:你只需要用 CMake 的--build命令去驱动 Ninja 或 Make,不需要任何新特性,系统包管理器里的版本完全够用。源码编译有它自己的维护成本——新版本意味着新特性,但新特性往往会和旧项目里的某些写法冲突,比如 3.24 开始对add_custom_command的输出路径检查更严格,以前能蒙混过关的相对路径,新版直接报错。做好"装完可能要回头修项目"的心理准备,再动手。
3. 本地编译安装 CMake 3.24.0:完整步骤与参数详解
3.1 前置依赖与最小命令
在动手之前,先把编译工具链准备好。CMake 的源码包自身依赖 C++ 编译器和标准库,常见发行版默认都带。缺的话先补上:
# Debian/Ubuntu 系 sudo apt-get update && sudo apt-get install -y build-essential libssl-dev # 如果需要编译 CMake 自带的 ccmake 图形界面,还需要 ncurses sudo apt-get install -y libncurses-devlibssl-dev不是 CMake 编译的硬依赖,但它关系到 CMake 的curl组件能否正常启用 HTTPS 支持。如果你的构建流程经常用到file(DOWNLOAD)去拉远程文件,建议还是装上,否则下载大文件时会退化成不支持 HTTPS 的通道。
接下来进入解压和配置环节:
tar -zxvf cmake-3.24.0.tar.gz cd cmake-3.24.0 ./bootstrap --prefix=/opt/cmake-3.24.0 --parallel=8bootstrap是 CMake 源码包特有的配置脚本,它做的事情是先编译一个最小版本的 CMake,再用这个 CMake 去配置完整的构建。这里--prefix指定安装前缀,我一般不用/usr/local,而是单独建一个/opt/cmake-3.24.0目录,这样多个版本共存时切换方便,直接改PATH就行。--parallel=8控制 bootstrap 阶段的并行编译任务数,8 是保守值,机器核多可以调高到 16 或 32,注意内存别被占满就好。
3.2 正式构建与安装的两种姿势
bootstrap 跑完之后,源码目录里会生成一个能用的Makefile,之后就是常规流程:
make -j8 sudo make installmake -j8的-j参数和 bootstrap 里的--parallel不是一回事。前者是 Make 自己的并行编译参数,后者是 CMake 配置阶段内部执行 try-compile 时的并行度。如果两者不一致,比如 bootstrap 用了--parallel=32但 make 只给-j4,配置阶段生成的构建系统会按 4 线程跑,不会自动继承 bootstrap 的值。
另一种姿势是让 CMake 自己编自己,也就是用系统已有的 CMake 去配置这个源码包。如果你的系统 CMake 版本不太老,这种方法更可控,因为你可以显式指定生成器(比如 Ninja):
# 确保系统里已有 cmake cmake --version # 在源码目录外单独建 build 目录,保持源码树干净 cd cmake-3.24.0 mkdir -p build && cd build cmake .. -DCMAKE_INSTALL_PREFIX=/opt/cmake-3.24.0 \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_USE_OPENSSL=ON cmake --build . --parallel 8 sudo cmake --install .我通常推荐第二种。原因很简单:./bootstrap的过程是个黑匣子,它内部做了什么编译器检测、缓存了什么变量,出了问题不好排查。而用现有 CMake 配置新 CMake,生成的CMakeCache.txt是明文可读的,任何配置项都能直接grep到。另外,CMake 3.24 对自身项目的构建脚本也做了模块化重构,用 Ninja 生成器编译时,增量编译速度快得多——改个文档或脚本,二次构建基本秒完成。
3.3 三个关键配置参数的取舍
编译 CMake 本身时可调的参数不算多,但有几个直接影响使用体验。
第一个是CMAKE_BUILD_TYPE。默认是空字符串,等价于无优化版本。我一般设成Release,因为 CMake 自身的运行性能在 Release 下明显更好,尤其是处理超大 CMakeLists 项目时,解析和生成速度能快 20%-30%。需要注意 Debug 版的 CMake 对某些编译警告更严格,但日常用不到,只会拖慢速度。
第二个是CMAKE_USE_OPENSSL。这个开关决定 CMake 内嵌的curl组件是否支持 HTTPS。如果你不开它,file(DOWNLOAD)遇到https://链接会直接失败。有些发行版会把 CMake 的 curl 支持拆成动态库,但源码编译默认不启用,需要你在配置时手动打开。装上libssl-dev或者openssl-devel之后再开这个选项,基本零成本。
第三个是CMAKE_BUILD_PARALLEL_LEVEL,环境变量,不需要在配置时写死。它在cmake --build阶段被读取,指定构建时的并行任务数。设成8对大多数机器是安全的,设成0表示用 CPU 核心数。建议把它写进你的构建脚本或 shell profile,这样每次cmake --build都不用敲--parallel,也不会因为忘了加而陷入单线程编译。
4. 安装之后的路径规划:多个 CMake 版本怎么共存
4.1 不覆盖系统 CMake 的软链方案
如果你按我前面的做法装到了/opt/cmake-3.24.0,接下来关键一步是把它变成默认命令行入口。我见过太多人直接把/usr/bin/cmake替换掉,结果系统里那些依赖老版本 CMake 的软件包在下次升级时全崩了。正确做法是软链:
sudo ln -s /opt/cmake-3.24.0/bin/cmake /usr/local/bin/cmake sudo ln -s /opt/cmake-3.24.0/bin/ctest /usr/local/bin/ctest sudo ln -s /opt/cmake-3.24.0/bin/cpack /usr/local/bin/cpack/usr/local/bin在默认PATH里通常排在/usr/bin前面,所以软链能生效。这样做的好处是系统升级时不会把你的 CMake 覆盖掉,也不用担心apt或yum的依赖检查抱怨版本冲突。坏处是软链指向的版本如果被你删了,/usr/local/bin/cmake就悬空了,所以升级版本前记得先删旧软链。
如果你连/usr/local/bin都不想动,可以用环境变量:
export PATH=/opt/cmake-3.24.0/bin:$PATH把这个写进~/.bashrc或~/.zshrc,只对当前用户生效。多版本切换时,直接改这一行里的路径就够了。
4.2 验证安装结果与构建环境的联动
装完必须先验证,不能只看cmake --version就完事。因为它输出的版本号可能来自缓存、环境变量或者软链指向的任意一层。我的验证套路分三步:
# 第一步:版本号 which cmake && cmake --version # 第二步:确认 cmake 的可执行文件实际路径 ls -l $(which cmake) # 第三步:验证 CMake 自带的模块能被正确找到 cmake --system-information | grep -E "CMAKE_ROOT|CMAKE_MODULE_PATH"CMAKE_ROOT这个变量很关键。它指向 CMake 安装目录下的share/cmake-3.24目录,所有内置的FindXXX.cmake模块都放在那里。如果你在安装时用了奇怪的--prefix导致目录结构不完整,CMAKE_ROOT会指向一个不存在的路径,后果是任何使用了find_package()的项目都报Could NOT find错误,而你完全想不通为什么系统里明明装了库。
4.3 项目里锁定 CMake 版本的最佳实践
如果你的是多人协作项目,光在自己机器上装对版本没用,得在仓库里把版本钉死。常见做法是在CMakeLists.txt顶部写cmake_minimum_required(VERSION 3.24.0),这样拿到源码的人用低版本 CMake 会立刻收到友好报错而不是编译到一半才失败。
但只写这个还不够。3.24 里新增的特性如果被人跨版本混用,比如 CI 用的是 3.22、本地是 3.24,行为的差异特别容易在FetchContent或ExternalProject模块上暴露。我的习惯是在 CI 构建脚本里显式检查版本:
cmake --version > /dev/null 2>&1 || { echo "cmake required"; exit 1; } ver=$(cmake --version | grep -oP '\d+\.\d+' | head -1) [ "$ver" = "3.24" ] || { echo "need cmake 3.24, got $ver"; exit 1; }这个脚本片段适合 CI 起步阶段快速拦截版本漂移。更优雅的方案是用CMakePresets.json文件里的condition字段来判断 CMake 版本是否满足要求,但这个特性对 CMake 3.24 自己来说已经完整了,旧版本解析不了这个文件里的新字段,所以 CI 里还是建议先用脚本探一下版本,确保解析器本身存在。
5. 编译安装与使用 CMake 3.24.0 的避坑记录
5.1bootstrap阶段卡在Could not find CMAKE_ROOT或者串行编译链
现象是./bootstrap执行到一半,输出一串CMake Error: Could not find CMAKE_ROOT。原因:我曾在/home/xxx下解压源码包,然后直接跑 bootstrap,但当时环境里有另一套非标准的 CMake 缓存变量干扰了检测逻辑。这种报错通常不是路径真的丢了,而是 bootstrap 在检测系统环境时,读到了一个比你预期更老的 CMake 版本,它的CMAKE_ROOT指向规则和 3.24 不一样。
解决:把源码包解压到/tmp/cmake-build这种干净目录再试。或者先清干净当前 shell 里的 CMake 缓存变量:
unset CMAKE_ROOT unset CMAKE_MODULE_PATH我遇到过一次奇怪的情况:前一个项目在 shell 里导入了CMAKE_MODULE_PATH指到自定义模块目录,bootstrp 带着这个环境变量去生成初始 cache,结果就翻车了。清掉之后一遍过。
5.2 编译出的 CMake 不认识系统里的编译器
现象:装完后新建项目执行cmake ..,报CMAKE_C_COMPILER not set或The C compiler is not a full path。
原因:CMake 的编译器检测依赖一个内部列表,里面硬编码了常见编译器的路径与名称。如果你系统里装的是某厂商的定制版 GCC,或者编译器不在标准/usr/bin下,3.24 的检测逻辑就会抓瞎。另外,CC和CXX环境变量在配置阶段如果指向了不存在的路径,也会让检测静默失败。
解决:显式指定编译器路径:
cmake .. -DCMAKE_C_COMPILER=/opt/gcc-12/bin/gcc \ -DCMAKE_CXX_COMPILER=/opt/gcc-12/bin/g++装完之后再确认一下:cmake --system-information | grep COMPILER。你会发现 CMake 缓存了CMAKE_C_COMPILER:FILEPATH,后续构建会持续用这个路径,不会再自动探测。这也是为什么有条件的话尽量用系统包管理器把编译器路径统一——多版本编译器混用会让 CMake 缓存里的编译器记录越攒越乱。
5.3--fresh与其他版本行为差异导致的缓存迷惑
现象:同一个构建目录,用之前在 3.22 下配置好的 cache,直接执行cmake -LA能看到一大堆变量;换成 3.24 之后跑同样的命令,部分变量消失,甚至出现重复条目。
原因:3.24.0 对缓存变量的清理逻辑做了调整,某些在旧版本里不会写进 cache 的变量,现在变成了普通变量,不会持久化。--fresh参数会强制清空整个 cache 重新配置,但如果你不是有意为之,它不会主动触发。
解决:装完 3.24 后建议用新目录重新配置,不要复用旧版本的 build 目录。实在要复用,先清空CMakeCache.txt和CMakeFiles:
rm -rf CMakeCache.txt CMakeFiles cmake ..这是我在升级版本后最后悔没早做的事情。血泪经验:CMake 的 cache 文件本质是给同一版本用的,跨版本复用就是给自己埋雷。你后续两天可能都在排查为什么某些新变量没生效,结果问题全出在旧缓存身上。
5.4 编译时内存不足导致的make被系统 kill
现象:make -j16跑到一半,Killed字样出现,dmesg里有 OOM 记录。
原因:CMake 自带的编译包含不少模板重载的 C++ 文件,开启高并行时,每个编译进程可能占 2-4 GB 内存。如果你机器是 8G 内存还开-j16,直接爆掉。
解决:降级并行数,或者给 make 设置内存感知的并行策略:
make -j$(nproc --ignore=2)--ignore=2的意思是留出 2 个核的余量,适用于内存紧张但不至于 OOM 的机器。如果你经常编译超大模板项目,建议直接换 Ninja 生成器,它对并行任务的内存调度更温和,不会一次性拉起全部编译进程。
5.5ctest --version版本和cmake --version不一致
现象:cmake --version显示 3.24.0,但ctest --version显示 3.20.2,执行ctest时行为异常。
原因:CMake、CTest、CPack 三个可执行文件版本应该一致。如果你之前装过别的版本,且/usr/bin和/usr/local/bin各有一份,然后软链只覆盖了cmake,就会出现 ctest 和 cmake 分家的情况。
解决:重建软链,确保三种二进制都指向同一个目录:
ls -l /usr/local/bin/ctest /usr/local/bin/cpack rm -f /usr/local/bin/ctest /usr/local/bin/cpack ln -s /opt/cmake-3.24.0/bin/ctest /usr/local/bin/ctest ln -s /opt/cmake-3.24.0/bin/cpack /usr/local/bin/cpack验证:ctest --version && cpack --version。
6. 用 3.24.0 的新特性做快速验证:预设文件与环境变量联动
装完新版本,空跑cmake --version验证太单调。我用它写作收尾阶段,其实是做了个小实验:利用 3.24 的预设文件新特性,在同一个工程里为 Debug 和 Release 构建分别定制不同的环境变量,这个在 3.21 版本还是要靠外部包装脚本才能实现的。
先建一个极简的CMakeLists.txt:
cmake_minimum_required(VERSION 3.24) project(hello VERSION 1.0) message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") message(STATUS "Extra option: $ENV{EXTRA_OPTION}") add_executable(hello main.cpp)对应的CMakePresets.json:
{ "version": 6, "configurePresets": [ { "name": "debug", "displayName": "Debug build", "generator": "Ninja", "binaryDir": "${sourceDir}/build/debug", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" }, "environment": { "EXTRA_OPTION": "debug-mode" } }, { "name": "release", "generator": "Ninja", "binaryDir": "${sourceDir}/build/release", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" }, "environment": { "EXTRA_OPTION": "release-mode" } } ] }注意version字段,3.24 支持的最高预设版本就是 6。如果写 7 或更高的假想版本号,CMake 会直接报错。这个细节在 3.24 里第一次引入严格版本校验,旧版本只会忽略它不认识的新字段,而 3.24 会明确拒绝未知的预设版本。
用命令行验证:
cmake --preset=debug cmake --build build/debug cd build/debug && ./hello观察cmake --preset=debug的输出,你会看到:
Build type: Debug Extra option: debug-mode然后切到 release preset 再跑一次,环境变量自动变成release-mode。这就是 3.24 相对旧版最直观的体感差异——以前你需要在构建脚本里手动 export 环境变量,或者修改 CMakeLists 用if(DEFINED ENV{...})做条件判断,现在完全靠 preset 文件的隔离就能做到。
这个用法在做视觉推理框架的交叉编译时很有用。比如 Debug 需要把CUDA_LAUNCH_BLOCKING=1注入运行时环境,Release 不需要,直接在 presets 里分开配环境变量就行。我后来把整套逻辑整理进了模拟项目X的构建脚本,团队里新人跑构建不用再翻文档查环境变量,算是这套特性落地最直接的收益。
希望这个 3.24.0 的编译与验证流程能帮到你,至少在下一回拿到一个陌生的.tar.gz时,知道它是谁、能干什么、以及怎么干净地装进你自己的环境里。
本文还有配套的精品资源,点击获取