Use when maintaining Debian packages that need Qt5/Qt6 dual support, CMakeLists.txt has hard-coded Qt5/Qt6 or DTK5/DTK6 versions, or projects need dynamic library linking based on detected Qt version for deepin V25/V20 compatibility
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
You Might Also Like
Related Skills

create-pr
Creates GitHub pull requests with properly formatted titles that pass the check-pr-title CI validation. Use when creating PRs, submitting changes for review, or when the user says /pr or asks to create a pull request.
n8n-io
electron-chromium-upgrade
Guide for performing Chromium version upgrades in the Electron project. Use when working on the roller/chromium/main branch to fix patch conflicts during `e sync --3`. Covers the patch application workflow, conflict resolution, analyzing upstream Chromium changes, and proper commit formatting for patch fixes.
electron
pr-creator
Use this skill when asked to create a pull request (PR). It ensures all PRs follow the repository's established templates and standards.
google-gemini
clawdhub
Use the ClawdHub CLI to search, install, update, and publish agent skills from clawdhub.com. Use when you need to fetch new skills on the fly, sync installed skills to latest or a specific version, or publish new/updated skill folders with the npm-installed clawdhub CLI.
moltbot
tmux
Remote-control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output.
moltbot
create-pull-request
Create a GitHub pull request following project conventions. Use when the user asks to create a PR, submit changes for review, or open a pull request. Handles commit analysis, branch management, and PR creation using the gh CLI tool.
cline