cmake项目,多模块的一些自我摸索

ops/2025/2/19 18:43:51/

我的项目是:有一个根cmakelist,下面有若干个子项目,在这个基础上,需要在根下的common目录下存放公用的代码文件

如果你的项目结构是一个根 CMakeLists.txt 管理若干个子项目,并且需要在 common 目录下存放公共代码文件,那么可以通过以下方式实现:


项目结构示例

假设你的项目结构如下:

复制

project/
├── CMakeLists.txt              # 根 CMakeLists.txt
├── common/                     # 公共代码目录
│   ├── utils.cpp
│   ├── utils.h
│   ├── logger.cpp
│   └── logger.h
├── subproject1/                # 子项目 1
│   ├── CMakeLists.txt
│   ├── main.cpp
│   └── ...
├── subproject2/                # 子项目 2
│   ├── CMakeLists.txt
│   ├── main.cpp
│   └── ...
└── ...

实现步骤

1. 在根 CMakeLists.txt 中定义公共代码

在根 CMakeLists.txt 中,将 common 目录中的代码定义为一个接口库(Interface Library),这样可以在子项目中共享这些代码,而无需重复编译。

cmake

复制

# 根 CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyProject)# 添加 common 目录中的源文件
file(GLOB COMMON_SOURCES "common/*.cpp" "common/*.h")# 创建一个接口库(不生成实际的库文件,仅用于共享代码)
add_library(common_interface INTERFACE)# 将 common 目录中的源文件添加到接口库
target_sources(common_interface INTERFACE ${COMMON_SOURCES})# 将 common 目录添加到接口库的头文件搜索路径
target_include_directories(common_interface INTERFACE common)# 添加子项目
add_subdirectory(subproject1)
add_subdirectory(subproject2)

2. 在子项目中使用公共代码

在每个子项目的 CMakeLists.txt 中,通过 target_link_libraries 将 common_interface 链接到子项目的目标中。

例如,subproject1/CMakeLists.txt

cmake

复制

# subproject1/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(SubProject1)# 添加子项目的源文件
set(SOURCES main.cpp)# 创建可执行文件
add_executable(subproject1 ${SOURCES})# 链接 common_interface
target_link_libraries(subproject1 common_interface)

subproject2/CMakeLists.txt

cmake

复制

# subproject2/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(SubProject2)# 添加子项目的源文件
set(SOURCES main.cpp)# 创建可执行文件
add_executable(subproject2 ${SOURCES})# 链接 common_interface
target_link_libraries(subproject2 common_interface)

3. 重新生成构建系统并编译

在项目根目录下运行以下命令:

bash

复制

cmake -S . -B build
cmake --build build

关键点解释

  1. 接口库 (INTERFACE)

    • 接口库不会生成实际的库文件,它仅用于共享代码和编译选项。

    • 通过 target_sources 和 target_include_directories,可以将 common 目录中的代码和头文件路径共享给子项目。

  2. 子项目链接公共代码

    • 在子项目中,通过 target_link_libraries 链接 common_interface,即可使用 common 目录中的代码。

  3. 避免重复编译

    • 由于 common 目录中的代码被定义为接口库,子项目在链接时不会重复编译这些代码。


示例项目结构

以下是完整的示例项目结构:

根目录:CMakeLists.txt

cmake

复制

cmake_minimum_required(VERSION 3.10)
project(MyProject)# 添加 common 目录中的源文件
file(GLOB COMMON_SOURCES "common/*.cpp" "common/*.h")# 创建一个接口库
add_library(common_interface INTERFACE)# 将 common 目录中的源文件添加到接口库
target_sources(common_interface INTERFACE ${COMMON_SOURCES})# 将 common 目录添加到接口库的头文件搜索路径
target_include_directories(common_interface INTERFACE common)# 添加子项目
add_subdirectory(subproject1)
add_subdirectory(subproject2)
common 目录
  • common/utils.cpp

    cpp

    复制

    #include "utils.h"
    void print_message(const std::string& message) {std::cout << message << std::endl;
    }
  • common/utils.h

    cpp

    复制

    #pragma once
    #include <iostream>
    #include <string>
    void print_message(const std::string& message);
subproject1 目录
  • subproject1/CMakeLists.txt

    cmake

    复制

    cmake_minimum_required(VERSION 3.10)
    project(SubProject1)set(SOURCES main.cpp)add_executable(subproject1 ${SOURCES})target_link_libraries(subproject1 common_interface)
  • subproject1/main.cpp

    cpp

    复制

    #include "utils.h"
    int main() {print_message("Hello from subproject1!");return 0;
    }
subproject2 目录
  • subproject2/CMakeLists.txt

    cmake

    复制

    cmake_minimum_required(VERSION 3.10)
    project(SubProject2)set(SOURCES main.cpp)add_executable(subproject2 ${SOURCES})target_link_libraries(subproject2 common_interface)
  • subproject2/main.cpp

    cpp

    复制

    #include "utils.h"
    int main() {print_message("Hello from subproject2!");return 0;
    }

总结

通过以上方法,你可以在根 CMakeLists.txt 中管理公共代码,并在子项目中共享这些代码,而无需为 common 目录单独创建 CMakeLists.txt。这种方式既保持了代码的模块化,又避免了重复编译。

如果还有其他问题,请随时提问!

方法不错,但是我在qtcreator中,为什么看不到common文件夹

在 Qt Creator 中看不到 common 文件夹,通常是因为 common 目录没有被添加到项目的文件树中。Qt Creator 的文件树视图是基于 CMakeLists.txt 中的 add_subdirectory 或 file(GLOB ...) 等命令来显示的。由于你的 common 目录没有单独的子项目(即没有 add_subdirectory(common)),Qt Creator 默认不会显示它。

以下是解决这个问题的几种方法:


方法 1:将 common 目录添加到文件树中

即使 common 目录不需要单独构建,你也可以通过以下方式让 Qt Creator 显示它。

修改根 CMakeLists.txt

在根 CMakeLists.txt 中,添加一个虚拟目标来包含 common 目录:

cmake

复制

# 添加 common 目录中的源文件
file(GLOB COMMON_SOURCES "common/*.cpp" "common/*.h")# 创建一个虚拟目标(不生成实际的库或可执行文件)
add_custom_target(common SOURCES ${COMMON_SOURCES})# 将 common 目录添加到接口库
add_library(common_interface INTERFACE)
target_sources(common_interface INTERFACE ${COMMON_SOURCES})
target_include_directories(common_interface INTERFACE common)
效果
  • add_custom_target(common SOURCES ...) 会让 Qt Creator 将 common 目录显示在文件树中。

  • 由于这是一个虚拟目标,不会影响实际的构建过程。


方法 2:手动添加 common 目录到 Qt Creator

如果不想修改 CMakeLists.txt,可以通过 Qt Creator 的界面手动添加 common 目录。

  1. 打开 Qt Creator。

  2. 在左侧的 项目模式 中,右键点击项目根目录。

  3. 选择 添加现有目录

  4. 选择 common 目录并确认。

效果
  • common 目录会显示在文件树中,但不会影响构建过程。


方法 3:在子项目中显式引用 common 文件

如果 common 目录中的文件已经在子项目中被引用(例如通过 target_sources),Qt Creator 通常会自动显示这些文件。

示例

在子项目的 CMakeLists.txt 中,显式引用 common 目录中的文件:

cmake

复制

# subproject1/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(SubProject1)# 添加子项目的源文件
set(SOURCES main.cpp)# 添加 common 目录中的源文件
file(GLOB COMMON_SOURCES "../common/*.cpp" "../common/*.h")# 创建可执行文件
add_executable(subproject1 ${SOURCES} ${COMMON_SOURCES})# 链接 common_interface
target_link_libraries(subproject1 common_interface)
效果
  • Qt Creator 会自动将 common 目录中的文件显示在子项目的文件树中。


方法 4:使用 aux_source_directory 命令

aux_source_directory 命令可以将指定目录中的源文件添加到变量中,并让 Qt Creator 显示这些文件。

修改根 CMakeLists.txt

cmake

复制

# 添加 common 目录中的源文件
aux_source_directory(common COMMON_SOURCES)# 创建一个接口库
add_library(common_interface INTERFACE)
target_sources(common_interface INTERFACE ${COMMON_SOURCES})
target_include_directories(common_interface INTERFACE common)
效果
  • aux_source_directory 会让 Qt Creator 将 common 目录显示在文件树中。


方法 5:在 Qt Creator 中手动刷新项目

有时 Qt Creator 的文件树可能没有及时更新。你可以尝试手动刷新项目:

  1. 在 Qt Creator 中,点击 项目模式

  2. 右键点击项目根目录,选择 重新解析项目 或 重新加载项目


总结

  • 推荐方法 1:通过 add_custom_target 让 Qt Creator 显示 common 目录。

  • 推荐方法 3:在子项目中显式引用 common 文件,让 Qt Creator 自动显示。

  • 方法 2 和 方法 4 是备选方案,适用于不想修改 CMakeLists.txt 的情况。

选择适合你的方法即可。如果问题仍然存在,请提供更多上下文信息,我会进一步帮助你!

2 / 2

继续上面的问题,common中,用到了qt的network,该怎么维护cmakelist?

如果 common 目录中的代码使用了 Qt 的 Network 模块,你需要在 CMakeLists.txt 中正确地链接 Qt 的 Network 模块。以下是详细的步骤:


1. 修改根 CMakeLists.txt

在根 CMakeLists.txt 中,确保正确配置 Qt 并链接 Network 模块。

示例:根 CMakeLists.txt

cmake

复制

cmake_minimum_required(VERSION 3.10)
project(MyProject)# 查找 Qt 库
set(CMAKE_AUTOMOC ON)  # 启用自动 MOC
set(CMAKE_AUTORCC ON)  # 启用自动 RCC
set(CMAKE_AUTOUIC ON)  # 启用自动 UICfind_package(Qt6 REQUIRED COMPONENTS Core Network)  # 查找 Qt6 Core 和 Network 模块# 添加 common 目录中的源文件
file(GLOB COMMON_SOURCES "common/*.cpp" "common/*.h")# 创建一个接口库
add_library(common_interface INTERFACE)# 将 common 目录中的源文件添加到接口库
target_sources(common_interface INTERFACE ${COMMON_SOURCES})# 将 common 目录添加到接口库的头文件搜索路径
target_include_directories(common_interface INTERFACE common)# 链接 Qt 的 Core 和 Network 模块到接口库
target_link_libraries(common_interface INTERFACE Qt6::Core Qt6::Network)# 添加子项目
add_subdirectory(subproject1)
add_subdirectory(subproject2)

2. 修改子项目的 CMakeLists.txt

在子项目的 CMakeLists.txt 中,确保链接了 common_interface,这样会自动继承 Qt 的 Core 和 Network 模块。

示例:子项目 subproject1/CMakeLists.txt

cmake

复制

cmake_minimum_required(VERSION 3.10)
project(SubProject1)# 添加子项目的源文件
set(SOURCES main.cpp)# 创建可执行文件
add_executable(subproject1 ${SOURCES})# 链接 common_interface
target_link_libraries(subproject1 common_interface)

3. 在 common 中使用 Qt Network

假设 common 目录中有一个文件使用了 Qt 的 Network 模块,例如 network_utils.cpp

common/network_utils.cpp

cpp

复制

#include "network_utils.h"
#include <QtNetwork/QTcpSocket>void sendData(const QString& host, int port, const QByteArray& data) {QTcpSocket socket;socket.connectToHost(host, port);if (socket.waitForConnected()) {socket.write(data);socket.waitForBytesWritten();}
}
common/network_utils.h

cpp

复制

#pragma once
#include <QString>
#include <QByteArray>void sendData(const QString& host, int port, const QByteArray& data);

4. 确保 Qt Creator 正确显示 common 目录

为了让 Qt Creator 正确显示 common 目录,可以使用以下方法之一:

方法 1:添加虚拟目标

在根 CMakeLists.txt 中添加一个虚拟目标:

cmake

复制

add_custom_target(common SOURCES ${COMMON_SOURCES})
方法 2:显式引用 common 文件

在子项目的 CMakeLists.txt 中显式引用 common 文件:

cmake

复制

file(GLOB COMMON_SOURCES "../common/*.cpp" "../common/*.h")
add_executable(subproject1 ${SOURCES} ${COMMON_SOURCES})

5. 重新生成构建系统并编译

在项目根目录下运行以下命令:

bash

复制

cmake -S . -B build
cmake --build build

6. 验证 Qt Network 模块

在子项目中,尝试使用 common 目录中的网络功能。例如,在 subproject1/main.cpp 中调用 sendData 函数:

cpp

复制

#include "network_utils.h"int main() {sendData("127.0.0.1", 8080, "Hello, Qt Network!");return 0;
}

7. 总结

  • 在根 CMakeLists.txt 中,通过 find_package 查找 Qt 的 Core 和 Network 模块。

  • 将 Network 模块链接到 common_interface 接口库。

  • 在子项目中链接 common_interface,以继承 Qt 的 Core 和 Network 模块。

  • 使用 add_custom_target 或显式引用文件,确保 Qt Creator 正确显示 common 目录。

通过以上步骤,你可以在 common 目录中使用 Qt 的 Network 模块,并确保项目正确构建和显示。如果还有其他问题,请随时提问!


http://www.ppmy.cn/ops/158798.html

相关文章

CTF-web:java-h2 堆叠注入rce -- N1ctf Junior EasyDB

代码存在sql注入 // 处理登录表单的POST请求PostMapping({"/login"})public String handleLogin(RequestParam String username, RequestParam String password, HttpSession session, Model model) throws SQLException {// 验证用户凭据if (this.userService.valid…

Grafana-使用Button修改MySQL数据库

背景 众所周知&#xff0c;Grafana是一个用来展示数据的平台&#xff0c;但是有时候还是会有需求说能不能有一个按钮&#xff0c;点击的时候再对数据库进行修改&#xff0c;从而达到更新数据的效果 经过多方查证&#xff0c;终于实现了一个简单的&#xff0c;点击button执行sq…

ArcGIS注册开发账号及API KEY

注册与激活 Sign up | ArcGIS Location Platform 填写信息&#xff0c;然后邮箱收到激活邮件&#xff0c;激活&#xff0c;再补充信息。 参考 Tutorial: Create an API key | Documentation | Esri Developer 产生API KEY Tutorial: Create an API key | Documentation |…

JavaScript作用域与闭包

一 作用域 在JavaScript中&#xff0c;作用域&#xff08;Scope&#xff09;指的是变量和函数的可访问性范围。在JavaScript中&#xff0c;作用域有全局作用域和局部作用域之分。 全局作用域&#xff08;Global Scope&#xff09;&#xff1a;全局作用域指的是在代码中任何位置…

ASP.NET Core SixLabors.ImageSharp v1.0 的图像实用程序类 web示例

这个小型实用程序库需要将 NuGet SixLabors.ImageSharp包&#xff08;版本 1.0.4&#xff09;添加到.NET Core 3.1/ .NET 6 / .NET 8项目中。它与Windows、Linux和 MacOS兼容。 这已针对 ImageSharp v3.0.1 进行了重新设计。 它可以根据百万像素数或长度乘以宽度来调整图像大…

C++17中的clamp函数

一、std::clamp() 其实在前面简单介绍过这个函数&#xff0c;但当时只是一个集中的说明&#xff0c;为了更好的理解std::clamp的应用&#xff0c;本篇再详细进行阐述一次。std::clamp在C17中其定义的方式为&#xff1a; template< class T > constexpr const T& cl…

二叉树(C语言版)

文章目录 二叉树完全二叉树和满二叉树二叉搜索树基本操作实现代码运行结果 分析红黑树2-3-4树(理论模型)红黑树(实际实现) 二叉树 树是一种层次结构&#xff0c;它在现实生活中是广泛存在的&#xff0c;比如&#xff1a;族谱(family tree)&#xff0c;组织机构&#xff0c;目录…

【个人开发】deepseed+Llama-factory 本地数据多卡Lora微调

文章目录 1.背景2.微调方式2.1 关键环境版本信息2.2 步骤2.2.1 下载llama-factory2.2.2 准备数据集2.2.3 微调模式2.2.4 微调脚本 2.3 踩坑经验2.3.1 问题一&#xff1a;ValueError: Undefined dataset xxxx in dataset_info.json.2.3.2 问题二&#xff1a; ValueError: Target…