qt-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.
File Convention
| File | Deepin Version | Qt Version |
|---|---|---|
debian/control |
V25 | Qt6 |
debian/control.1 |
V20 | Qt5 |
Why: control (no suffix) = latest version (V25), control.1 (with suffix) = previous version (V20).
When to Use
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
Qt5::orQt6::intarget_link_libraries - CMakeLists.txt has hard-coded
Dtk::orDtk6::infind_packageor linking - 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)
Quick Reference
| Task | Command/Pattern |
|---|---|
| Auto-detect Qt | find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core) |
| Map DTK to Qt | if (QT_VERSION_MAJOR MATCHES 6) set(DTK_VERSION_MAJOR 6) |
| Dynamic Qt find | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS ${QT} REQUIRED) |
| Dynamic DTK find | find_package(Dtk${DTK_VERSION_MAJOR}Widget REQUIRED) |
| Dynamic Qt linking | Qt${QT_VERSION_MAJOR}::Core |
| Dynamic DTK linking | Dtk${DTK_VERSION_MAJOR}::Core |
| V25 build | cmake -B build -DQT_DIR=/usr/lib/x86_64-linux-gnu/cmake/Qt6 |
| V20 build | cmake -B build5 -DQT_DIR=/usr/lib/x86_64-linux-gnu/cmake/Qt5 |
Note: -DQT_DIR is optional for local build convenience. CMake auto-detects if not specified.
Implementation
Step 1: Add Qt Detection (CMakeLists.txt top)
# 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}")
Step 2: Update All find_package Calls
Before (hard-coded):
find_package(Qt6 COMPONENTS Core Gui Widgets Network REQUIRED)
find_package(DtkWidget REQUIRED)
After (dynamic):
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
Before (hard-coded):
target_link_libraries(mylib
Dtk::Core
Dtk::Gui
Qt6::Network
)
After (dynamic):
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}::
Step 4: Translation Generation (if needed)
Create 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()
Usage:
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
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
Dependency Mapping
| Purpose | V25 (Qt6) | V20 (Qt5) |
|---|---|---|
| Base | qt6-base-dev |
qtbase5-dev |
| Tools | qt6-tools-dev |
qttools5-dev |
| SVG | qt6-svg-dev |
libqt5svg5-dev |
| DTK Widget | libdtk6widget-dev |
libdtkwidget-dev |
| DTK Core | libdtk6core-dev |
libdtkcore-dev |
Common Mistakes
| Mistake | Why It's Wrong | Fix |
|---|---|---|
Hard-coded Qt5::Core / Qt6::Core |
Forces specific Qt version | Use Qt${QT_VERSION_MAJOR}::Core |
Hard-coded Dtk::Core / Dtk6::Core |
Forces specific DTK version | Use Dtk${DTK_VERSION_MAJOR}::Core |
Missing DTK_VERSION_MAJOR |
DTK won't map to Qt version | Add variable mapping from Qt detection |
Only using control without control.1 |
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 find_package(QT NAMES Qt6 Qt5 ...) |
Won't auto-detect both | Use correct find_package pattern |
Red Flags - STOP and Check
- Hard-coded Qt5/Qt6 in CMakeLists.txt → Must use
QT_VERSION_MAJORvariable - Hard-coded DTK5/DTK6 in CMakeLists.txt → Must use
DTK_VERSION_MAJORvariable - Missing
DTK_VERSION_MAJORvariable → DTK won't map to Qt version - 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
find_package(QT NAMES Qt6 Qt5 ...)→ Won't detect both versions
More from re2zero/deepin-skills
qt-unittest-make
Use when users request generating unit tests for Qt modules or classes, completing test cases, or creating test files. Supports module batch generation and incremental completion.
56qt-translation-assistant
Use when user requests translating Qt project localization files (TS files), automating translation workflows, or setting up multilingual support for Qt applications. This skill uses parallel processing with ThreadPoolExecutor to translate TS (Translation Source) files efficiently.
36qt-unittest-build
为 Qt 项目生成单元测试框架。包含完整依赖、子 Agent 和固定脚本,一键生成 autotests 测试框架。
22git-commit-workflow
Expertise in structured Git commit workflow with Chinese team conventions. Use
18github-review-report
Use when generating Chinese format Excel reports from GitHub code reviews with AI analysis and filtering by date, branch, or reviewers
18create-release-tags
Use when releasing new versions for Debian projects with optional linglong.yaml support, updating debian/changelog, incrementing patch versions automatically, and creating git commits
17