概述:一般在开发UI应用时候我们都会存在多个子项目,比如一个是主UI界面的项目,有些动态库的项目,主UI中用到子项目中的动态库,我们来看看如何利用cmake来构建这样的一个工程,方便我们在跨平台中开发(macos、windows、linux)
前提条件:安装了CMake Qt5开发环境
1、工程的项目结构
1.1 目录说明
CCQTAPP目录 :项目的主目录
CMakeLists.txt: 项目的主CMakeLists.txt
cc-desktop目录: 主程序(主要是UI)
cc-engine目录: 提供给主程序调用的动态库(主要提供一些数据获取接口或者其他逻辑)
2、项目主CMakeLists.txt
cmake_minimum_required(VERSION 3.6)
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "My multi config types" FORCE)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set_property(GLOBAL PROPERTY AUTOGEN_TARGETS_FOLDER AutoMoc)
if(UNIX AND NOT APPLE)
set(LINUX 1)
endif(UNIX AND NOT APPLE)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
project(CcQtApp)
if(WIN32)
add_definitions("/wd4819")
elseif(APPLE)
SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.12")
endif(WIN32)
macro(ADD_FRAMEWORK fwname appname)
find_library(FRAMEWORK_${fwname}
NAMES ${fwname}
PATHS ${CMAKE_OSX_SYSROOT}/System/Library
PATH_SUFFIXES Frameworks
NO_DEFAULT_PATH)
if( ${FRAMEWORK_${fwname}} STREQUAL FRAMEWORK_${fwname}-NOTFOUND)
MESSAGE(ERROR ": Framework ${fwname} not found")
else()
TARGET_LINK_LIBRARIES(${appname} ${FRAMEWORK_${fwname}})
MESSAGE(STATUS "Framework ${fwname} found at ${FRAMEWORK_${fwname}}")
endif()
endmacro(ADD_FRAMEWORK)
if(WIN32)
set(QtVersion 5.14)
elseif(APPLE)
set(QtVersion 5.7)
elseif(LINUX)
set(QtVersion 5.14)
endif()
# 将项目目录组织化的宏,使用cmake的source_group函数
macro(cc_source_group_by_dir source_files)
set(sgbd_cur_dir ${CMAKE_CURRENT_SOURCE_DIR}/)
foreach(sgbd_file ${${source_files}})
string(REGEX REPLACE ${sgbd_cur_dir} "" sgbd_fpath ${sgbd_file})
string(REGEX REPLACE "[^/\\\\]+$" "" sgbd_group_name ${sgbd_fpath})
if(sgbd_group_name)
string(REPLACE "/" "\\\\" sgbd_group_name_normal ${sgbd_group_name})
source_group(${sgbd_group_name_normal} FILES ${sgbd_file})
endif(sgbd_group_name)
endforeach(sgbd_file)
endmacro(cc_source_group_by_dir)
# 添加子项目cc-desktop
add_subdirectory(cc-desktop)
# 添加子项目cc-engine
add_subdirectory(cc-engine)
3、子项目cc-desktop
3.1 cc-desktop的CMakeLists.txt
cmake_minimum_required(VERSION 3.6)
project(CcQtApp)
SET(CMAKE_PREFIX_PATH $ENV{QTDIR})
find_package(Qt5Core $ENV{QTVERSION} REQUIRED)
find_package(Qt5Concurrent $ENV{QTVERSION} REQUIRED)
find_package(Qt5Sql $ENV{QTVERSION} REQUIRED)
find_package(Qt5Gui $ENV{QTVERSION} REQUIRED)
find_package(Qt5Widgets $ENV{QTVERSION} REQUIRED)
find_package(Qt5Network $ENV{QTVERSION} REQUIRED)
find_package(Qt5Multimedia $ENV{QTVERSION} REQUIRED)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
FILE(GLOB_RECURSE FORMS "*.ui")
QT5_WRAP_UI(FORMS_UIC ${FORMS})
file(GLOB_RECURSE All_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.mm
${CMAKE_CURRENT_SOURCE_DIR}/*.m
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/*.mm
${CMAKE_CURRENT_SOURCE_DIR}/*.c
${CMAKE_CURRENT_SOURCE_DIR}/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/*.hh
${CMAKE_CURRENT_SOURCE_DIR}/*.h
${CMAKE_CURRENT_SOURCE_DIR}/*.hpp)
cc_source_group_by_dir(All_SOURCES)
include_directories(${Qt5Core_PRIVATE_INCLUDE_DIRS}
${Qt5Widgets_PRIVATE_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../cc-engine/include
)
if(WIN32)
set(exe_property WIN32)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD /Zi /MP /Gm- /Qpar /wd4996")
if(${close_optimize} STREQUAL "ON")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Od")
endif()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF /LARGEADDRESSAWARE")
add_definitions(-DUNICODE -D_UNICODE -D_SCL_SECURE_NO_WARNINGS -DWIN32 -DV_LOG -DCURL_STATICLIB)
link_directories(${CMAKE_CURRENT_BINARY_DIR}/../cc-engine/$(CONFIGURATION))
set(LINK_LIBRARY CcEngine.lib)
elseif(APPLE)
SET(BUILD_WITH_INSTALL_RPATH TRUE)
set(exe_property MACOSX_BUNDLE)
set (CMAKE_CXX_FLAGS "--std=gnu++11 ${CMAKE_CXX_FLAGS}")
message("CMAKE_OSX_DEPLOYMENT_TARGET is ${CMAKE_OSX_DEPLOYMENT_TARGET}")
message(${CMAKE_CURRENT_BINARY_DIR})
set(LINK_LIBRARY libCcEngine.dylib)
link_directories(${CMAKE_CURRENT_BINARY_DIR}/../cc-engine/$(CONFIGURATION))
elseif(LINUX)
SET(CMAKE_BUILD_TYPE Debug)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif(WIN32)
set(NAME CcApp)
add_executable(${NAME} ${exe_property} ${All_SOURCES} ${FORMS_UIC} ${MACOSX_BUNDLE_ICON_FILE})
if(WIN32)
elseif(APPLE)
ADD_FRAMEWORK(AVFoundation CcApp)
ADD_FRAMEWORK(Foundation CcApp)
ADD_FRAMEWORK(Security CcApp)
ADD_FRAMEWORK(Carbon CcApp)
ADD_FRAMEWORK(Appkit CcApp)
ADD_FRAMEWORK(VideoDecodeAcceleration CcApp)
ADD_FRAMEWORK(VideoToolbox CcApp)
ADD_FRAMEWORK(SystemConfiguration CcApp)
set_target_properties(CcApp PROPERTIES XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym")
set_target_properties(CcApp PROPERTIES XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS "YES")
set_target_properties(CcApp PROPERTIES XCODE_ATTRIBUTE_SEPARATE_STRIP "YES")
set_target_properties(CcApp PROPERTIES XCODE_ATTRIBUTE_STRIP_STYLE "Non-Global Symbols")
endif(WIN32)
if(APPLE)
set_target_properties(${NAME} PROPERTIES XCODE_ATTRIBUTE_ARCHS "x86_64")
endif()
if(WIN32)
qt5_use_modules(${NAME} WinExtras)
elseif(APPLE)
endif(WIN32)
qt5_use_modules(${NAME} Core)
qt5_use_modules(${NAME} Concurrent)
qt5_use_modules(${NAME} Sql)
qt5_use_modules(${NAME} Gui)
qt5_use_modules(${NAME} Widgets)
qt5_use_modules(${NAME} Network)
qt5_use_modules(${NAME} Multimedia)
qt5_use_modules(${NAME} WebEngineWidgets)
qt5_use_modules(${NAME} WebChannel)
target_link_libraries(${NAME} ${LINK_LIBRARY})
3.2 cc-desktop的main.cpp文件
#include <QApplication>
#include <QWidget>
#include <QDebug>
//cc-engine里面生成的动态库
#include "CcDataManage.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
window.resize(650, 350);
window.setWindowTitle("简单的cmake构建的Qt窗口程序");
window.show();
CcDataManage data_manage;
qDebug() << "Get Data From cc-engine dynamic library: " << data_manage.GetCurrentJsonData();
return app.exec();
}
4、子项目cc-engine
4.1 cc-engine的CMakeLists.txt
这个主要是生成动态库
cmake_minimum_required(VERSION 3.6)
project(CCEngine)
SET(CMAKE_PREFIX_PATH $ENV{QTDIR})
# 找到Qt相关库并导入项目,确保其被正确安装在系统中
find_package(Qt5Core $ENV{QTVERSION} REQUIRED)
find_package(Qt5Gui $ENV{QTVERSION} REQUIRED)
find_package(Qt5Widgets $ENV{QTVERSION} REQUIRED)
find_package(Qt5Network $ENV{QTVERSION} REQUIRED)
file(GLOB_RECURSE All_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/*.c
${CMAKE_CURRENT_SOURCE_DIR}/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/*.mm
${CMAKE_CURRENT_SOURCE_DIR}/*.hh
${CMAKE_CURRENT_SOURCE_DIR}/*.h)
cc_source_group_by_dir(All_SOURCES)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${Qt5Core_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/include)
if(WIN32)
set(exe_property WIN32)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT /Zi /MP /Qpar /Gm-")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")
add_definitions(-DUNICODE -D_UNICODE -D_SCL_SECURE_NO_WARNINGS -DWIN32 -DCCENGINE_LIB -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB)
elseif(APPLE)
SET(BUILD_WITH_INSTALL_RPATH TRUE)
set(exe_property MACOSX_BUNDLE)
set (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
add_definitions(-DQT_CORE_LIB -DQT_GUI_LIB)
elseif(LINUX)
endif(WIN32)
set(NAME CcEngine)
# 生成动态库CcEngine.dylib
add_library(${NAME} SHARED ${All_SOURCES})
if(WIN32)
add_custom_command(TARGET CcEngine PRE_BUILD COMMAND if exist ${CMAKE_CURRENT_BINARY_DIR}/$(Configuration) cmake -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/$(Configuration))
elseif(APPLE)
set_target_properties(${NAME} PROPERTIES XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym")
set_target_properties(${NAME} PROPERTIES XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS "YES")
set_target_properties(${NAME} PROPERTIES XCODE_ATTRIBUTE_SEPARATE_STRIP "YES")
set_target_properties(${NAME} PROPERTIES XCODE_ATTRIBUTE_STRIP_STYLE "Non-Global Symbols")
target_link_libraries(${NAME} "-framework CoreVideo" "-framework CoreImage" "-framework CoreGraphics" "-framework AVFoundation")
endif()
if(APPLE)
set_target_properties(${NAME} PROPERTIES XCODE_ATTRIBUTE_ARCHS "x86_64")
endif()
# 将Qt的相关模块链接到相关目标(target)中,以使得目标能够使用Qt的相关模块功能
qt5_use_modules(${NAME} Core)
qt5_use_modules(${NAME} Gui)
qt5_use_modules(${NAME} Widgets)
qt5_use_modules(${NAME} Network)
target_link_libraries(CcEngine ${Qt5Core_LIBRARIES} ${LINK_LIBRARY})
5、生成项目
5.1 生成xcode工程
1.主目录中新建build
2. cd build
3. cmake -G"Xcode" ..
5.2 生成vistual stdio 2019项目
1.在主目录中新建build
2.cd build
3.cmake -G"Visual Studio 16 2019" -A Win32 ..
4.在build里面打开CcQtApp.sln解决方案
6、gitee上有这个项目工程的源码
windows macos linux都可以用这个CMake来构建
链接地址: CcQtApp: Qt测试demo