整体结构:
最外层的cmakelist
CMakeLists.txt
project(cmakeMulPackage)
cmake_minimum_required(VERSION 3.17)
set(CMAKE_CXX_STANDARD 11)
#设置环境相关
message("====================set env.cmake===================")
message("CMAKE_BUILD_TYPE is ${CMAKE_BUILD_TYPE}")
set(PROJECT_LIBRARY_DIR ${PROJECT_SOURCE_DIR}/Library)
set(PROJECT_LIBRARY_INCLUDE_DIR ${PROJECT_LIBRARY_DIR}/${CMAKE_BUILD_TYPE}/include)
set(PROJECT_LIBRARY_LIB_DIR ${PROJECT_LIBRARY_DIR}/${CMAKE_BUILD_TYPE}/lib)
set(PROJECT_LIBRARY_DLL_DIR ${PROJECT_LIBRARY_DIR}/${CMAKE_BUILD_TYPE}/dll)
message("PROJECT_LIBRARY_DIR is ${PROJECT_LIBRARY_DIR}")
message("PROJECT_LIBRARY_INCLUDE_DIR is ${PROJECT_LIBRARY_INCLUDE_DIR}")
message("PROJECT_LIBRARY_LIB_DIR is ${PROJECT_LIBRARY_LIB_DIR}")
message("PROJECT_LIBRARY_DLL_DIR is ${PROJECT_LIBRARY_DLL_DIR}")
#同时生成lib与DLL
message("PROJECT_BINARY_DIR is ${PROJECT_BINARY_DIR}")
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) #DLL生成路径
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) #lib生成路径
set(CMAKE_PDB_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) #pdb生成路径
# 处理编译字符集问题
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
#设置QT相关配置
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_PREFIX_PATH D:/Library/Qt5.14.2/5.14.2/msvc2017_64/lib/cmake) # 配置QT路径
find_package(Qt5 COMPONENTS # 查找QT的模块
Core
Gui
Widgets
REQUIRED)
message(STATUS "CMAKE_PREFIX_PATH is ${CMAKE_PREFIX_PATH}")
message("====================set include path.cmake===================")
#定义头文件需要寻址的路径
include_directories(
${PROJECT_LIBRARY_INCLUDE_DIR} #头文件
App/include #模块头文件
AppModuleA/include #模块头文件
AppModuleB/include #模块头文件
)
#定义库文件需要寻址的路径
link_directories(
${PROJECT_LIBRARY_LIB_DIR}
)
message("====================set sub directory.cmake===================")
#添加一个子目录并构建该子目录
add_subdirectory(AppModuleA)
add_subdirectory(AppModuleB)
add_subdirectory(App)
主程序
CMakeLists.txt
#定义头文件路径
include_directories(./include)
#把目录src和inc下面的所有文件作为变量存储
file(GLOB_RECURSE SRC_FILES "src/*")
file(GLOB_RECURSE INC_FILES "include/*")
# 针对存在Q_OBJECT宏的文件,需要MOC,则把其他模块的.h文件加进来了
set(MOC_FILES
${PROJECT_SOURCE_DIR}/AppModuleB/include/module_b.h
)
#生成可执行exe
add_executable(cmakeMulPackage ${SRC_FILES} ${INC_FILES} ${MOC_FILES})
#加载依赖的库
target_link_libraries(cmakeMulPackage
AppModuleA
AppModuleB
)
#将生成的依赖复制到可执行目录下
message("====================set copy final.cmake===================")
file(GLOB_RECURSE MY_COMPONENTS "${PROJECT_LIBRARY_DLL_DIR}/*")
if (WIN32 AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
#拷贝依赖的DLL和exe
foreach (MY_COMPONENT ${MY_COMPONENTS})
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${MY_COMPONENT}" "${PROJECT_BINARY_DIR}")
message(STATUS "COPY DLL ${MY_COMPONENT}")
endforeach (MY_COMPONENT)
endif ()
main_app.h
//
// Created by zhe.xiao on 2023/12/15.
//
#pragma once
#include <iostream>
class MainApp
{
public:
static void run();
};
main_app.cpp
//
// Created by zhe.xiao on 2023/12/15.
//
#include "main_app.h"
#include "module_a.h"
#include "module_b.h"
void MainApp::run()
{
std::cout << "hello main" << "\n";
ModuleA::run();
auto moduleA = new ModuleB();
moduleA->start();
auto tModule = new ModuleB();
tModule->start();
std::this_thread::sleep_for(std::chrono::seconds(10));
}
main.cpp
#include "main_app.h"
int main() {
MainApp::run();
return 0;
}
AppModuleA 子模块
CMakeLists.txt
#定义头文件路径
include_directories(./include)
#把目录src和inc下面的所有文件作为变量存储
file(GLOB_RECURSE SRC_FILES "src/*")
file(GLOB_RECURSE INC_FILES "include/*")
#生成库
add_library(AppModuleA SHARED ${SRC_FILES} ${INC_FILES})
module_a.h
//
// Created by zhe.xiao on 2023/12/15.
//
#pragma once
class ModuleA
{
public:
static void run();
};
module_a.cpp
//
// Created by zhe.xiao on 2023/12/15.
//
#include "module_a.h"
#include <iostream>
void ModuleA::run()
{
std::cout << "ModuleA run" << "\n";
}
AppModuleB 子模块
CMakeLists.txt
#定义头文件路径
include_directories(./include)
#把目录src和inc下面的所有文件作为变量存储
file(GLOB_RECURSE SRC_FILES "src/*")
file(GLOB_RECURSE INC_FILES "include/*")
#生成库
add_library(AppModuleB SHARED ${SRC_FILES} ${INC_FILES})
#添加依赖库
target_link_libraries(AppModuleB Qt5::Core)
module_b.h
//
// Created by zhe.xiao on 2023/12/15.
//
#pragma once
#include <QThread>
class ModuleB: public QThread
{
Q_OBJECT
public:
ModuleB(QObject* parent = nullptr);
~ModuleB();
protected:
void run();
};
module_b.cpp
//
// Created by zhe.xiao on 2023/12/15.
//
#include "module_b.h"
#include <iostream>
#include <QString>
ModuleB::ModuleB(QObject* parent) : QThread(parent)
{
}
ModuleB::~ModuleB()
{
}
void ModuleB::run()
{
std::cout << "ModuleB run" << "\n";
QString data("QString data");
std::cout << data.toStdString() << "\n";
}
三方依赖的DLL和头文件
主要通过设置环境变量定义具体路径。
然后通过add_custom_command进行拷贝dll到生成路径
message("====================set copy final.cmake===================")
file(GLOB_RECURSE MY_COMPONENTS "${PROJECT_LIBRARY_DLL_DIR}/*")
if (WIN32 AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
#拷贝依赖的DLL和exe
foreach (MY_COMPONENT ${MY_COMPONENTS})
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${MY_COMPONENT}" "${PROJECT_BINARY_DIR}")
message(STATUS "COPY DLL ${MY_COMPONENT}")
endforeach (MY_COMPONENT)
endif ()