qt-compatibility-build
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseqt-compatibility-build
qt-compatibility-build
Overview
概述
Unifies CMake configuration for deepin V25/V20 dual-version support by automatically detecting Qt5/Qt6 and dynamically mapping DTK versions, eliminating hard-coded version references throughout the build system.
通过自动检测Qt5/Qt6并动态映射DTK版本,统一CMake配置以支持deepin V25/V20双版本,消除构建系统中所有硬编码的版本引用。
File Convention
文件约定
| File | Deepin Version | Qt Version |
|---|---|---|
| V25 | Qt6 |
| V20 | Qt5 |
Why: (no suffix) = latest version (V25), (with suffix) = previous version (V20).
controlcontrol.1| 文件 | Deepin版本 | Qt版本 |
|---|---|---|
| V25 | Qt6 |
| V20 | Qt5 |
原因:无后缀的对应最新版本(V25),带后缀的对应旧版本(V20)。
controlcontrol.1When to Use
适用场景
dot
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"];
}Use when:
- CMakeLists.txt has hard-coded or
Qt5::inQt6::target_link_libraries - CMakeLists.txt has hard-coded or
Dtk::inDtk6::or linkingfind_package - Projects need both V25 (Qt6) and V20 (Qt5) builds from same code
- Need dynamic library linking based on detected Qt version
- DTK dependencies need to map automatically to installed Qt version
Do NOT use when:
- Projects without CMake build system
- Projects without Qt dependencies
- Single version support only (V25-only or V20-only)
dot
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)
Quick Reference
快速参考
| Task | Command/Pattern |
|---|---|
| Auto-detect Qt | |
| Map DTK to Qt | |
| Dynamic Qt find | |
| Dynamic DTK find | |
| Dynamic Qt linking | |
| Dynamic DTK linking | |
| V25 build | |
| V20 build | |
Note: is optional for local build convenience. CMake auto-detects if not specified.
-DQT_DIR| 任务 | 命令/模式 |
|---|---|
| 自动检测Qt | |
| 映射DTK到Qt版本 | |
| 动态查找Qt | |
| 动态查找DTK | |
| 动态链接Qt | |
| 动态链接DTK | |
| V25构建 | |
| V20构建 | |
注意:是为了本地构建方便而设的可选参数。如果未指定,CMake会自动检测。
-DQT_DIRImplementation
实现步骤
Step 1: Add Qt Detection (CMakeLists.txt top)
步骤1:添加Qt检测(CMakeLists.txt顶部)
cmake
undefinedcmake
undefinedAuto-detect Qt version (tries Qt6 first, falls back to Qt5)
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}")
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)
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}")
undefinedif (QT_VERSION_MAJOR MATCHES 6)
set(DTK_VERSION_MAJOR 6)
else()
set(DTK_VERSION_MAJOR "")
endif()
message(STATUS "Build with DTK: ${DTK_VERSION_MAJOR}")
undefinedStep 2: Update All find_package Calls
步骤2:更新所有find_package调用
Before (hard-coded):
cmake
find_package(Qt6 COMPONENTS Core Gui Widgets Network REQUIRED)
find_package(DtkWidget REQUIRED)After (dynamic):
cmake
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)修改前(硬编码):
cmake
find_package(Qt6 COMPONENTS Core Gui Widgets Network REQUIRED)
find_package(DtkWidget REQUIRED)修改后(动态):
cmake
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)Step 3: Update All target_link_libraries
步骤3:更新所有target_link_libraries
Before (hard-coded):
cmake
target_link_libraries(mylib
Dtk::Core
Dtk::Gui
Qt6::Network
)After (dynamic):
cmake
target_link_libraries(mylib
Dtk${DTK_VERSION_MAJOR}::Core
Dtk${DTK_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Network
)Replacement pattern:
- →
Qt5::Qt${QT_VERSION_MAJOR}:: - →
Qt6::Qt${QT_VERSION_MAJOR}:: - →
Dtk::Dtk${DTK_VERSION_MAJOR}:: - →
Dtk6::Dtk${DTK_VERSION_MAJOR}::
修改前(硬编码):
cmake
target_link_libraries(mylib
Dtk::Core
Dtk::Gui
Qt6::Network
)修改后(动态):
cmake
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}::
Step 4: Translation Generation (if needed)
步骤4:生成翻译文件(如有需要)
Create :
cmake/translation-generate.cmakecmake
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()Usage:
cmake
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)创建:
cmake/translation-generate.cmakecmake
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()使用方式:
cmake
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)Step 5: Create Control Files
步骤5:创建Control文件
debian/control (V25/Qt6):
Build-Depends:
cmake,
pkg-config,
qt6-base-dev,
qt6-tools-dev,
qt6-svg-dev,
libdtk6widget-dev,
libdtk6core-devdebian/control.1 (V20/Qt5):
Build-Depends:
cmake,
pkg-config,
qtbase5-dev,
qttools5-dev,
libqt5svg5-dev,
libdtkwidget-dev,
libdtkcore-devdebian/control(V25/Qt6):
Build-Depends:
cmake,
pkg-config,
qt6-base-dev,
qt6-tools-dev,
qt6-svg-dev,
libdtk6widget-dev,
libdtk6core-devdebian/control.1(V20/Qt5):
Build-Depends:
cmake,
pkg-config,
qtbase5-dev,
qttools5-dev,
libqt5svg5-dev,
libdtkwidget-dev,
libdtkcore-devDependency Mapping
依赖映射
| Purpose | V25 (Qt6) | V20 (Qt5) |
|---|---|---|
| Base | | |
| Tools | | |
| SVG | | |
| DTK Widget | | |
| DTK Core | | |
| 用途 | V25 (Qt6) | V20 (Qt5) |
|---|---|---|
| 基础库 | | |
| 工具 | | |
| SVG支持 | | |
| DTK组件库 | | |
| DTK核心库 | | |
Common Mistakes
常见错误
| Mistake | Why It's Wrong | Fix |
|---|---|---|
Hard-coded | Forces specific Qt version | Use |
Hard-coded | Forces specific DTK version | Use |
Missing | DTK won't map to Qt version | Add variable mapping from Qt detection |
Only using | Won't support V20 | Create both control files |
| Using OR dependencies in single control | Should use separate files | Split into control and control.1 |
| Only testing one Qt version | Both must work for dual support | Test V25 and V20 builds |
Not using | Won't auto-detect both | Use correct find_package pattern |
| 错误 | 原因 | 修复方案 |
|---|---|---|
硬编码 | 强制使用特定Qt版本 | 使用 |
硬编码 | 强制使用特定DTK版本 | 使用 |
缺少 | DTK无法映射到Qt版本 | 添加从Qt检测结果映射变量的代码 |
仅使用 | 无法支持V20版本 | 同时创建两个control文件 |
| 在单个control文件中使用OR依赖 | 应该使用分离的文件 | 拆分为control和control.1 |
| 仅测试一个Qt版本 | 双版本支持需要确保两者都可用 | 测试V25和V20两种构建 |
Qt检测未使用 | 无法检测两个版本 | 使用正确的find_package格式 |
Red Flags - STOP and Check
警示信号 - 立即检查
- Hard-coded Qt5/Qt6 in CMakeLists.txt → Must use variable
QT_VERSION_MAJOR - Hard-coded DTK5/DTK6 in CMakeLists.txt → Must use variable
DTK_VERSION_MAJOR - Missing variable → DTK won't map to Qt version
DTK_VERSION_MAJOR - Using OR dependencies instead of separate control files → Should use control/control.1
- Only testing one Qt version → Both versions must work
- Qt detection not using → Won't detect both versions
find_package(QT NAMES Qt6 Qt5 ...)
- CMakeLists.txt中硬编码Qt5/Qt6 → 必须使用变量
QT_VERSION_MAJOR - CMakeLists.txt中硬编码DTK5/DTK6 → 必须使用变量
DTK_VERSION_MAJOR - 缺少变量 → DTK无法映射到Qt版本
DTK_VERSION_MAJOR - 使用OR依赖而非分离的control文件 → 应该使用control/control.1
- 仅测试一个Qt版本 → 两个版本都必须能正常工作
- Qt检测未使用→ 无法检测两个版本
find_package(QT NAMES Qt6 Qt5 ...)