ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

CMake 3.24.0源码编译实战:从bootstrap到make install的完整指南

CMake 3.24.0源码编译实战:从bootstrap到make install的完整指南 简介CMake 3.24.0 源码包是一套完整的跨平台构建系统面向 C 开发者与多编译器环境通过解析 CMakeLists.txt 并生成对应平台的 Make、Ninja 或 Visual Studio 工程有效解决手动配置多环境构建的复杂度。压缩包整体约 9.91MB共 2000 个文件其中 6696 个 txt 提供说明与数据5935 个 cmake 文件承载各组件构建规则1916 个 rst 构成官方文档1464 个 c 与 840 个 cxx、620 个 cpp 等组成核心实现辅以头文件、测试脚本与辅助资源结构清晰可直接展开研究。已有 426 人学习下载适合希望深入掌握构建系统原理、需要从源码定制行为或解决复杂构建问题的中高级开发者。通过编译与阅读这些文件读者不仅能查看 CMake 内部模块的组织方式和依赖检测逻辑还能学习其测试集成与跨平台配置的实践方法为自有 C 项目的构建脚本设计提供可靠借鉴。1. 拿到 cmake-3.24.0.tar.gz 之后先别急着 ./configure第一次在服务器上看到 cmake-3.24.0.tar.gz 这个文件时我先入为主把它当成了安装包解压完就找 configure 脚本结果目录里根本没有这个文件只有 bootstrap。这个 tar.gz 不是开箱即用的二进制安装包而是 CMake 3.24.0 的源码打包产物需要本机编译器配合依赖库把它变成可执行文件。读完这篇文章你能搞明白三件事什么情况下值得自己编译而不是用发行版仓库里的老版本、源码编译的参数怎么给、装完之后和 VS Code、MinGW 以及老项目打交道时有哪些常见坑。适合两类人一类是系统自带 cmake 版本太低导致项目配置失败另一类是离线环境或者想把某个固定版本装到 /opt 下的开发者。2. 编译前先花十分钟搞清三件事依赖、平台与安装目录2.1 依赖检查g、make、OpenSSL 开发库一个都不能少在动手 ./bootstrap 之前我先用一条命令把本机的基础状态摸清楚。CMake 3.24.0 的源码主体是 Cbootstrap 阶段需要一个能正常工作的 C 编译器后续构建还需要 make。如果系统里只有 gcc 没有 g会卡在编译器检测那一关而且报错信息并不直观容易让人误以为源码包损坏。# 检查基础工具链 g --version make --version # Debian/Ubuntu 系装齐最小依赖 sudo apt install -y build-essential libssl-dev这里 build-essential 提供 gcc/g/makelibssl-dev 提供 OpenSSL 头文件。为什么特意强调 OpenSSL如果缺它bootstrap 不一定立刻失败但编译出来的 cmake 在通过 file(DOWNLOAD) 访问 https 地址、或者给 ctest 配置需要 TLS 的服务器时会直接报协议不支持。这类问题排查起来很玄学因为它在最常见的本地项目场景里完全看不出来。如果你是在最小化安装的容器里编译顺手把 ca-certificates 一起装上否则后续下载依赖时证书校验也会翻车。Windows 上从源码编译 CMake 也可以但更常见的做法是直接用官方安装器源码编译这条路径在 Windows 上需要额外配好 Visual Studio 的编译环境性价比不高所以下面步骤默认在 Linux 环境下执行。2.2 二进制发行版 vs 源码编译先想清楚省下这十五分钟的理由很多朋友看到源码包的第一反应是不是有官方二进制包吗确实CMake 官方为 Windows 提供安装器为 Linux 提供预编译 tar.gz而且大部分发行版软件源里也有 cmake 包。我个人的判断标准很简单能用 apt 装的绝不自己源码编译但以下两种场景必须走源码。第一种是版本下限被项目卡死。Ubuntu 20.04 软件源里的 cmake 是 3.16.3而不少新项目已经在 CMakeLists.txt 里写了 cmake_minimum_required(VERSION 3.20) 甚至更高直接用发行版自带版本会在配置阶段被一个 hard error 拦住没有任何商量余地。第二种是离线内网环境既没有外网下载官方二进制也不想把在线源挂进去这时手上的 cmake-3.24.0.tar.gz 就是后悔药只要内网里有一台机器能编译整个团队都能用。顺便把 makefile 和 cmake 的区别说清楚因为不少新人是被这个绕进去的。Makefile 是构建规则本身描述这个文件依赖哪些文件、怎么生成CMake 是生成 Makefile 的元构建工具它先分析 CMakeLists.txt 里的 target 和依赖关系再输出 Makefile 或 Ninja 文件。所以 CMake 解决的是跨平台项目如何描述构建make 解决的是拿到规则后如何执行增量编译。你编译安装 CMake 这一层是在对元构建工具本身做一次原生构建这个理解到位了后面看构建日志就不会慌。2.3 安装前缀为什么我习惯装到 /opt/cmake-3.24.0源码包默认的安装前缀是 /usr/local我不推荐新手直接一路回车装到那。更安全也更常见的做法是自定义一个带版本号的前缀目录原因有三。其一/usr/local/bin 里通常已经躺着发行版自带的 cmake再覆盖会把系统包管理器的状态弄脏其二/opt/cmake-3.24.0 这种目录自带版本标识以后要切回 3.16 或者升级到 3.27只需要把 PATH 里的目录换一下其三卸载时不需要任何卸载脚本删目录就是卸载这是源码编译最干净的隔离姿势。这个决定要在 bootstrap 之前做好因为编译产物里会写死安装路径。中间后悔了也不是不能改重新跑一遍 bootstrap 加 make install 到新目录机器上多花几分钟而已比用系统包乱覆盖值得多。所以我的编译流程里第一步永远不是 ./configure而是先建目录、写环境变量mkdir -p /opt/cmake-3.24.0 export CMAKE_PREFIX/opt/cmake-3.24.0 echo export PATH/opt/cmake-3.24.0/bin:$PATH ~/.bashrc把 CMAKE_PREFIX 这个变量先放好是为了让后面的 bootstrap 和 make install 有明确的落点。如果你不做这一步默认装到 /usr/local 也能用只是以后多版本切换时要跟系统自带的版本打架。我自己的习惯是任何源码编译的软件都会在安装前先决定它未来的安装路径而不是让默认值替我决定。路径选对了后面多版本管理能省掉大量麻烦。3. 源码编译三步走bootstrap、make 与 make install 的完整跑法3.1 解压与目录选择别在 /tmp 里干活源码编译最常见的翻车开始于路径选择。把 cmake-3.24.0.tar.gz 解压到 /tmp 再编译看着方便但 /tmp 在多数系统上会被定时清理而且部分环境里它挂载在 tmpfs 内存盘上空间有限。bootstrap 过程中会生成大量中间目标文件很容易把内存盘塞满然后制造出磁盘空间不足这种看似莫名其妙的报错。我一般会在专门的工作目录里解压并且保留整个源码树不删构建中间文件。mkdir -p ~/work cd ~/work tar xzf cmake-3.24.0.tar.gz ls cmake-3.24.0解压后目录里能看到 CMakeLists.txt、bootstrap、Source、Utilities 等文件。bootstrap 是源码自带的引导脚本它会先在本目录生成一个最小可用的 cmake再用这个 cmake 去配置完整的构建。源码包里没有 configure这是 CMake 源码构建和很多 autoconf 项目的明显区别——第一次接触时不用到处找 configure 脚本找到 bootstrap 就对了。3.2 bootstrap 的常用参数--prefix、--parallel、--system-curlbootstrap 脚本承担了传统 configure 的职责但名字不同。最简用法是 ./bootstrap --prefix/opt/cmake-3.24.0不过为了编译速度和后期的网络功能我会额外带两个参数。cd cmake-3.24.0 ./bootstrap --prefix/opt/cmake-3.24.0 \ --parallel8 \ --system-curl--parallel8 让 CMake 在引导自己时就用 8 路并行编译这一步不开的话 bootstrap 阶段会明显变慢尤其在资源充足的机器上纯属浪费时间。--system-curl 指示它优先使用系统自带的 libcurl而不是编译内置的 curl 副本。这个参数有两个好处一是链接系统 curl 更稳二是 SSL 行为跟随系统证书库后续拉 https 地址时不容易出现证书不识别的问题。代价是系统里得有 libcurl 开发头文件Debian/Ubuntu 上是 libcurl4-openssl-dev。如果你不想引入这个依赖可以去掉 --system-curl 走内置 curl但某些特殊网络环境下的行为会不一样我建议优先用系统 curl。等这个脚本跑完最后几行会提示你可以运行 make 了。这一步最常见的误用是直接 ./bootstrap 不加任何参数然后装到 /usr/local也不是不能用但版本管理的坑后面全要找回来。还有一点值得注意bootstrap 是全源码构建它不需要系统里有现成的 cmake所以不存在先装老版本 cmake 才能编译新版本 cmake的鸡生蛋问题。3.3 make 并行构建与 make install装完先看一眼 bin 目录bootstrap 结束之后正式的构建就交给 make。这里我有两个习惯第一用 -j 显式指定并行度不要放任单线程慢慢跑第二make install 之前先确认一下将拷进前缀目录的文件清单心里有底。make -j$(nproc) make install /opt/cmake-3.24.0/bin/cmake --version ls /opt/cmake-3.24.0/bin/make 的 -j$(nproc) 自动用上机器所有逻辑核心编译 CMake 本体在八线程机器上通常几分钟内完成。make install 会把可执行文件和共享库拷到 /opt/cmake-3.24.0 下。装完后 bin 目录里应该有 cmake、ctest、cpack如果 bootstrap 时带了 GUI 相关选项并且系统装好了 Qt还会有 cmake-gui。我一般只看前三个GUI 版我在 Linux 上很少依赖做项目配置我更习惯命令行方式。这里再多说一句make 和 make install 是两个不同的阶段。make 阶段失败不影响已经生成的前缀目录但 make install 会往系统目录里写东西。因此每次改参数重编我都习惯先清理再重新 make避免旧的编译产物干扰新配置。CMake 源码树不像用户项目那样常用 CMakeCache 缓存路径直接重编不像项目那样容易踩到缓存残留但保持干净总没有坏处。4. 用它跑通一个真实项目最小 CMakeLists、MinGW 工具链与 VS Code 配置4.1 用 3.24 跑通最小项目从源码到可执行文件装好了编译器总得验证它不是个摆设。我第一步从来不是跑大型项目而是建一个两个文件的 demo确认这条链路的每个环节都通。这个验证过程比任何 --version 输出都有说服力。// main.cpp #include cstdio int main() { printf(cmake works, version check pass\n); return 0; }# CMakeLists.txt cmake_minimum_required(VERSION 3.20) project(cmake_demo LANGUAGES CXX) add_executable(demo main.cpp)然后执行配置与构建mkdir -p build cd build /opt/cmake-3.24.0/bin/cmake .. /opt/cmake-3.24.0/bin/cmake --build . ./demo第一次执行 cmake .. 时CMake 会生成 CMakeCache.txt 和一套构建脚本。如果你用的是默认的 Unix Makefiles 生成器你会看到 build 目录里出现 Makefile。cmake --build . 是官方推荐的第二步它不管底层是 make、ninja 还是 Visual Studio 工程都能正确调用对应的构建工具。这么做的好处是你的命令不依赖具体生成器后续想切换 Ninja 也不用改习惯。4.2 CMake 与 MinGW手动指定生成器和编译器在 Windows 上用 CMake 有两条主线MSVC 下生成 Visual Studio 工程MinGW 下生成 Makefile。聊到 cmake 和 mingw多半是后者。没有 Visual Studio 的机器上我会提前装好 MinGW-w64并把 g 所在目录加进 PATH然后再跑配置。cmake -S . -B build-mingw -G MinGW Makefiles -DCMAKE_CXX_COMPILERg这里 -S 指定源码目录-B 指定构建目录比 cd build 这种写法更显式也适合写进脚本。关键是 -G 参数如果没有指定CMake 在 Windows 上默认找 Visual Studio找不到会报错所以显式给出 MinGW Makefiles 生成器让 CMake 明白你想用 GNU 工具链。-DCMAKE_CXX_COMPILERg 再补一层保险防止多版本编译器混在一起时挑错。生成后 build-mingw 里出现的是 Makefile此时用 cmake --build build-mingw 就能出可执行文件。顺带说下用 vscode 开发 stm32 的场景原理完全相同嵌入式工具链本质是交叉编译器配置时要用 -DCMAKE_TOOLCHAIN_FILE 指向工具链文件里面定义 arm-none-eabi-gcc 作为编译器。CMake 的生成器还是 Ninja 或 Unix Makefiles换的是编译器而不是流程。源码包安装的 3.24 在这方面跟发行版自带版本没有差别但版本新能减少部分 IDE 插件处理新语法时的兼容问题。4.3 VS Code 里 CMake Tools 的 Configure 按钮不出现排查三个常见成因很多新手在 VS Code 里装了 CMake Tools 扩展却发现底部状态栏没有 Configure 按钮就以为扩展没装好。这个问题我排查过很多次九成是下面三个原因之一。首先CMake Tools 只在当前打开的根目录里找到 CMakeLists.txt 时才认为这是一个 CMake 项目。你用 VS Code 打开了整个工作区但 CMakeLists.txt 在下一级子目录里扩展就识别不到状态栏自然不出现按钮。解法是直接打开含 CMakeLists.txt 的那层目录。第二扩展默认会用自动探测的编译器作为 kit。如果你的项目要求特定版本 cmake可以在 .vscode/settings.json 里强制指定{ cmake.cmakePath: /opt/cmake-3.24.0/bin/cmake, cmake.configureSettings: { CMAKE_PREFIX_PATH: /opt/cmake-3.24.0 } }cmake.cmakePath 告诉扩展使用我们编译好的 3.24而不是系统 PATH 里的旧版本。configureSettings 里的 CMAKE_PREFIX_PATH 是给 find_package 用的项目里要找 Eigen3 这类自定义安装的库时把对应前缀写进这里能让配置阶段少走弯路。第三如果配置时一直报找不到编译器的错用 CtrlShiftP 调出命令面板运行 CMake: Scan for Kits让扩展重新扫描 MinGW 或 MSVC 的编译套件。做完以上三步状态栏的 Configure 按钮基本都会出现。这里没有玄学都是 CMake 在 IDE 里的标准协作方式。5. 避坑源码装 CMake 最常见的 5 个问题与排查思路5.1 bootstrap 卡在编译器检测先确认 g 真的存在现象bootstrap 跑到 Checking whether the C compiler works 时输出错误并退出日志里看不到具体原因只有一句 failed。原因最小化安装的服务器或容器里只有 gcc 没有 g或者内存只有 1GB并行编译被 OOM 杀掉。解决先确认工具链再看资源。惯用的检查命令是which g || echo no g free -h如果 g 不存在按系统包管理器装上 build-essential 即可。内存小的机器把 bootstrap 的 --parallel 降到 2 或 4或者临时加 swap比反复重试更有效。5.2 链接阶段报 curl 相关符号未定义--system-curl 的副作用现象make 跑到链接 cmake 时报大量 curl_global_init、curl_easy_setopt 等符号未定义。原因bootstrap 时用了 --system-curl让 CMake 链接系统 libcurl但系统只装了运行库没有装开发头文件导致编译能找到头文件但链接缺符号。解决装开发库后重新 make不需要重新 bootstrap。sudo apt install -y libcurl4-openssl-dev make -j$(nproc)如果不想装这个依赖也可以回到 --no-system-curl 让 CMake 用内置 curl。但对离线内网环境而言系统 curl 更可控我一般还是选择装依赖。5.3 装完 cmake --version 显示的还是旧版本PATH 优先级问题现象make install 成功后输入 cmake --version 出来一个很老的版本号比如 Ubuntu 自带的 3.16.3。原因PATH 里 /usr/bin 排在 /opt/cmake-3.24.0/bin 前面shell 先找到了系统装的旧版本。解决检查 echo $PATH要么把 /opt/cmake-3.24.0/bin 排到前面要么直接用全路径调用。我用的做法是先在当前 shell 里 export PATH 确认没问题再写进 ~/.bashrc避免起手就污染全局环境。export PATH/opt/cmake-3.24.0/bin:$PATH which cmake cmake --version提示如果 which cmake 指向的还是 /usr/bin/cmake说明 export 没生效或者当前目录没在 PATH 里别急着怀疑安装有问题。5.4 MinGW 生成器提示找不到 sh.exe环境变量串味现象Windows 上敲 cmake -G MinGW Makefiles .. 配置失败提示找不到 sh.exe或者报 sh.exe was found in your PATH。原因系统里同时装了 Git Bash 或 MSYS2PATH 里有 sh.exeCMake 的 MinGW Makefiles 生成器会尝试用它执行命令和 Windows 原生环境冲突。解决配置时把 PATH 里的 MSYS2 或 Git 目录临时拿掉或者改用 Ninja 生成器。cmake -S . -B build -G Ninja -DCMAKE_C_COMPILERgcc -DCMAKE_CXX_COMPILERgNinja 在 Windows 上的行为更干净不依赖 Unix shell。这个坑在各讨论区出现频率极高遇到了优先怀疑 PATH而不是怀疑 cmake 本体装坏了。5.5 配置旧 Qt 项目报 cmake error at qt5config.cmake新 CMake 和老依赖的兼容问题现象项目里用了旧版 Qt比如 5.9.4用 CMake 3.24 去 configure 时Qt5Config.cmake 里报错配置流程断在 find_package(Qt5) 上。原因Qt 的 CMake 配置文件通常只在 Qt 发布时打过标记新版本 CMake 的内部策略变更会触发老脚本中的废弃用法Qt 官方并没有对旧版本做前向兼容承诺。解决优先把 Qt 升到 5.12 以上不能升级时把项目里对 CMake 版本的下限调低或者改用系统自带的旧 CMake 来处理这个旧 Qt 项目。新 CMake 未必能配旧依赖这个认知比任何参数都重要遇到类似报错先别想着给 CMake 打补丁先看看 find_package 的是哪个版本的库。6. 把 3.24.0 用成工具箱多版本切换、离线打包与 --fresh 小技巧6.1 多版本共存符号链接切换的土办法如果你不是只有一台机器而是有一批服务器最省事的做法是把编译好的 CMake 目录打包分发而不是每台机器都重新编译。我把 /opt/cmake-3.24.0 直接 tar 打包拷贝到目标机器后解压到相同路径cmake --version 就能正常工作。要注意一点CMake 安装时会写死一些内部路径解压到不同的前缀目录会出现奇怪行为所以离线分发时尽量保持路径一致这是我从实际打包分发里得到的教训。6.2 用 cmake --fresh 代替手动删 build 目录3.24.0 这个版本让我最顺手的一个新特性是 --fresh。以前改完 CMakeLists.txt如果怀疑 CMakeCache.txt 里有残留缓存我得手动删掉 build 目录再重新配置。现在直接执行cmake --fresh -S . -B build--fresh 会在配置前清除缓存等于把删目录这个操作内置了。项目里如果遇到改了选项不生效的诡异问题先用这一招重置配置通常能省掉半小时排查时间。这也是我遇到项目要求最低版本是 3.20 时愿意特意装一个新版本 CMake 的动力之一。6.3 验证安装是否可靠换个真实项目跑一遍安装完 CMake 后我一般不做太多验证直接拿一个稍微复杂的项目跑配置。那种只检查 --version 的做法不足以证明功能完整因为很多问题是在实际配置阶段才暴露的。我的习惯是找一个依赖 find_package、包含多个子目录的项目依次执行 cmake --fresh、cmake --build确认全链路没问题后才认为这个 CMake 可用。这套验证流程走完基本能覆盖大部分功能点。希望这篇源码编译的实战记录能帮到你至少在下次拿到 .tar.gz 时能少走一个弯路。本文还有配套的精品资源点击获取
返回列表