当前位置: 首页 > article >正文

使用 CMake 构建 Qt 动态库模块

1. 项目结构与需求分析

典型 Qt 动态库项目布局

ProjectRoot/  
├── CMakeLists.txt              # 主配置  
├── app/  
│   ├── CMakeLists.txt          # 主应用程序配置  
│   └── main.cpp  
├── libs/  
│   ├── CoreLibrary/            # 动态库模块1  
│   │   ├── CMakeLists.txt  
│   │   ├── CoreLibrary.h  
│   │   └── CoreLibrary.cpp  
│   └── NetworkModule/          # 动态库模块2  
│       ├── CMakeLists.txt  
│       ├── NetworkModule.h  
│       └── NetworkModule.cpp  
└── resources/                 # Qt 资源文件(可选)  

核心需求

  • 模块化管理:将功能拆分为独立的动态库
  • 跨平台兼容:兼容 Windows(DLL)、Linux(.so)和 macOS(.dylib)
  • 正确的路径管理:确保构建和运行时依赖路径正确
  • Qt 特性支持:自动处理 MOC、UIC 和 RCC 的生成

2. 基础 CMake 配置(Qt 集成)

CMake 主文件骨架

cmake_minimum_required(VERSION 3.20)  
project(MyQtApp VERSION 1.0 LANGUAGES CXX)  


# 全局默认设定:可执行文件和 DLL 到 bin/, 静态库和导入库(.dll.a)到 lib/
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

# 设置 C++ 标准  
set(CMAKE_CXX_STANDARD 17)  
set(CMAKE_CXX_STANDARD_REQUIRED ON)  

# 查找 Qt 依赖  
find_package(Qt6 COMPONENTS Core Gui Widgets Network REQUIRED)  

# 启用自动处理 MOC/UIC/RCC  
set(CMAKE_AUTOMOC ON)  
set(CMAKE_AUTUIC ON)  
set(CMAKE_AUTORCC ON)  

file(GLOB SOURCE_CPP ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB SOURCE_H ${CMAKE_CURRENT_SOURCE_DIR}/*.h)

set(SOURCE_FILE
    ${SOURCE_CPP}
    ${SOURCE_H}
)
# 添加子目录  
add_subdirectory(libs/CoreLibrary)  
add_subdirectory(libs/NetworkModule)  
add_subdirectory(app)  

add_executable(${PROJECT_NAME} ${SOURCE_FILE})

target_link_libraries(${PROJECT_NAME} Qt6::Widgets CoreLibrary NetworkModule)

3. 动态库模块的创建与配置

示例:子模块CoreLibrary 动态库的 CMakeLists及CoreLibrary.h

# libs/CoreLibrary/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)

project(CoreLibrary VERSION 1.0 LANGUAGES CXX)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 REQUIRED COMPONENTS Widgets)

set(SOURCE_FILE
    CoreLibrary.cpp
    CoreLibrary.h
    CoreLibrary.ui
)

add_library(${PROJECT_NAME} SHARED ${SOURCE_FILE})

target_compile_definitions(${PROJECT_NAME} PRIVATE CORELIBRARY_LIBRARY)

# 显式设置运行时 .dll 到 bin/, 导入库到 lib/
# 跨平台输出路径配置  (根据平台优化)
if(WIN32)
    # Windows: DLL → bin/, 导入库 → lib/
    set_target_properties(${TARGET_NAME} PROPERTIES
            RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
            ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
    )
else()
    # Linux/macOS: 共享库 → lib/
    set_target_properties(${TARGET_NAME} PROPERTIES
            LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
    )
endif()

# 指定库的包含目录
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

target_link_libraries(${PROJECT_NAME} Qt6::Widgets)
# libs/CoreLibrary/CoreLibrary.h
#ifndef CORELIBRARY_H
#define CORELIBRARY_H

#include <QWidget>

#if defined(CORELIBRARY_LIBRARY)
#define CORELIBRARY_EXPORT Q_DECL_EXPORT
#else
#define CORELIBRARY_EXPORT Q_DECL_IMPORT
#endif

QT_BEGIN_NAMESPACE

namespace Ui {
    class CoreLibrary;
}

QT_END_NAMESPACE

class CORELIBRARY_EXPORT CoreLibrary: public QWidget {
    Q_OBJECT

public:
    explicit CoreLibrary(QWidget *parent = nullptr);
    ...

4.总结

1.指定生成动态库

add_library(${PROJECT_NAME} SHARED ${SOURCE_FILE})

2.在编译时定义一个预处理宏 CORELIBRARY_LIBRARY(自定义)

target_compile_definitions(${PROJECT_NAME} PRIVATE CORELIBRARY_LIBRARY)

3.设置 TARGET_NAME 目标的特定属性。主要控制 可执行文件和库的输出目录

# 显式设置运行时 .dll 到 bin/, 导入库到 lib/
# 跨平台输出路径配置  (根据平台优化)
if(WIN32)
    # Windows: DLL → bin/, 导入库 → lib/
    set_target_properties(${TARGET_NAME} PROPERTIES
            RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
            ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
    )
else()
    # Linux/macOS: 共享库 → lib/
    set_target_properties(${TARGET_NAME} PROPERTIES
            LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
    )
endif()

4. 控制符号导出/导入

  • Q_DECL_EXPORT(导出):
    NDBPOOL_LIBRARY 宏被定义时,说明当前代码正在编译 动态库,需要将库中的符号(类、函数)导出,以便其他应用使用。
  • Q_DECL_IMPORT(导入):
    NDBPOOL_LIBRARY 未定义 时,说明当前代码是一个使用该库的应用程序,需要导入符号。

如: 

#if defined(CORELIBRARY_LIBRARY)
#define CORELIBRARY_EXPORT Q_DECL_EXPORT
#else
#define CORELIBRARY_EXPORT Q_DECL_IMPORT
#endif

5.标记 需要导出或导入 的类 

class NDBPOOLSHARED_EXPORT MyClass

 6.在主CMakeLists文件中设置默认输出目录

# 全局默认设定:可执行文件和 DLL 到 bin/, 静态库和导入库(.dll.a)到 lib/
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

http://www.kler.cn/a/573058.html

相关文章:

  • Tick数据20241224
  • 人机交互革命:从触屏到脑波的13维战争
  • grpc工具使用
  • 剑指 Offer II 060. 出现频率最高的 k 个数字
  • 基于RKNN的嵌入式深度学习开发(2)
  • 第3章 nmap网络映射器(网络安全防御实战--蓝军武器库)
  • 大语言模型中温度参数(Temperature)的核心原理
  • 汽车免拆诊断案例 | 2023款丰田雷凌汽油版车行驶中偶尔出现通信故障
  • PHP之字符串拼接
  • NLP如何训练AI模型以理解知识
  • 【Hudi-SQL DDL创建表语法】
  • 01_NLP基础之文本处理的基本方法
  • 【Kubernets】K8S内部nginx访问Service资源原理说明
  • 【C语言】宏定义中X-Micro的使用
  • MySQL 数据库连接池爆满问题排查与解决
  • STM32---FreeRTOS临界段与任务调度器
  • 华为od机试-缓存需要最少金币数 /静态扫描(java)
  • 【C++设计模式】第四篇:建造者模式(Builder)
  • 机器学习-决策树详细解释
  • 算法进阶——枚举