mcpField
Q
qt-compatibility-build

qt-compatibility-build

github.com/re2zero开发777 次安装13 周前更新
代码仓库

关于 qt-compatibility-build

为 Deepin V25/V20 的 Qt/CMake 项目提供构建配置指导,帮助维护者用同一套代码兼容 Qt6 与 Qt5。通过自动检测 Qt 版本并映射 DTK 版本,避免在 CMake 中固定版本引用。

主要功能

  1. 01自动检测 Qt5 或 Qt6
  2. 02按 Qt 版本映射 DTK
  3. 03动态配置依赖与链接库
  4. 04区分 V25 和 V20 控制文件
  5. 05提供翻译生成配置指导

适用场景

  1. 01让同一项目支持 V25 与 V20
  2. 02替换 CMake 中固定的 Qt/DTK 引用
  3. 03按已安装的 Qt 版本配置链接
  4. 04为双版本构建检查 Debian 依赖

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/re2zero/deepin-skills --skill qt-compatibility-build

安装后在 Claude Code 中输入/qt-compatibility-build确认已加载。

详细介绍

qt-compatibility-build

概述

统一 CMake 配置,以支持 deepin V25/V20 双版本,并自动检测 Qt5/Qt6、动态映射 DTK 版本,从而消除整个构建系统中的硬编码版本引用。

文件约定

文件deepin 版本Qt 版本
debian/controlV25Qt6
debian/control.1V20Qt5

原因:control(无后缀)=最新版本(V25),control.1(带后缀)=上一版本(V20)。

适用场景

digraph when_to_use {
    "Qt/CMake project?" [shape=diamond];
    "V25/V20 dual support?" [shape=diamond];
    "Hard-coded Qt/DTK?" [shape=diamond];
    "Use this skill" [shape=box];
    "Wrong tool" [shape=box];

    "Qt/CMake project?" -> "V25/V20 dual support?" [label="yes"];
    "V25/V20 dual support?" -> "Hard-coded Qt/DTK?" [label="yes"];
    "Hard-coded Qt/DTK?" -> "Use this skill" [label="yes"];
}

适用于:

  • CMakeLists.txt 的 target_link_libraries 中硬编码了 Qt5:: 或 Qt6::
  • CMakeLists.txt 的 find_package 或链接中硬编码了 Dtk:: 或 Dtk6::
  • 项目需要从同一份代码构建 V25(Qt6)和 V20(Qt5)
  • 需要根据检测到的 Qt 版本动态链接库
  • DTK 依赖需要自动映射到已安装的 Qt 版本

不适用于:

  • 不使用 CMake 构建系统的项目
  • 不依赖 Qt 的项目
  • 仅支持单个版本(仅 V25 或仅 V20)

快速参考

任务命令/模式
自动检测 Qtfind_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
将 DTK 映射到 Qtif (QT_VERSION_MAJOR MATCHES 6) set(DTK_VERSION_MAJOR 6)
动态查找 Qtfind_package(Qt${QT_VERSION_MAJOR} COMPONENTS ${QT} REQUIRED)
动态查找 DTKfind_package(Dtk${DTK_VERSION_MAJOR}Widget REQUIRED)
动态链接 QtQt${QT_VERSION_MAJOR}::Core
动态链接 DTKDtk${DTK_VERSION_MAJOR}::Core
V25 构建cmake -B build -DQT_DIR=/usr/lib/x86_64-linux-gnu/cmake/Qt6
V20 构建cmake -B build5 -DQT_DIR=/usr/lib/x86_64-linux-gnu/cmake/Qt5

注意:为方便本地构建,-DQT_DIR 是可选项。未指定时,CMake 会自动检测。

实现

步骤 1:添加 Qt 检测(CMakeLists.txt 顶部)
# Auto-detect Qt version (tries Qt6 first, falls back to Qt5)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
message(STATUS "Found Qt version: ${QT_VERSION_MAJOR}")

# Map to DTK version (Qt6→DTK6, Qt5→DTK5)
if (QT_VERSION_MAJOR MATCHES 6)
    set(DTK_VERSION_MAJOR 6)
else()
    set(DTK_VERSION_MAJOR "")
endif()
message(STATUS "Build with DTK: ${DTK_VERSION_MAJOR}")
步骤 2:更新所有 find_package 调用

之前(硬编码):

find_package(Qt6 COMPONENTS Core Gui Widgets Network REQUIRED)
find_package(DtkWidget REQUIRED)

之后(动态):

set(QT Core Gui Widgets Network DBus Sql Svg Test WebChannel WebSockets)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS ${QT} REQUIRED)

find_package(Dtk${DTK_VERSION_MAJOR}Widget REQUIRED)
find_package(Dtk${DTK_VERSION_MAJOR}Core REQUIRED)
find_package(Dtk${DTK_VERSION_MAJOR}Gui REQUIRED)
步骤 3:更新所有 target_link_libraries

之前(硬编码):

target_link_libraries(mylib
    Dtk::Core
    Dtk::Gui
    Qt6::Network
)

之后(动态):

target_link_libraries(mylib
    Dtk${DTK_VERSION_MAJOR}::Core
    Dtk${DTK_VERSION_MAJOR}::Gui
    Qt${QT_VERSION_MAJOR}::Network
)

替换模式:

  • Qt5:: → Qt${QT_VERSION_MAJOR}::
  • Qt6:: → Qt${QT_VERSION_MAJOR}::
  • Dtk:: → Dtk${DTK_VERSION_MAJOR}::
  • Dtk6:: → Dtk${DTK_VERSION_MAJOR}::
步骤 4:生成翻译(如有需要)

创建 cmake/translation-generate.cmake:

function(TRANSLATION_GENERATE QMS)
  find_package(Qt${QT_VERSION_MAJOR}LinguistTools QUIET)

  if (NOT Qt${QT_VERSION_MAJOR}_LRELEASE_EXECUTABLE)
    set(QT_LRELEASE "/lib/qt${QT_VERSION_MAJOR}/bin/lrelease")
    message(STATUS "NOT found lrelease, set QT_LRELEASE = ${QT_LRELEASE}")
  else()
    set(QT_LRELEASE "${Qt${QT_VERSION_MAJOR}_LRELEASE_EXECUTABLE}")
  endif()

  if(NOT ARGN)
    message(SEND_ERROR "Error: TRANSLATION_GENERATE() called without any .ts path")
    return()
  endif()

  file(GLOB TS_FILES "${ARGN}/*.ts")
  set(${QMS})
  foreach(TSFIL ${TS_FILES})
      get_filename_component(FIL_WE ${TSFIL} NAME_WE)
      set(QMFIL ${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.qm)
      list(APPEND ${QMS} ${QMFIL})
      add_custom_command(
          OUTPUT ${QMFIL}
          COMMAND ${QT_LRELEASE} ${TSFIL} -qm ${QMFIL}
          DEPENDS ${TSFIL}
          COMMENT "Running ${QT_LRELEASE} on ${TSFIL}"
          VERBATIM
      )
  endforeach()

  set_source_files_properties(${${QMS}} PROPERTIES GENERATED TRUE)
  set(${QMS} ${${QMS}} PARENT_SCOPE)
endfunction()

用法:

include(translation-generate)
TRANSLATION_GENERATE(QM_FILES ${CMAKE_SOURCE_DIR}/translations)
add_custom_target(${PROJECT_NAME}_qm_files DEPENDS ${QM_FILES})
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}_qm_files)
install(FILES ${QM_FILES} DESTINATION share/${PROJECT_NAME}/translations)
步骤 5:创建 control 文件

debian/control(V25/Qt6):

Build-Depends:
 cmake,
 pkg-config,
 qt6-base-dev,
 qt6-tools-dev,
 qt6-svg-dev,
 libdtk6widget-dev,
 libdtk6core-dev

debian/control.1(V20/Qt5):

Build-Depends:
 cmake,
 pkg-config,
 qtbase5-dev,
 qttools5-dev,
 libqt5svg5-dev,
 libdtkwidget-dev,
 libdtkcore-dev

依赖映射

用途V25 (Qt6)V20 (Qt5)
基础qt6-base-devqtbase5-dev
工具qt6-tools-devqttools5-dev
SVGqt6-svg-devlibqt5svg5-dev
DTK Widgetlibdtk6widget-devlibdtkwidget-dev
DTK Corelibdtk6core-devlibdtkcore-dev

常见错误

错误错误原因修正方法
硬编码 Qt5::Core / Qt6::Core强制使用特定 Qt 版本使用 Qt${QT_VERSION_MAJOR}::Core
硬编码 Dtk::Core / Dtk6::Core强制使用特定 DTK 版本使用 Dtk${DTK_VERSION_MAJOR}::Core
缺少 DTK_VERSION_MAJORDTK 无法映射到 Qt 版本添加从 Qt 检测结果映射变量的逻辑
只使用 control,没有 control.1不支持 V20创建两个 control 文件
在单个 control 文件中使用 OR 依赖应使用单独的文件拆分为 control 和 control.1
只测试一个 Qt 版本双版本支持要求两个版本都能正常工作测试 V25 和 V20 构建
未使用 find_package(QT NAMES Qt6 Qt5 ...)无法自动检测两个版本使用正确的 find_package 模式

危险信号——停止并检查

  • 在 CMakeLists.txt 中硬编码 Qt5/Qt6 → 必须使用 QT_VERSION_MAJOR 变量
  • 在 CMakeLists.txt 中硬编码 DTK5/DTK6 → 必须使用 DTK_VERSION_MAJOR 变量
  • 缺少 DTK_VERSION_MAJOR 变量 → DTK 无法映射到 Qt 版本
  • 使用 OR 依赖项,而不是单独的控制文件 → 应使用 control/control.1
  • 只测试一个 Qt 版本 → 两个版本都必须可用
  • Qt 检测未使用 find_package(QT NAMES Qt6 Qt5 ...) → 无法检测两个版本

评论

支持 Markdown