ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

从源码编译CMake 3.24:解决版本过低与工程构建问题

从源码编译CMake 3.24:解决版本过低与工程构建问题 简介CMake 是一个广泛使用的跨平台构建系统这份源码压缩包提供其 3.24.0 版本的完整内容专门面向需要在 Linux 或 Unix 环境中编译安装、定制构建流程或研究构建机制的 C 开发者。压缩包采用 tar.gz 格式解压后共包含约两千个文件文本说明、CMake 模块脚本、RST 文档、C/C 源文件与头文件构成主体同时附有测试用例、配置模板以及各平台支持文件基本覆盖从项目配置、源码编译到打包分发的完整构建链路。全部文件大小仅为九点九一兆字节体积小巧便于下载存储与长期归档。目前已有四百二十五人学习下载反映出它在 C 工程实践中的实用价值。对于希望深入了解 CMake 内部实现、复用现有模块或排查复杂构建问题的开发者而言这份源码包既是可离线部署的基础工具也是学习现代 C 工程化组织方式的宝贵参考资料。 拿起这份cmake-3.24.0.tar.gz很多做 C/C 开发的同行应该都不陌生——CMake 是目前跨平台构建工具里事实上的标准3.24.0 是 2022 年发布的稳定版而 tar.gz 后缀说明它是面向 Linux/Unix 系统的源码包。我之所以愿意专门写一篇是因为“cmake 下载、cmake 安装、cmake 教程”这几个词背后其实藏着一大批被“CMake 3.1.3...3.26 or higher is required. You are running version 2.8.12.2”这种报错卡住的同学。如果你也遇到过系统自带的 cmake 太老、装新模块装不上、编译开源项目被版本要求卡脖子那这篇就是写给你看的。我会从源码编译安装讲起一直说到用 CMake 3.24 组织 C 工程最后把几个高频报错整理成排查手册。1. 为什么非源码包不可cmake-3.24.0.tar.gz 的真实价值1.1 源码包和二进制包的本质区别Linux 下装软件最省事的方式是apt install cmake或者yum install cmake但这会带来一个很现实的问题版本锁死。Ubuntu 20.04 自带的 cmake 是 3.16.3CentOS 7 更夸张默认仓库里是 2.8.12.2。现在的项目动不动要求cmake_minimum_required(VERSION 3.14)甚至 3.26你拿一个 2.8 的版本去跑它连target_link_libraries的新写法和Preset特性都不认识自然只能报“编译失败”或者“找不到指令”。源码包的价值就在于它可以绕开系统的包管理器和软件源自己决定装哪个版本、装到哪个目录甚至可以在编译时选择启用哪些特性。cmake-3.24.0.tar.gz就是这样一个纯净的源码分发物只要你的机器上有 C 编译器理论上它就能把自己从源代码编译成可执行文件。这种“自举”能力在需要固定工具链版本的内网环境、离线服务器、交叉编译场景里特别重要。1.2 什么样的人必须自己编译安装 CMake我总结下来以下几类情况大概率得手动来一次源码安装老系统跑新项目比如 CentOS 7 上默认 cmake 是 2.8.12.2而几十个热门开源项目最低要求 3.10这时候必须升级。需要特定版本新特性CMake 3.21 之后才有像样的CMakePresets.json3.24 对 CUDA、Swift 等语言的支持也明显更完善老版本根本跑不动。交叉编译和嵌入式开发要在主机上生成一份能编译 ARM 或特定平台代码的 CMake需要搭配 toolchain 文件而某些旧版 cmake 对CMAKE_TOOLCHAIN_FILE的处理有兼容性问题。想脱离系统目录干净管理自己装在/opt/cmake-3.24.0通过软链接切换版本比把系统自带的 cmake 强拆掉要安全得多。下面这张表可以更直观地对比对比项apt/yum 安装源码编译 cmake-3.24.0版本新鲜度跟随系统发行版普遍偏旧可装任意新版安装目录分散在 /usr/bin, /usr/share可统一指定 /opt 或 /usr/local离线部署依赖本地仓库或缓存只需拷贝一个压缩包定制能力基本没有可配置 OpenSSL、GUI 等开关升级/降级受包管理器限制软链接随时切换所以如果你正好看到项目日志里出现“requires cmake 3.26 or higher”这样的字眼与其去百度找一个不明来路的安装包不如亲手编译一次这个 tar.gz整个过程也就十来分钟。2. 从 tar.gz 到可执行文件源码编译安装全流程实录2.1 编译前的环境检查在编译 CMake 之前先确认机器上有能用的 C/C 编译器。CMake 自身是用 C 写的3.24 版本要求编译器支持 C11说人话就是 GCC 5.1 以上。CentOS 7 默认的 GCC 4.8 肯定不行需要先切换到高版本工具链比如 devtoolset-7。打开终端先跑这几条命令gcc --version g --version make --version如果输出里能看到版本号就说明基础编译工具是齐的。顺便检查一下 OpenSSL 开发库是否安装因为 CMake 在下载 Python 包、处理 HTTPS 链接时会用到 OpenSSLopenssl version如果没有 OpenSSL 开发头文件也可以在编译时显式关闭相关功能但我不推荐默认关掉后面下载模块会踩坑。这块不用太焦虑即使缺了bootstrap 过程也会给出清晰的提示。2.2 完整编译安装步骤拿到cmake-3.24.0.tar.gz后按顺序执行# 1. 解压 tar -xzf cmake-3.24.0.tar.gz # 2. 进入源码目录 cd cmake-3.24.0 # 3. 生成构建系统 ./bootstrap --prefix/usr/local/cmake-3.24.0 # 4. 并行编译-j 后面跟 CPU 核数 make -j$(nproc) # 5. 安装到指定目录 sudo make install这里最重要的一个步骤是./bootstrap。它的作用和大多数源码包的./configure类似但又有区别bootstrap 不是单纯检测环境而是先用系统编译器编译出一个最小的 CMake 原型再用这个原型去编译完整的 CMake。这个“自举”过程能保证最终装出来的版本用的就是你自己指定的编译器。--prefix参数指定安装目录建议不要直接指到/usr装在一个独立目录里更好维护。如果网速和环境允许可以加一个--with-openssl这样编译出来的 CMake 支持 HTTPS 协议后续 FetchContent 下载依赖包时不会报 SSL 错误。想要图形界面的同学可以加--qt-gui但服务端开发一般用不到我通常不启用它能省不少编译时间。编译耗时看机器性能4 核机器大概 5-10 分钟。编译完成后在bin/目录下会生成cmake和ctest等文件。2.3 验证安装结果与版本切换技巧安装完成后先验证一下/usr/local/cmake-3.24.0/bin/cmake --version如果输出里能看到“cmake version 3.24.0”说明安装成功。再把它软链接到系统 PATH方便全局使用sudo ln -s /usr/local/cmake-3.24.0/bin/cmake /usr/local/bin/cmake sudo ln -s /usr/local/cmake-3.24.0/bin/ctest /usr/local/bin/ctest hash -r cmake --version提示不要在 PATH 里把多个版本的 CMake 目录同时放进去很容易出现“明明刚装的 3.24cmake --version 却还是老版本”的诡异问题。我习惯用软链接指向当前项目需要的版本切换时只需要改软链接干净利落。3. 装完别急着跑用 CMake 3.24 组织一个真正的 C 工程3.1 CMakeLists.txt 的最小骨架CMake 不是一个编译器它的任务是“生成编译指令”让 Make 或 Ninja 去干活。理解这一点后写CMakeLists.txt就不会迷路。新建一个目录放一个最简单的工程my_project/ ├── CMakeLists.txt └── main.cppmain.cpp随便写个 hello worldCMakeLists.txt写成这样cmake_minimum_required(VERSION 3.20) project(MyApp VERSION 1.0.0 LANGUAGES CXX) add_executable(my_app main.cpp) target_compile_features(my_app PRIVATE cxx_std_17) install(TARGETS my_app RUNTIME DESTINATION bin)cmake_minimum_required不是摆设它决定了 CMake 以哪种兼容模式运行。如果项目要求 3.20而用户机器上跑的是 2.8CMake 会直接拒绝执行。这也就是为什么很多项目 README 里第一句就写“You need CMake x.x”——这个数字就是在这里定义的。target_compile_features是推荐写法比直接set(CMAKE_CXX_STANDARD 17)更精确它告诉 CMake如果编译器不支持 C17就在配置阶段响亮地失败而不是等到编译到一半才报一堆莫名其妙的错误。3.2 构建流程从 build 目录到可执行文件第一次用 CMake 的人最容易犯的错是直接在源码目录里执行cmake .导致生成的中间文件把源码目录搞得乌烟瘴气。正确姿势是“源外构建”mkdir -p build cd build cmake .. -DCMAKE_BUILD_TYPERelease make -j$(nproc)cmake ..会根据CMakeLists.txt生成 Makefilemake才会真正调用编译器。为什么要单独建一个 build 目录因为 CMake 生成的文件很多包括缓存、依赖文件、生成的头文件等全部放在源码目录里会污染项目后期想切换 Debug/Release 也更麻烦。CMake 3.21 之后引入了CMakePresets.json3.24 支持得非常好可以极大简化配置{ version: 3, configurePresets: [ { name: release, generator: Unix Makefiles, binaryDir: ${sourceDir}/build/release, cacheVariables: { CMAKE_BUILD_TYPE: Release } } ] }之后只需要cmake --preset release cmake --build --preset release不夸张地说preset 是近几年 CMake 最提升幸福感的功能项目一多你再也不需要在十几个-D参数之间复制粘贴了。3.3 引入第三方库find_package 与 option真实项目里没有哪个 C 工程只靠自己一个文件就能跑肯定要引入第三方库。CMake 的find_package是核心find_package(OpenSSL REQUIRED) target_link_libraries(my_app PRIVATE OpenSSL::SSL OpenSSL::Crypto) option(ENABLE_TESTS Build tests ON) if(ENABLE_TESTS) enable_testing() add_executable(test_main test_main.cpp) add_test(NAME basic_test COMMAND test_main) endif()find_package其实就是在指定路径下找库的Config.cmake或查找脚本找到之后拿到库的头文件和二进制位置。如果你的库不是标准路径下可以用-DOpenSSL_ROOT_DIR/your/path手动指定搜索起点。option则是给用户一个开关cmake .. -DENABLE_TESTSOFF就能关掉测试编译非常实用。注意如果你的项目要编译 C20 协程或模块CMake 3.24 已经能正确识别编译器的模块扫描命令但如果编译器版本太老CMake 也会在配置阶段主动报错所以别以为升级了 CMake 就万事大吉编译器版本同样重要。4. 高频报错排查实录从热搜词看真实战场4.1 版本过低报错“CMake 3.1.3...3.26 or higher is required”这个报错可以说占据了 cmake 热搜榜的半壁江山。错误形态一般长这样CMake Error at CMakeLists.txt:1 (cmake_minimum_required): CMake 3.26 or higher is required. You are running version 2.8.12.2原因很简单项目要求新版本而你系统自带的 cmake 太老最常见于 CentOS 7、Ubuntu 18.04 这类自带版本“考古”级别的系统。解决办法就是本文第二部分的源码安装流程装完新版本后用软链接覆盖旧版问题立刻消失。这里提醒一句不要为了绕过报错去改项目里的cmake_minimum_required。把 3.26 改成 3.10 确实能让 CMake 不再报错但项目里可能用到了只有新版本才支持的语法比如target_link_options、add_link_options、ctest的新特性。你把门槛降到 3.10换来的不是成功而是后面随时可能爆出来的语法报错。4.2 CUDA 编译器报错CMAKE_CUDA_COMPILER 没设置热词里另一个高频问题是CMake Error: CMAKE_CUDA_COMPILER not set, after EnableLanguage出现这种报错通常是因为项目里启用了 CUDA 语言但 CMake 找不到 nvcc。手动检查一下 nvcc 是否存在which nvcc /usr/local/cuda/bin/nvcc --version如果 nvcc 没装或不在 PATH 里需要先安装 CUDA Toolkit或者显式指定编译器cmake .. -DCMAKE_CUDA_COMPILER/usr/local/cuda/bin/nvcc更稳妥的办法是在CMakeLists.txt里提前设定set(CMAKE_CUDA_COMPILER /usr/local/cuda/bin/nvcc) project(MyApp LANGUAGES CXX CUDA)但要注意CMake 要求project()声明语言之前就必须能识别编译器所以set(CMAKE_CUDA_COMPILER)最好放在project()之前。这个报错之所以频繁还有一个原因是用户只装了 GPU 驱动没装完整 CUDA Toolkit驱动和 Toolkit 是两个东西前者负责运行后者才提供编译器。4.3 Windows 下编译与 win7 32 位的老问题cmake 热词里“cmake win7 32位下载安装”也一直很火这里我多说两句避免大家走弯路。cmake-3.24.0.tar.gz是 UNIX 源码包Windows 上官方提供的是.msi安装包或.zip二进制包不要拿 tar.gz 硬解压了然后到处找.exe。另外CMake 3.24 的官方 Windows 安装包已经全面转向 64 位如果你还在用 32 位 Windows 7去找 3.13 或更早的 32 位安装包更现实。即便安装成功还要考虑 Visual Studio 或 MinGW 的版本匹配VS2015 以下的工具链编译现代 CMake 项目时也会碰到标准库支持问题。简单说老系统老工具链就认命别硬上最新 CMake。4.4 工具链、日志与 MPI 的补充排查出现频率同样不低的还有几个词一块儿说了cmake toolchain交叉编译的标配。比如你想用 CMake 编译一个跑在 ARM 开发板上的程序需要写一个.cmake工具链文件然后在配置时用-DCMAKE_TOOLCHAIN_FILExxx.cmake指定。CMake 3.24 对编译器检测的日志更详细了如果编译器识别失败建议先看CMakeFiles/CMakeError.log里面会记录具体失败的原因。cmake loglevel / 调试日志想在构建时看 CMake 到底做了啥可以用cmake --trace或cmake --debug-output追踪配置过程。在 CMakeLists.txt 里用message(STATUS ...)打印关键变量是最常见的调试方式。cmake 引入 MPI并行计算项目的刚需。通常这样写find_package(MPI REQUIRED) target_link_libraries(my_app PRIVATE MPI::MPI_CXX)如果没找到 MPI需要手动指定cmake .. -DMPI_CXX_COMPILER/path/to/mpicxx特别提醒find_package(MPI)要求 CMake 能找到mpicxx或mpic所以先运行which mpicxx确认 MPI 已经装好再谈引入。4.5 一个很实用的排查习惯最后分享一个我自己的习惯不管项目报什么构建错误先跑一句cmake --version确认当前版本。很多时候版本不对是万恶之源。然后赶紧看错误日志文件CMake 出错时会生成CMakeCache.txt和CMakeFiles/CMakeError.log这里面记录的是“为什么失败”的第一手资料远比你在搜索框里复制报错乱猜靠谱。我踩过的最深的一次坑是把 CMake 从 2.8 换成 3.24 后老项目里用短横线写的编译选项全部失效找了半天才发现是新版本对-Wl参数解析更严格了。后来我养成了一个习惯升级 CMake 后先把项目里所有CMAKE_CXX_FLAGS打印出来看一遍再开始调试。你现在手动编译一次cmake-3.24.0.tar.gz相当于给自己省掉了未来无数个“为什么报错”的夜晚。本文还有配套的精品资源点击获取
返回列表