我的项目是:有一个根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),这样可以在子项目中共享这些代码,而无需重复编译。
复制
# 根 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
:
复制
# 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
:
复制
# 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
关键点解释
-
接口库 (
INTERFACE
):-
接口库不会生成实际的库文件,它仅用于共享代码和编译选项。
-
通过
target_sources
和target_include_directories
,可以将common
目录中的代码和头文件路径共享给子项目。
-
-
子项目链接公共代码:
-
在子项目中,通过
target_link_libraries
链接common_interface
,即可使用common
目录中的代码。
-
-
避免重复编译:
-
由于
common
目录中的代码被定义为接口库,子项目在链接时不会重复编译这些代码。
-
示例项目结构
以下是完整的示例项目结构:
根目录: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)
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_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_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
目录:
复制
# 添加 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
目录。
-
打开 Qt Creator。
-
在左侧的 项目模式 中,右键点击项目根目录。
-
选择 添加现有目录。
-
选择
common
目录并确认。
效果
-
common
目录会显示在文件树中,但不会影响构建过程。
方法 3:在子项目中显式引用 common
文件
如果 common
目录中的文件已经在子项目中被引用(例如通过 target_sources
),Qt Creator 通常会自动显示这些文件。
示例
在子项目的 CMakeLists.txt
中,显式引用 common
目录中的文件:
复制
# 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
复制
# 添加 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 的文件树可能没有及时更新。你可以尝试手动刷新项目:
-
在 Qt Creator 中,点击 项目模式。
-
右键点击项目根目录,选择 重新解析项目 或 重新加载项目。
总结
-
推荐方法 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_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_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
中添加一个虚拟目标:
复制
add_custom_target(common SOURCES ${COMMON_SOURCES})
方法 2:显式引用 common
文件
在子项目的 CMakeLists.txt
中显式引用 common
文件:
复制
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
模块,并确保项目正确构建和显示。如果还有其他问题,请随时提问!