概述:一般在开发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/LibraryPATH_SUFFIXES FrameworksNO_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