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(fluentuipluginPRIVATEQT_MESSAGELOGCONTEXT
)if (FLUENTUI_BUILD_EXAMPLES)# 添加子目录exampleadd_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-UpdateTranslationsCOMMAND ${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}/i18nCOMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_NAME}_en_US.qm ${PROJECT_NAME}_zh_CN.qm ${APPLICATION_DIR_PATH}/i18nSOURCES ${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} PROPERTIESMACOSX_BUNDLE_GUI_IDENTIFIER my.${PROJECT_NAME}.comMACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}MACOSX_BUNDLE TRUEWIN32_EXECUTABLE TRUE
)# Release也支持日志打印代码位置
target_compile_definitions(${PROJECT_NAME}PRIVATEQT_MESSAGELOGCONTEXT
)# 目标文件链接库
target_link_libraries(${PROJECT_NAME} PRIVATEQt${QT_VERSION_MAJOR}::QuickQt${QT_VERSION_MAJOR}::SvgQt${QT_VERSION_MAJOR}::Networkfluentuiplugin
)#添加部署脚本
if (CMAKE_BUILD_TYPE MATCHES "Release")if (APPLE)find_program(QT_DEPLOY_QT NAMES macdeployqt)add_custom_target(Script-DeployReleaseCOMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/distCOMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/distCOMMAND ${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.txtWORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})endif ()if (WIN32)find_program(QT_DEPLOY_QT NAMES windeployqt)add_custom_target(Script-DeployReleaseCOMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/distCOMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/distCOMMAND ${QT_DEPLOY_QT} --qmldir=${CMAKE_CURRENT_LIST_DIR} --plugindir ${CMAKE_SOURCE_DIR}/dist/plugins --no-translations --compiler-runtime ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME}.exeCOMMENT "Windows Deploying Qt Dependencies After Build........."SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txtWORKING_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.0URI "FluentUI"# 修改qmltypes文件名称。默认fluentuiplugin.qmltypes,使用默认名称有时候import FluentUI 1.0会爆红,所以修改成plugins.qmltypesTYPEINFO "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.cmakeinclude(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.0SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH} ${QRC_RESOURCES}QMLFILES ${qml_files}QMLDIR imports/FluentUIBINARY_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} PUBLICQt${QT_VERSION_MAJOR}::CoreQt${QT_VERSION_MAJOR}::QuickQt${QT_VERSION_MAJOR}::QmlQt${QT_VERSION_MAJOR}::WidgetsQt${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-QmlTypesCOMMAND ${QML_PLUGIN_DUMP} -nonrelocatable FluentUI 1.0 ${CMAKE_CURRENT_BINARY_DIR} > ${CMAKE_CURRENT_SOURCE_DIR}/Qt5/imports/FluentUI/plugins.qmltypesCOMMENT "Generate qmltypes........."SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Qt5/imports/FluentUI/plugins.qmltypesWORKING_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)
相关文章:
Qt中CMakeLists.txt解释大全
Qt从Qt5.15版本开始正式推荐使用CMake进行项目管理。 在Qt 5.15之前,虽然可以使用CMake进行构建,但Qt官方更推荐使用qmake。 然而,从Qt5.15开始,Qt官方正式推荐使用CMake作为主要的构建系统,并在Qt 6中进一步加强了…...
【在 PyTorch 中使用 tqdm 显示训练进度条,并解决常见错误TypeError: ‘module‘ object is not callable】
在 PyTorch 中使用 tqdm 显示训练进度条,并解决常见错误TypeError: module object is not callable 在进行深度学习模型训练时,尤其是在处理大规模数据时,实时了解训练过程中的进展是非常重要的。为了实现这一点,我们可以使用 tq…...
数据结构-堆的实现和应用
目录 1.堆的概念 2.堆的构建 3.堆的实现 4.堆的功能实现 4.1堆的初始化 4.2堆的销毁 4.3堆的插入 4.3.1向上调整 4.4堆的删除 4.4.1向下调整法 编辑4.5取堆顶 5. 向上调整法和向下调整法比较 6.堆的应用 6.1TOP-K问题 6.2TOP-K思路 6.2.1用前n个数据来建堆 6.…...
数据分析的尽头是web APP?
数据分析的尽头是web APP? 在做了一些数据分析的项目,也制作了一些数据分析相关的web APP之后,总结自己的一些想法和大家分享。 1.web APP是呈现数据分析结果的另外一种形式。 数据分析常见的结果是数据分析报告,可以是PPT或者…...
YOLO系列论文综述(从YOLOv1到YOLOv11)【第3篇:YOLOv1——YOLO的开山之作】
YOLOv1 1 摘要2 YOLO: You Only Look Once2.1 如何工作2.2 网络架构2.3 训练2.4 优缺点 YOLO系列博文: 【第1篇:概述物体检测算法发展史、YOLO应用领域、评价指标和NMS】【第2篇:YOLO系列论文、代码和主要优缺点汇总】 ——————————…...
容器和它的隔离机制
什么是容器和它的隔离机制? 容器 是一种轻量化的虚拟化技术,它允许多个应用程序共享同一个操作系统(OS)内核,同时为每个应用程序提供自己的运行环境。容器通过利用 Linux 的内核功能(如 Namespaces 和 Cgr…...
【数据结构与算法】排序算法总结:冒泡 / 快排 / 直接插入 / 希尔 / 简单选择 / 堆排序 / 归并排序
1 排序 1.1 冒泡 内排序的交换排序类别 1.1.1 普通实现 public class BubbleSort {/*** 基本的 冒泡排序*/public static void bubbleSort(int[] srcArray) {int i,j; // 用于存放数组下标int temp 0; // 用于交换数值时临时存放值for(i0;i<srcArray.length-1;i){// j …...
Windows Serv 2019 虚拟机 安装Oracle19c,图文详情(超详细)
1、下载安装文件 Oracle官网下载直链:https://www.oracle.com/database/technologies/oracle-database-software-downloads.html#db_ee 夸克网盘下载:https://pan.quark.cn/s/1460a663ee83 2、新建 Windows Server 2019 虚拟机 (超详细&a…...
数字孪生开发之 Three.js 插件资源库(2)
在当今数字化快速发展的时代,数字孪生技术正逐渐成为各个领域的关键技术之一。它通过创建物理实体的虚拟副本,实现对实体的实时监测、模拟和优化,为企业和组织带来了诸多好处,如提高生产效率、降低成本、改进产品质量等。然而&…...
小米C++ 面试题及参考答案下(120道面试题覆盖各种类型八股文)
指针和引用的区别?怎么实现的? 指针和引用有以下一些主要区别。 从概念上来说,指针是一个变量,它存储的是另一个变量的地址。可以通过指针来间接访问所指向的变量。例如,我们定义一个整型指针int *p;,它可以指向一个整型变量的内存地址。而引用是一个别名,它必须在定义的…...
OpenOCD之J-Link下载
NOTE:此篇文章由笔者的 VSCode编辑GCC for ARM交叉编译工具链Makefile构建OpenOCD调试(基于STM32的标准库)派生而来。 1.下载USB Dirver Tool.exe,选择J-Link dirver,替换成WinUSB驱动。(⭐USB Dirver Tool…...
华为云云连接+squid进行正向代理上网冲浪
1 概述 Squid是一个高性能的代理缓存服务器,主要用于缓冲Internet数据。它支持多种协议,包括FTP、gopher、HTTPS和HTTP。Squid通过一个单独的、非模块化的、I/O驱动的进程来处理所有的客户端请求,这使得它在处理请求时具有较高的效率。…...
情绪识别项目
文章目录 1、mp4s文件转mp3文件2、Audition下载3、Audition安装4、Audition使用: 1、mp4s文件转mp3文件 在线转:Convert audio to MP3(https://audio.online-convert.com/convert-to-mp3) 2、Audition下载 Audition CC2019/64位…...
【RISC-V CPU debug 专栏 2.2 -- Hart DM States】
文章目录 Hart DM StatesHart 的 DM 状态1. 不存在(Non-existent)2. 不可用(Unavailable)3. 运行(Running)4. 暂停(Halted)状态转换与复位行为状态指示信号Hart DM States 在 RISC-V 调试架构中,每个可以被选择的硬件线程(hart)处于以下四种调试模块(DM)状态之一…...
从零样本到少样本学习:一文读懂 Zero-shot、One-shot 和 Few-shot 的核心原理与应用!
爆款标题: 《从零样本到少样本学习:一文读懂 Zero-shot、One-shot 和 Few-shot 的核心原理与应用!》 正文: 在自然语言处理(NLP)领域,Zero-shot、One-shot 和 Few-shot 学习已经成为衡量大语言…...
【LC】3101. 交替子数组计数
题目描述: 给你一个二进制数组nums 。如果一个子数组中 不存在 两个 相邻 元素的值 相同 的情况,我们称这样的子数组为 交替子数组 。返回数组 nums 中交替子数组的数量。 示例 1: 输入: nums [0,1,1,1] 输出: 5 …...
如何构建SAAS项目
在后台使用JDBC方式动态创建用户输入的数据库信息(库名、地址、用户名、密码) 执行预先写好的sql文件(如mybatis的scriptRunner)执行建表语句及插入基础数据(管理员用户、普通用户)...
树莓派搭建NextCloud:给数据一个安全的家
前言 NAS有很多方案,常见的有 Nextcloud、Seafile、iStoreOS、Synology、ownCloud 和 OpenMediaVault ,以下是他们的特点: 1. Nextcloud 优势: 功能全面:支持文件同步、共享、在线文档编辑、视频会议、日历、联系人…...
深入解读 MongoDB 查询耗时:Execution 和 Fetching 阶段详解
在使用 MongoDB 时,查询性能的分析与优化是开发者关注的重点。MongoDB 的查询过程通常分为两个主要阶段:Execution(执行阶段)和Fetching(拉取阶段)。每个阶段的耗时代表不同的性能瓶颈,优化思路…...
frida_hook_dlopen(当年到lib目录下找发现一个so都没有,hook下dlopen)
Frida 脚本用于拦截 Android 应用程序中的 dlopen 和 android_dlopen_ext 函数。这两个函数用于动态加载共享库,脚本通过拦截这些函数的调用来记录加载的库的路径。 代码分析 var dlopen Module.findExportByName(null, "dlopen"); // 6.0 var android…...
Zero to JupyterHub with Kubernetes中篇 - Kubernetes 常规使用记录
前言:纯个人记录使用。 搭建 Zero to JupyterHub with Kubernetes 上篇 - Kubernetes 离线二进制部署。搭建 Zero to JupyterHub with Kubernetes 中篇 - Kubernetes 常规使用记录。搭建 Zero to JupyterHub with Kubernetes 下篇 - Jupyterhub on k8s。 参考&…...
WordCloud去掉停用词(fit_words+generate)的2种用法
-------------词云图集合------------- WordCloud去掉停用词(fit_wordsgenerate)的2种用法 通过词频来绘制词云图(jiebaWordCloud) Python教程95:去掉停用词词频统计jieba.tokenize示例用法 将进酒—李白process_t…...
Python 中如何处理异常?
在Python中,异常处理是一种重要的编程技术,它允许开发者优雅地处理程序运行过程中出现的错误或异常情况,而不是让程序直接崩溃。 通过异常处理,我们可以使程序更加健壮、用户友好。 异常处理的基本结构 Python中最基本的异常处…...
C++——多态(下)
目录 引言 多态 4.多态的原理 4.1 虚函数表指针 4.2 多态的原理 5.单继承和多继承关系的虚函数表 5.1 单继承中的虚函数表 5.2 多继承中的虚函数表 结束语 引言 接下来我们继续学习多态。 没有阅读多态(上)的可以点击下面的链接哦~ C——多态…...
qsort函数详解+代码展示
文章目录 概要系列文章目录前言(1) 定义(2) 使用(举例子 上代码)1、定义数组:2、定义比较函数:3、调用 qsort:4、输出结果: (3) 注意事项 小结 概要 本篇博客将详细地介绍qsort排序函数,&#x…...
leetcode hot100【LeetCode 136. 只出现一次的数字】java实现
LeetCode 136. 只出现一次的数字 题目描述 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。 …...
(免费送源码)计算机毕业设计原创定制:Java+ssm+JSP+Ajax SSM棕榈校园论坛的开发
摘要 随着计算机科学技术的高速发展,计算机成了人们日常生活的必需品,从而也带动了一系列与此相关产业,是人们的生活发生了翻天覆地的变化,而网络化的出现也在改变着人们传统的生活方式,包括工作,学习,社交…...
对抗攻击算法:FGSM和PGD
FGSM 传送门 FGSM 利用了梯度上升的思想,通过损失函数相对于输入图像的梯度来找到 最容易 迷惑网络的方向,并沿着这个方向对图像进行微小的扰动。 FGSM 的基本想法是,沿着这个梯度的符号方向对图像进行微调,以最大化损失函数。具…...
【八股文】小米
文章目录 一、vector 和 list 的区别?二、include 双引号和尖括号的区别?三、set 的底层数据结构?四、set 和 multiset 的区别?五、map 和 unordered_map 的区别?六、虚函数和纯虚函数的区别?七、extern C …...
xtu oj 众数
样例输入# 3 1 0 1 2 1 1 2 3 1 1 2 2样例输出# 1 2 3 解题思路:与数组大小有关,先排序 举个例子思考一下 n4 k2 数组为1 2 3 4 如果我们想让众数那个位的值为3(即max3),3出现的次数为3,即众数为3,需要修改多少次…...
做电影网站算侵权吗/百度网盘搜索引擎网站
测试环境:ubuntu18.04driver450cuda11.0cudnn8.0.5opencv4.4.0 1、ubuntu显卡驱动下载安装 2、cuda及cudnn安装 3、opencv4编译配置 4、darknet源码编译测试...
java做网站需要的技术/百度网首页登录入口
昨天花了一个下午才升级成功,今天费了点儿周折才打上补丁,不想同道中人再浪费不必要的时间,把以把我的步骤给大家说一下,供参考。 使用工具:x65Flasher与VK 升级文件及工具下载:http://yizhe.net/c65/ 步骤: 1.关机&am…...
全球网站域名/关键词排名优化系统
hashMap源码获取元素的位置: static int indexFor(int h, int length) {// assert Integer.bitCount(length) 1 : "length must be a non-zero power of 2";return h & (length-1); } 解释: h:为插入元素的hashcode length:为map的容量…...
网站改版 删除栏目/上海网络推广
数据表设计的时候使用一个字段来存储多对多关系,比如表 user 中有一个字段叫 category, category存储的是 "1,3,9" 这样的类型的数据,实际上是 category 的 id 用逗号分隔开来的。 向 user 表录入 100万的数据,同时建立 user_cate…...
国内最大的自建站平台/百度健康
2019独角兽企业重金招聘Python工程师标准>>> 硬件内部计时器精度 US级别 #include<iostream> #include "functional" #include "windows.h" using namespace std;#include <WinBase.h> long long calculateMS(std::function<vo…...
个人网站制作成品/昆明网站seo公司
1 前言本文以两道经典建模题为例, 进一步介绍 Gurobi 与 Python 的交互, 以及其在建模中的应用. 阅读本文前, 建议读者先配置好 Gurobi 环境, 并且对数学建模有一定的认识 (吹水, 不考虑绝对的严谨性)。本文也可作为建模小白的“入门指南”, 全文都是按照我的思维过程进行书写,…...