我为什么建议不要用CMake

本文指出尽管CMake能统一生成多平台的makefile或project文件,但存在诸多缺点,如不支持相对路径、包含头文件和库文件设置不能重用、版本兼容性差、对持续构建支持不好等。作者推荐在不同平台使用对应工程文件,纳入版本控制,虽需维护多平台文件,但工作量不大。

作者:朱金灿
来源:clever101的专栏

CMake的优点

  CMake在开源代码中最常见的应用场景之一是生成很多平台的makefile或者project文件,这种统一管理的方式确实有其方便之处。尽管CMake有一些优点,我依然不建议使用CMake。下面我要谈谈CMake的一些缺点。

CMake的缺点

CMake不支持相对路径

  这个是CMake的最大缺点之一。很多时候你通过CMake生成了一个project文件,换一下磁盘路径它就不能用了,还得重新生成project文件。

CMake的包含头文件和库文件设置不能重用

  因为CMake不支持相对路径,从而导致CMake生成的project文件并不能重用其他人设置好的包含头文件和库文件的设置。如果采用CMake,一个新人接手一个新项目,估计至少花半天来完成这些设置,期间可能他还要咨询其它同事。

CMake的版本兼容性很不好

  CMake 工具版本太旧的话,可能 CMakeLists.txt 使用了新的语法,就会不兼容;CMake 工具版本太新的话,也会出现不兼容问题,因为 CMake 新版本在更新时不一定向后兼容。

CMake对持续构建支持不好

  我搜过一些jenkins+cmake持续构建C++项目的文章,感觉都是玩具性质的作为,就是说按照这些文章的做法,不用任何第三方库的C++项目可以这么搞。问题是现实中稍微有点规模的C++项目,哪个不需要第三方库呢?要用到第三方库,就必然涉及到包含头文件和库文件的设置,而这个就是CMake的弱项。

更好的做法是什么

  如果不用CMake,那么更好的做法是什么?我推荐的做法是:Windows上直接使用VisualStudio的工程文件,Linux下使用QtCreator或codeblocks的工程文件或makefile,mac平台使用xcodeproject。工程文件都纳入版本控制。这样新手直接下载下来就能用,就能迅速进入项目开发状态了。这样做的缺点可能是需要维护多个平台的工程文件,但我个人认为这些工作量并不大,比如VisualStudio的工程文件和QtCreator的工程文件就能互转,这样只需要把一个维护好就行。

<think> 我们之前讨论的是在Qt项目中遇到'QHostInfo: No such file or directory'错误,现在用户是在使用CMake构建Qt项目时遇到同样的错误。因此,我们需要调整之前的解决方案以适应CMake构建系统。 ### 问题分析 在使用CMake构建Qt项目时出现`QHostInfo: No such file or directory`错误,主要原因包括: 1. **CMake未正确配置Qt Network模块**:在`CMakeLists.txt`中没有找到并链接Qt5 Network模块。 2. **Qt安装不完整**:当前Qt安装可能缺少Network组件。 3. **编译器搜索路径问题**:CMake未能正确设置包含路径。 ### 解决方案 #### 步骤1:修改CMakeLists.txt文件 在您的CMakeLists.txt中,确保已经包含了对Qt5 Network模块的查找和链接。具体步骤: 1. **添加`find_package`指令**:确保查找Qt5组件时包含Network模块。 ```cmake find_package(Qt5 COMPONENTS Core Gui Network REQUIRED) # 确保包含Network ``` 2. **将目标链接到Qt5模块**:在使用`target_link_libraries`时链接`Qt5::Network`。 ```cmake target_link_libraries(your_target_name PRIVATE Qt5::Core Qt5::Gui Qt5::Network) ``` #### 步骤2:重新生成构建系统 修改CMakeLists.txt后,必须重新生成构建文件: - 删除构建目录中的所有文件(特别是CMake缓存文件)。 - 重新运行CMake配置和生成步骤。 #### 步骤3:验证Qt安装 如果错误仍然存在,请检查您的Qt安装是否包含Network模块: - 在Qt安装目录下查找`include`子目录,检查是否存在`QtNetwork`目录,例如: ``` <Qt安装路径>/5.15.2/gcc_64/include/QtNetwork ``` 确认该目录下存在`QHostInfo`文件(如`qhostinfo.h`)。 #### 步骤4:手动指定包含路径(备用方案) 虽然通常不需要,但如果CMake未能正确设置包含路径,可以尝试手动添加: ```cmake include_directories(${Qt5Network_INCLUDE_DIRS}) ``` #### 步骤5:检查代码包含语句 确保源代码中正确包含头文件: ```cpp #include <QHostInfo> // 不要使用双引号或相对路径 ``` ### 验证与调试 - 成功标志:重新构建后不再报错。 - 如果问题依旧,可以尝试以下调试方法: 1. 在CMakeLists.txt中添加以下命令打印包含路径信息: ```cmake message(STATUS "Qt5 Network include dirs: ${Qt5Network_INCLUDE_DIRS}") ``` 2. 检查CMake输出的包含路径是否正确。 ### 预防措施 - 在添加新的Qt模块时,务必更新`find_package`和`target_link_libraries`。 - 确保使用兼容的Qt和CMake版本(推荐Qt5.12以上和CMake3.5以上)。 ### 注意事项 - 如果之前使用的是qmake,现在改用CMake,需要将`.pro`文件中的配置(如`QT += network`)转换为CMake的等效配置(即`find_package`和`target_link_libraries`)。 - 如果CMake在配置过程中报错,例如找不到Qt5,请确保正确设置了`CMAKE_PREFIX_PATH`变量指向您的Qt安装目录。例如: ```bash cmake -DCMAKE_PREFIX_PATH=/path/to/Qt/5.15.2/gcc_64 .. ``` ### 相关问题 1. **如何在CMake中正确配置Qt的串口模块(QSerialPort)?** 类似地,您需要在`find_package`中包含`SerialPort`,并链接`Qt5::SerialPort`。 2. **CMake构建过程中出现"Could not open file for write"错误怎么办?** 这通常是文件权限问题或路径包含空格导致,检查构建目录的读写权限以及路径中是否包含空格[^1][^2]。 3. **如何检查CMake是否找到了特定的Qt模块?** 在CMakeLists.txt中添加`message(STATUS "Qt5 Network found: ${Qt5Network_FOUND}")`来查看查找结果。 4. **CMake配置Qt项目的基本框架是怎样的?** 一个最小配置应包括: ```cmake cmake_minimum_required(VERSION 3.5) project(MyQtProject) find_package(Qt5 COMPONENTS Core Gui Widgets Network REQUIRED) add_executable(my_app main.cpp) target_link_libraries(my_app PRIVATE Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Network) ``` </think> ### 解决 CMake 构建 Qt 项目时 "QHostInfo: No such file or directory" 的错误 #### 📌 核心问题分析 该错误表明 CMake 在构建 Qt 项目时无法定位 `QHostInfo` 头文件,主要由于: 1. **CMake 未正确配置 Qt Network 模块**(关键原因) 2. Qt 安装缺少 Network 组件 3. 编译器搜索路径未包含 QtNetwork 头文件 4. CMake 生成的构建文件过期或缓存错误(参考引用[1]的缓存问题) --- ### 🔧 解决方案步骤 按照优先级顺序执行: #### ✅ 1. 修改 CMakeLists.txt 配置(必需) 在您的 `CMakeLists.txt` 中添加 Qt Network 模块依赖: ```cmake cmake_minimum_required(VERSION 3.5) project(YourProjectName) # 关键修改:添加 Network 模块 find_package(Qt5 COMPONENTS Core Gui Network REQUIRED) # 确保包含 Network add_executable(${PROJECT_NAME} main.cpp) # 链接 Network 模块 target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Gui Qt5::Network # 必须添加此行 ) ``` #### 🔄 2. 清理并重新生成构建文件 1. **完全删除构建目录**(如 `build/` 文件夹) 2. 重新创建构建目录并运行 CMake: ```bash mkdir build && cd build cmake .. -DCMAKE_PREFIX_PATH="<Your_Qt_Install_Path>" # 例如: /opt/Qt/5.15.2/gcc_64 ``` 3. 重新编译: ```bash make -j4 ``` #### 🔍 3. 验证 Qt 安装 1. 检查 Qt 安装目录是否包含 Network 模块: ```bash ls <Qt_Install_Path>/5.15.2/gcc_64/include/QtNetwork # 确认有 QHostInfo 文件 ``` 2. 如果缺少模块,通过 Qt 维护工具安装 `Qt Network` 组件 #### ⚙️ 4. 手动指定路径(备用方案) 在 `CMakeLists.txt` 中添加显式路径: ```cmake include_directories(${Qt5Network_INCLUDE_DIRS}) # 添加 Network 头文件路径 ``` #### ✏️ 5. 检查源代码包含 确保代码中使用标准包含语法: ```cpp #include <QHostInfo> // 正确写法 // 避免 #include "QtNetwork/QHostInfo" 或相对路径 ``` --- ### 🛠️ 高级调试技巧 1. **检查 CMake 模块查找结果**: ```cmake message(STATUS "Qt5 Network found: ${Qt5Network_FOUND}") message(STATUS "Include dirs: ${Qt5Network_INCLUDE_DIRS}") ``` 2. **检查编译器包含路径**: ```bash cd build make VERBOSE=1 # 查看实际编译命令中的 -I 参数 ``` 3. **修复 CMake 缓存问题**(参考引用[1][3]): ```bash rm -rf CMakeCache.txt CMakeFiles cmake -DCMAKE_CXX_COMPILER=g++ -G "Unix Makefiles" .. ``` --- ### ️ 预防措施 1. **始终在 `find_package` 中显式声明所需模块** 2. 定期清理构建目录避免缓存问题 3. 使用 CMake 变量指定 Qt 路径: ```bash cmake -DCMAKE_PREFIX_PATH="/opt/Qt/6.2.4/gcc_64" .. ``` 4. 验证模块链接状态: ```cmake if(NOT TARGET Qt5::Network) message(FATAL_ERROR "Qt5 Network module not found!") endif() ``` > 💡 **提示**:如果曾手动修改过 Qt 安装文件(如引用[4]所述),建议重装 Qt 以避免软链接损坏问题。 --- ### ❓ 相关问题 1. **如何在 CMake 中正确配置 Qt 的串口模块(QSerialPort)?** _解决方案类似,需添加 `find_package(Qt5 COMPONENTS SerialPort)` 并链接 `Qt5::SerialPort`_ 2. **CMake 找不到 Qt 安装路径如何解决?** _设置 `-DCMAKE_PREFIX_PATH=<Qt安装路径>` 或配置 `QT_DIR` 环境变量_ 3. **CMake 构建时出现 "Could not open file for write" 错误如何处理?** _检查目录权限,清除 CMake 缓存(参考引用[1]),确保路径无空格(参考引用[2])_ 4. **如何验证 CMake 是否找到特定 Qt 模块?** _使用 `message(STATUS "Qt5 Network status: ${Qt5Network_FOUND}")` 输出查找结果_
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

clever101

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值