Qt中CMakeLists.txt解释大全
Qt从Qt5.15版本开始正式推荐使用CMake进行项目管理。
在Qt 5.15之前,虽然可以使用CMake进行构建,但Qt官方更推荐使用qmake。
然而,从Qt5.15开始,Qt官方正式推荐使用CMake作为主要的构建系统,并在Qt 6中进一步加强了这一推荐。
以下通过三个样例进行切入,分析一下常用的CMake命令:
一、包含example文件夹(其中为样例工程)和src文件夹(其中为FluentUI库工程)两个工程的总体CMakeLists.txt:
# 指定CMake的最小版本
cmake_minimum_required(VERSION 3.20)
# 定义项目名称和版本,指定使用的语言
project(FluentUI VERSION 1.0)
if (MSVC)
# 让Release也生成pdb文件
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")
endif ()
# ※ list(APPEND CMAKE_MODULE_PATH ...):告诉CMake向CMAKE_MODULE_PATH变量追加新的路径。
# ※ ${CMAKE_CURRENT_SOURCE_DIR}:是一个CMake变量,它指向当前处理的CMakeLists.txt文件所在的目录
# 将当前源代码目录下的.cmake子目录追加到CMAKE_MODULE_PATH中。
# 这样做的效果是,当CMake在执行include()、find_package()或find_file()等命令时,
# 它也会在这个新的路径/.cmake/下搜索指定的模块或文件。
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/.cmake/)
# include(GetGitRevisionDescription)是一个CMake命令,
# 用于包含一个名为GetGitRevisionDescription.cmake的模块,
# 该模块提供了函数和变量,以便从Git版本控制系统中获取当前工作副本的修订信息
# (此处是用在.cmake目录下的GetGitRevisionDescription.cmake中)
include(GetGitRevisionDescription)
# CMake命令,用于定义一个选项,
# 包括:选项名称、选项描述、选项初始值
option(FLUENTUI_BUILD_EXAMPLES "Build FluentUI demo applications." ON)
option(FLUENTUI_BUILD_STATIC_LIB "Build static library." OFF)
# 导入Qt相关依赖包
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
# 添加子目录src
add_subdirectory(src)
# Release也支持日志打印代码位置
target_compile_definitions(fluentuiplugin
PRIVATE
QT_MESSAGELOGCONTEXT
)
if (FLUENTUI_BUILD_EXAMPLES)
# 添加子目录example
add_subdirectory(example)
endif ()
message("------------------------ FluentUI ------------------------")
message("Build FluentUI demo applications.: ${FLUENTUI_BUILD_EXAMPLES}")
message("Build static library.: ${FLUENTUI_BUILD_STATIC_LIB}")
message("Path to FluentUI plugin.: ${FLUENTUI_QML_PLUGIN_DIRECTORY}")
二、example样例工程的CMakeLists.txt:
# 指定CMake的最小版本
cmake_minimum_required(VERSION 3.20)
# 定义项目名称和版本,指定使用的语言
project(example VERSION 1.0)
# 配置通用编译
# ※ 设置了C++编译器的标准为C++17
set(CMAKE_CXX_STANDARD 17)
# ※ 使得CMake在编译时自动包含当前源目录,
# ※ 这通常用于确保ui_<filename>.h和MOC文件可以被正确找到。
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# ※ 开启CMake的自动MOC
# ※ 这意味着CMake会自动为QObject派生类生成MOC代码,无需手动添加MOC步骤
set(CMAKE_AUTOMOC ON)
# ※ 开启CMake的自动RCC
# ※ 这允许CMake自动识别和处理.qrc资源文件
set(CMAKE_AUTORCC ON)
# ※ 确保了编译器必须支持C++17标准
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 判断FluentUI库类型
if (FLUENTUI_BUILD_STATIC_LIB)
add_definitions(-DFLUENTUI_BUILD_STATIC_LIB)
endif ()
# 设置可执行文件输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE})
if (APPLE)
set(APPLICATION_DIR_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.app/Contents/MacOS)
else ()
set(APPLICATION_DIR_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
endif ()
# 导入Qt相关依赖包
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Quick Svg Network)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Quick Svg Network)
# 添加国际化脚本
find_program(QT_LUPDATE NAMES lupdate lupdate-qt6)
find_program(QT_LRELEASE NAMES lrelease lrelease-qt6)
file(GLOB TS_FILE_PATHS ${CMAKE_CURRENT_LIST_DIR}/ *.ts)
add_custom_target(Script-UpdateTranslations
COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts ${PROJECT_NAME}_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts ${PROJECT_NAME}_zh_CN.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
COMMAND ${QT_LRELEASE} ${PROJECT_NAME}_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
COMMAND ${QT_LRELEASE} ${PROJECT_NAME}_zh_CN.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${APPLICATION_DIR_PATH}/i18n
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_NAME}_en_US.qm ${PROJECT_NAME}_zh_CN.qm ${APPLICATION_DIR_PATH}/i18n
SOURCES ${TS_FILE_PATHS}
)
# 生成版本信息头文件
set(HEADER_FILE_VERSION_PATH ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/Version.h)
# configure_file命令用于从.in文件(模板文件)复制并生成一个新文件,
# 同时替换文件中的变量为当前CMake变量的值
configure_file(
${CMAKE_SOURCE_DIR}/.cmake/Version.h.in
${HEADER_FILE_VERSION_PATH}
)
# 遍历所有Cpp文件
file(GLOB_RECURSE CPP_FILES *.cpp *.h)
foreach (filepath ${CPP_FILES})
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
list(APPEND sources_files ${filename})
endforeach (filepath)
if (WIN32)
list(APPEND sources_files "src/app_dmp.h")
endif ()
# 如果是Windows平台,则生成rc文件,还有inno setup脚本文件
set(EXAMPLE_VERSION_RC_PATH "")
if (WIN32)
set(EXAMPLE_VERSION_RC_PATH ${CMAKE_CURRENT_BINARY_DIR}/version_${PROJECT_NAME}.rc)
configure_file(
${CMAKE_SOURCE_DIR}/.cmake/version_exe.rc.in
${EXAMPLE_VERSION_RC_PATH}
)
configure_file(
${CMAKE_SOURCE_DIR}/.cmake/InstallerScript.iss.in
${CMAKE_SOURCE_DIR}/package/InstallerScript.iss
)
endif ()
# 对source_files进行APPEND操作
list(APPEND sources_files ${PROJECT_NAME}.qrc)
# 添加可执行文件
if (WIN32)
list(APPEND sources_files ${EXAMPLE_VERSION_RC_PATH})
endif ()
if (${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(${PROJECT_NAME}
MANUAL_FINALIZATION
${sources_files}
)
else ()
add_executable(${PROJECT_NAME}
${sources_files}
)
endif ()
add_dependencies(${PROJECT_NAME} Script-UpdateTranslations)
# 复制程序运行所需要的动态库
if (WIN32)
if (MSVC)
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
# 用于查找与指定模式匹配的所有文件,并且递归地搜索所有子目录
file(GLOB_RECURSE 3RDPARTY_DLL_DIR ${CMAKE_SOURCE_DIR}/3rdparty/msvc/x86/*.dll)
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
file(GLOB_RECURSE 3RDPARTY_DLL_DIR ${CMAKE_SOURCE_DIR}/3rdparty/msvc/x64/*.dll)
endif ()
elseif (MINGW)
file(GLOB_RECURSE 3RDPARTY_DLL_DIR ${CMAKE_SOURCE_DIR}/3rdparty/mingw/*.dll)
endif ()
file(COPY ${3RDPARTY_DLL_DIR} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
endif ()
# 复制FluentUI源码到运行目录下,用于脚手架生成
file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/source/)
file(COPY ${CMAKE_SOURCE_DIR}/src/ DESTINATION ${APPLICATION_DIR_PATH}/source/)
# 导入component头文件,不然通过QML_NAMED_ELEMENT生成的c++类会找不到头文件报错
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/component
)
# 如果是静态库则需要手动注册插件,导入FluentUI.h头文件
if (FLUENTUI_BUILD_STATIC_LIB)
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_SOURCE_DIR}/src
)
endif ()
# 设置属性
set_target_properties(${PROJECT_NAME} PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER my.${PROJECT_NAME}.com
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
# Release也支持日志打印代码位置
target_compile_definitions(${PROJECT_NAME}
PRIVATE
QT_MESSAGELOGCONTEXT
)
# 目标文件链接库
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::Svg
Qt${QT_VERSION_MAJOR}::Network
fluentuiplugin
)
#添加部署脚本
if (CMAKE_BUILD_TYPE MATCHES "Release")
if (APPLE)
find_program(QT_DEPLOY_QT NAMES macdeployqt)
add_custom_target(Script-DeployRelease
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/dist
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/dist
COMMAND ${QT_DEPLOY_QT} ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME}.app -qmldir=${CMAKE_CURRENT_LIST_DIR}
COMMENT "MacOs Deploying Qt Dependencies After Build........."
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endif ()
if (WIN32)
find_program(QT_DEPLOY_QT NAMES windeployqt)
add_custom_target(Script-DeployRelease
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/dist
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/dist
COMMAND ${QT_DEPLOY_QT} --qmldir=${CMAKE_CURRENT_LIST_DIR} --plugindir ${CMAKE_SOURCE_DIR}/dist/plugins --no-translations --compiler-runtime ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME}.exe
COMMENT "Windows Deploying Qt Dependencies After Build........."
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endif ()
endif ()
三、src中FluentUI库工程的CMakeLists.txt:
# 指定CMake的最小版本
cmake_minimum_required(VERSION 3.20)
# 编译参数设置
option(FLUENTUI_BUILD_STATIC_LIB "Build static library." OFF)
# 设置版本号
# 编译器选项,用于定义一个名为FLUENTUI_VERSION的宏,并将其值设置为1,7,7,0
add_definitions(-DFLUENTUI_VERSION=1,7,7,0)
# 若存在FLUENTUI_BUILD_STATIC_LIB变量,则添加-DFLUENTUI_BUILD_STATIC_LIB选项
# 这个宏可以被C++代码检查,以确定是否应该编译静态库相关的代码路径
if (FLUENTUI_BUILD_STATIC_LIB)
add_definitions(-DFLUENTUI_BUILD_STATIC_LIB)
endif ()
# 导入Qt相关依赖包
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Quick Qml Widgets PrintSupport)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick Widgets PrintSupport)
# 设置Qt SDK路径
set(QT_SDK_DIR "${Qt${QT_VERSION_MAJOR}_DIR}/../../..")
# 规范化Qt SDK路径
cmake_path(SET QT_SDK_DIR NORMALIZE ${QT_SDK_DIR})
# 设置QML插件输出目录,可以通过外部设置,
# 如果外部没有设置就默认到<QT_SDK_DIR_PATH>\qml\FluentUI目录下
set(FLUENTUI_QML_PLUGIN_DIRECTORY "" CACHE PATH "Path to FluentUI plugin")
if (NOT FLUENTUI_QML_PLUGIN_DIRECTORY)
set(FLUENTUI_QML_PLUGIN_DIRECTORY ${QT_SDK_DIR}/qml/FluentUI)
endif ()
# 配置通用编译
# ※ 设置了C++编译器的标准为C++17
set(CMAKE_CXX_STANDARD 17)
# ※ 确保了编译器必须支持C++17标准
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (QT_VERSION VERSION_GREATER_EQUAL "6.3")
# ※ 在6.3及以后版本使用,用于设置一些标准项目配置,包括MOC、RCC和UIC的处理
qt_standard_project_setup()
else ()
# ※ 开启CMake的自动MOC
# ※ 这意味着CMake会自动为QObject派生类生成MOC代码,无需手动添加MOC步骤
set(CMAKE_AUTOMOC ON)
# ※ 开启CMake的自动RCC
# ※ 这允许CMake自动识别和处理.qrc资源文件
set(CMAKE_AUTORCC ON)
# ※ 使得CMake在编译时自动包含当前源目录,
# ※ 这通常用于确保ui_<filename>.h和MOC文件可以被正确找到。
set(CMAKE_INCLUDE_CURRENT_DIR ON)
endif ()
if (FLUENTUI_BUILD_STATIC_LIB AND (QT_VERSION VERSION_GREATER_EQUAL "6.2"))
# 定义项目名称和版本,指定使用的语言
project(fluentui VERSION 1.0 LANGUAGES CXX)
else ()
project(fluentuiplugin VERSION 1.0)
endif ()
# ※ list(APPEND CMAKE_MODULE_PATH ...):告诉CMake向CMAKE_MODULE_PATH变量追加新的路径。
# ※ ${CMAKE_CURRENT_SOURCE_DIR}:是一个CMake变量,它指向当前处理的CMakeLists.txt文件所在的目录
# 将当前源代码目录下的.cmake子目录追加到CMAKE_MODULE_PATH中。
# 这样做的效果是,当CMake在执行include()、find_package()或find_file()等命令时,
# 它也会在这个新的路径/.cmake/下搜索指定的模块或文件。
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/.cmake/)
# 国际化,调用lupdate、lrelease生成翻译文件
find_program(QT_LUPDATE NAMES lupdate)
find_program(QT_LRELEASE NAMES lrelease)
if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/fluentui_en_US.qm)
execute_process(COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts fluentui_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
execute_process(COMMAND ${QT_LRELEASE} fluentui_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
endif ()
if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/fluentui_zh_CN.qm)
execute_process(COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts fluentui_zh_CN.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
execute_process(COMMAND ${QT_LRELEASE} fluentui_zh_CN.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
endif ()
# 使用GLOB来查找当前CMakeLists.txt文件所在目录(${CMAKE_CURRENT_LIST_DIR})下所有.qm 文件,
# 并将它们的路径存储在变量QM_FILE_PATHS中
file(GLOB QM_FILE_PATHS ${CMAKE_CURRENT_LIST_DIR}/ *.qm)
# 将上面的这些.qm文件,复制到指定的目标目录
file(COPY ${QM_FILE_PATHS} DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/Qt${QT_VERSION_MAJOR}/imports/FluentUI/i18n")
# 用于查找与指定模式匹配的所有文件,并且递归地搜索所有子目录
# 遍历所有Cpp文件
# ※ string(REPLACE ...):这个CMake命令用于替换字符串中的特定部分。
# ※ ${CMAKE_CURRENT_SOURCE_DIR}:这是CMake变量,指向当前处理的CMakeLists.txt文件所在的目录。
# ※ "":这是要替换的字符串,这里表示将路径中的${CMAKE_CURRENT_SOURCE_DIR}部分替换为空字符串,实际上是去掉这个前缀。
# ※ filename:这是结果变量,存储替换后的文件名(不包含路径)
file(GLOB_RECURSE CPP_FILES *.cpp *.h *.cxx)
foreach (filepath ${CPP_FILES})
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
message(${filename})
list(APPEND sources_files ${filename})
endforeach (filepath)
# 从sources_files列表中移除了三个特定的源文件
list(REMOVE_ITEM sources_files qhotkey/qhotkey_mac.cpp qhotkey/qhotkey_win.cpp qhotkey/qhotkey_x11.cpp)
# 根据条件编译,对source_files进行APPEND操作
if (WIN32)
list(APPEND sources_files qhotkey/qhotkey_win.cpp)
elseif (APPLE)
list(APPEND sources_files qhotkey/qhotkey_mac.cpp)
elseif (UNIX)
list(APPEND sources_files qhotkey/qhotkey_x11.cpp)
endif()
if (WIN32)
set(FLUENTUI_VERSION_RC_PATH ${CMAKE_CURRENT_BINARY_DIR}/version_${PROJECT_NAME}.rc)
# configure_file命令用于从.in文件(模板文件)复制并生成一个新文件,
# 同时替换文件中的变量为当前CMake变量的值
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/.cmake/version_dll.rc.in
${FLUENTUI_VERSION_RC_PATH}
)
endif ()
if (QT_VERSION VERSION_GREATER_EQUAL "6.2")
# 删除fluentuiplugin.cpp与fluentuiplugin.h,这些只要Qt5使用,Qt6不需要
list(REMOVE_ITEM sources_files fluentuiplugin.h fluentuiplugin.cpp)
if (NOT FLUENTUI_BUILD_STATIC_LIB)
list(REMOVE_ITEM sources_files FluentUI.h FluentUI.cpp)
endif ()
# 遍历所有qml文件
file(GLOB_RECURSE QML_PATHS *.qml qmldir)
foreach (filepath ${QML_PATHS})
if (${filepath} MATCHES "Qt${QT_VERSION_MAJOR}/")
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
if (${filename} MATCHES "qmldir")
list(APPEND resource_files ${filename})
else ()
list(APPEND qml_files ${filename})
endif ()
endif ()
endforeach (filepath)
# 遍历所有资源文件
file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp *.js *.qm)
foreach (filepath ${RES_PATHS})
if (${filepath} MATCHES "Qt${QT_VERSION_MAJOR}/")
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
list(APPEND resource_files ${filename})
endif ()
endforeach (filepath)
# 修改资源文件导出路径
foreach (filepath IN LISTS qml_files resource_files)
string(REPLACE "Qt${QT_VERSION_MAJOR}/imports/FluentUI/" "" filename ${filepath})
set_source_files_properties(${filepath} PROPERTIES QT_RESOURCE_ALIAS ${filename})
endforeach ()
endif ()
if (FLUENTUI_BUILD_STATIC_LIB)
set(LIB_TYPE "STATIC")
else ()
set(LIB_TYPE "SHARED")
endif ()
if (FLUENTUI_BUILD_STATIC_LIB)
set(PLUGIN_TARGET_NAME "")
else ()
# 如果是动态库,则使用插件目标作为其自己的支持目标来定义 QML 模块,在这种情况下,模块必须在运行时动态加载,并且不能由其他目标直接链接到
set(PLUGIN_TARGET_NAME ${PROJECT_NAME})
endif ()
# 如果是Windows平台,则生成rc文件
set(FLUENTUI_VERSION_RC_PATH "")
if (WIN32)
set(FLUENTUI_VERSION_RC_PATH ${CMAKE_CURRENT_BINARY_DIR}/version_${PROJECT_NAME}.rc)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/.cmake/version_dll.rc.in
${FLUENTUI_VERSION_RC_PATH}
)
endif ()
if (QT_VERSION VERSION_GREATER_EQUAL "6.2")
# 如果是Qt6.2版本以上,则使用qt_add_library,qt_add_qml_module函数添加资源文件
if (FLUENTUI_BUILD_STATIC_LIB)
set(FLUENTUI_QML_PLUGIN_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/FluentUI)
endif ()
qt_add_library(${PROJECT_NAME} ${LIB_TYPE})
# qt_add_qml_module函数用于添加一个QML模块。
# ※ PLUGIN_TARGET指定插件目标。
# ※ OUTPUT_DIRECTORY指定输出目录。
# ※ VERSION指定模块版本。
# ※ URI指定模块的URI。
# ※ TYPEINFO指定类型信息文件。
# ※ SOURCES包含源文件。
# ※ QML_FILES包含QML文件。
# ※ RESOURCES包含资源文件。
# ※ RESOURCE_PREFIX指定资源前缀。
qt_add_qml_module(${PROJECT_NAME}
PLUGIN_TARGET ${PLUGIN_TARGET_NAME}
OUTPUT_DIRECTORY ${FLUENTUI_QML_PLUGIN_DIRECTORY}
VERSION 1.0
URI "FluentUI"
# 修改qmltypes文件名称。默认fluentuiplugin.qmltypes,使用默认名称有时候import FluentUI 1.0会爆红,所以修改成plugins.qmltypes
TYPEINFO "plugins.qmltypes"
SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH}
QML_FILES ${qml_files}
RESOURCES ${resource_files}
RESOURCE_PREFIX "/qt/qml"
)
else ()
qt_add_resources(QRC_RESOURCES Qt5/imports/fluentui.qrc)
# 如果是Qt6.2版本以下,则使用add_qmlplugin函数添加资源文件,这是个自定义的函数,详情见.cmake/QmlPlugin.cmake
include(QmlPlugin)
# add_qmlplugin函数用于添加QML插件。
# ※ URI和VERSION与Qt 6.2及以上版本中的配置相同。
# ※ SOURCES包含源文件和资源文件。
# ※ QMLFILES包含QML文件。
# ※ QMLDIR指定QML目录。
# ※ BINARY_DIR指定二进制目录。
# ※ LIBTYPE指定库类型
add_qmlplugin(${PROJECT_NAME}
URI "FluentUI"
VERSION 1.0
SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH} ${QRC_RESOURCES}
QMLFILES ${qml_files}
QMLDIR imports/FluentUI
BINARY_DIR ${FLUENTUI_QML_PLUGIN_DIRECTORY}
LIBTYPE ${LIB_TYPE}
)
endif ()
# 用于为目标(如库或可执行文件)添加预处理器宏定义
# 为目标(${PROJECT_NAME})添加一个名为 HAVE_CONFIG_H 的预处理器宏定义,并标记为私有
# ※ 在源代码中,可以使用 #ifdef HAVE_CONFIG_H 来检查这个宏是否定义
# ※ HAVE_CONFIG_H宏定义表明项目中存在一个自动生成的config.h文件,
# ※ 这个文件通常由配置脚本(如autoconf)生成,包含了从configure脚本中提取的配置宏
# ※ 这个宏定义只对 ${PROJECT_NAME} 目标有效,不会影响其他可能链接到这个目标的库或可执行文件
target_compile_definitions(${PROJECT_NAME}
PRIVATE
# 导入qrcode配置文件
HAVE_CONFIG_H
)
# 去掉mingw生成的动态库libxxx前缀lib,不去掉前缀会导致 module "FluentUI" plugin "fluentuiplugin" not found
if (MINGW)
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
# 解决编译器报 too many sections的问题
target_compile_options(${PROJECT_NAME} PRIVATE -Wa,-mbig-obj)
endif ()
# MSVC Debug 添加后缀d,与Qt插件风格保持一致
if (MSVC)
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "d")
endif ()
# 链接库
target_link_libraries(${PROJECT_NAME} PUBLIC
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::Qml
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::PrintSupport
)
if(APPLE)
find_library(CARBON_LIBRARY Carbon)
target_link_libraries(${PROJECT_NAME} PRIVATE ${CARBON_LIBRARY})
elseif(WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE user32)
elseif(UNIX)
if(QT_VERSION_MAJOR STREQUAL "6")
if(QT_VERSION VERSION_LESS "6.2.0")
message(FATAL_ERROR "Qt 6.2.0 or greater is required when using Qt6")
endif()
else()
if(QT_VERSION_MAJOR LESS "6")
find_package(Qt5 REQUIRED COMPONENTS X11Extras)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::X11Extras)
endif()
endif()
target_link_libraries(${PROJECT_NAME} PRIVATE X11)
endif()
# 用于为目标(如库或可执行文件)添加编译时的头文件搜索路径
# ※ ${PROJECT_NAME}:这是变量,代表当前项目的名字。
# ※ 这个变量通常在项目的根 CMakeLists.txt 文件中通过 project() 命令设置
# ※ PRIVATE:这个关键字指定添加的包含目录是私有的,意味着它们只对指定的目标有效,
# ※ 不会传递给链接到这个目标的其他目标
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/qmlcustomplot
)
# 在Qt版本为6或更早的版本,并且构建类型为发布模式时,
# 使用qmlplugindump工具生成QML类型信息文件(plugins.qmltypes)
if ((${QT_VERSION_MAJOR} LESS_EQUAL 6) AND (CMAKE_BUILD_TYPE MATCHES "Release"))
# find_program:这个CMake命令用于查找名为qmlplugindump的程序。
# QML_PLUGIN_DUMP:这是一个变量,存储找到的qmlplugindump程序的路径。
# NAMES qmlplugindump:指定要查找的程序名称
find_program(QML_PLUGIN_DUMP NAMES qmlplugindump)
# add_custom_target:这个CMake命令用于添加一个自定义目标,可以执行一系列自定义命令。
# ※ Script-Generate-QmlTypes:这是自定义目标的名称。
# ※ COMMAND:指定要执行的命令。
# ※ ${QML_PLUGIN_DUMP}:这是之前找到的qmlplugindump程序的路径。
# ※ -nonrelocatable:qmlplugindump的一个选项,表示生成的qmltypes文件不包含可重定位的路径。
# ※ FluentUI 1.0:指定QML模块的名称和版本。
# ※ ${CMAKE_CURRENT_BINARY_DIR}:这是当前构建目录的路径,qmlplugindump将在这里查找QML插件。
# ※ >:这是一个重定向操作符,将qmlplugindump的输出重定向到plugins.qmltypes文件。
# ※ COMMENT:为这个自定义目标添加一个注释,当构建系统执行这个目标时,会在控制台中显示。
# ※ SOURCES:指定这个自定义目标依赖的文件,尽管这个文件实际上并不用于构建,但它可以被CMake用作 依赖关系检查。
# ※ WORKING_DIRECTORY:指定执行命令时的工作目录
add_custom_target(Script-Generate-QmlTypes
COMMAND ${QML_PLUGIN_DUMP} -nonrelocatable FluentUI 1.0 ${CMAKE_CURRENT_BINARY_DIR} > ${CMAKE_CURRENT_SOURCE_DIR}/Qt5/imports/FluentUI/plugins.qmltypes
COMMENT "Generate qmltypes........."
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Qt5/imports/FluentUI/plugins.qmltypes
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endif()
# 安装
# ※ 这行命令的作用是将${FLUENTUI_QML_PLUGIN_DIRECTORY}目录及其内容安装到${CMAKE_INSTALL_PREFIX}/imports目录下。
# ※ 这意味着,当用户运行安装命令(如make install或cmake --install)时,${FLUENTUI_QML_PLUGIN_DIRECTORY}目录中的所有文件和子目录将被复制到${CMAKE_INSTALL_PREFIX}/imports目录中
install(DIRECTORY ${FLUENTUI_QML_PLUGIN_DIRECTORY} DESTINATION ${CMAKE_INSTALL_PREFIX}/imports)