Qt 与 GTK 图形框架教程 / 11 - 跨平台开发 / Cross-Platform
跨平台开发 / Cross-Platform Development
掌握 Qt 与 GTK 应用在 Windows、macOS、Linux 上的部署与打包。 Master deployment and packaging for Windows, macOS, and Linux.
11.1 平台差异总览 / Platform Differences
| 特性 / Feature | Windows | macOS | Linux |
|---|---|---|---|
| Qt 部署 | windeployqt | macdeployqt | linuxdeployqt / AppImage |
| GTK 部署 | MSYS2 | 手动打包 | Flatpak / Snap / 原生 |
| 安装器 | NSIS / WiX / Inno Setup | DMG / pkg | deb / rpm / AppImage |
| 文件位置 | %APPDATA% | ~/Library/Application Support | ~/.config |
| 桌面集成 | 开始菜单快捷方式 | .app Bundle | .desktop 文件 |
| 自动启动 | 注册表 Run | Login Items | ~/.config/autostart |
| 通知 | WinRT Notification | NSUserNotification | libnotify |
| 系统托盘 | QSystemTrayIcon | NSStatusItem | AppIndicator |
11.2 Qt 跨平台部署 / Qt Cross-Platform Deployment
Windows 部署
# 使用 windeployqt 自动收集依赖
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
# 自动复制 Qt DLL 和插件
windeployqt --release --no-translations myapp.exe
# 目录结构
# build/
# ├── myapp.exe
# ├── Qt6Core.dll
# ├── Qt6Gui.dll
# ├── Qt6Widgets.dll
# ├── platforms/
# │ └── qwindows.dll
# ├── styles/
# ├── imageformats/
# └── ...
macOS 部署
# 1. 构建
mkdir build && cd build
cmake .. -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0
cmake --build . --config Release
# 2. 创建 .app bundle
macdeployqt MyApp.app -dmg
# 3. 生成 DMG 安装器
# macdeployqt 自动复制 Qt 框架到 .app/Contents/Frameworks/
# 结构
# MyApp.app/
# └── Contents/
# ├── Info.plist
# ├── MacOS/
# │ └── MyApp # 可执行文件
# ├── Frameworks/ # Qt 框架
# ├── Resources/ # 图标、资源
# └── PlugIns/ # Qt 插件
Linux 部署 (AppImage)
# 使用 linuxdeploy + linuxdeploy-plugin-qt
# 1. 安装工具
wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
chmod +x linuxdeploy-x86_64.AppImage
# 2. 创建 AppDir 结构
mkdir -p AppDir/usr/bin AppDir/usr/share/applications AppDir/usr/share/icons
cp build/myapp AppDir/usr/bin/
cp myapp.desktop AppDir/usr/share/applications/
cp icon.png AppDir/usr/share/icons/myapp.png
# 3. 打包为 AppImage
./linuxdeploy-x86_64.AppImage --appdir AppDir \
--plugin qt \
--output appimage
# 输出: MyApp-x86_64.AppImage
CMake 跨平台配置
# CMakeLists.txt - 跨平台打包配置
cmake_minimum_required(VERSION 3.16)
project(MyApp VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_AUTOMOC ON)
find_package(Qt6 REQUIRED COMPONENTS Core Widgets)
add_executable(myapp main.cpp mainwindow.cpp)
target_link_libraries(myapp PRIVATE Qt6::Core Qt6::Widgets)
# 安装规则
install(TARGETS myapp DESTINATION bin)
# CPack 配置
set(CPACK_PACKAGE_NAME "MyApp")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_PACKAGE_CONTACT "developer@example.com")
if(WIN32)
set(CPACK_GENERATOR "NSIS;ZIP")
set(CPACK_NSIS_DISPLAY_NAME "MyApp")
set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64")
elseif(APPLE)
set(CPACK_GENERATOR "DragNDrop")
set(CPACK_DMG_VOLUME_NAME "MyApp")
else()
set(CPACK_GENERATOR "DEB;RPM")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6widgets6")
set(CPACK_RPM_PACKAGE_REQUIRES "qt6-qtbase")
endif()
include(CPack)
11.3 GTK 跨平台部署 / GTK Cross-Platform Deployment
Flatpak 打包(推荐)
# com.example.myapp.yml - Flatpak 清单
app-id: com.example.myapp
runtime: org.gnome.Platform//46
runtime-version: '46'
sdk: org.gnome.Sdk//46
command: myapp
finish-args:
- --share=network
- --share=ipc
- --socket=fallback-x11
- --socket=wayland
- --device=dri
- --filesystem=home
modules:
- name: myapp
buildsystem: meson
sources:
- type: git
url: https://github.com/user/myapp.git
tag: v1.0.0
# 构建 Flatpak
flatpak-builder --user --install --force-clean build-dir com.example.myapp.yml
# 运行
flatpak run com.example.myapp
Snap 打包
# snapcraft.yaml
name: myapp
version: '1.0.0'
summary: My GTK4 Application
description: A modern GTK4 application
base: core24
confinement: strict
grade: stable
apps:
myapp:
command: usr/bin/myapp
extensions: [gnome]
plugs:
- home
- network
- desktop
parts:
myapp:
plugin: meson
source: .
meson-parameters:
- --prefix=/usr
build-packages:
- libgtk-4-dev
- libadwaita-1-dev
11.4 NSIS Windows 安装器 / NSIS Installer
; installer.nsi - NSIS 安装器脚本
!include "MUI2.nsh"
Name "MyApp"
OutFile "MyApp-Setup.exe"
InstallDir "$PROGRAMFILES64\MyApp"
RequestExecutionLevel admin
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
Section "Install"
SetOutPath $INSTDIR
File /r "build\release\*.*"
; 创建快捷方式
CreateDirectory "$SMPROGRAMS\MyApp"
CreateShortCut "$SMPROGRAMS\MyApp\MyApp.lnk" "$INSTDIR\myapp.exe"
CreateShortCut "$DESKTOP\MyApp.lnk" "$INSTDIR\myapp.exe"
; 写入注册表(卸载程序)
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" \
"DisplayName" "MyApp"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp" \
"UninstallString" "$\"$INSTDIR\uninstall.exe$\""
WriteUninstaller "$INSTDIR\uninstall.exe"
SectionEnd
Section "Uninstall"
Delete "$INSTDIR\*.*"
RMDir /r "$INSTDIR"
Delete "$SMPROGRAMS\MyApp\*.*"
RMDir "$SMPROGRAMS\MyApp"
Delete "$DESKTOP\MyApp.lnk"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp"
SectionEnd
11.5 macOS .desktop 配置 / macOS Bundle
Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>MyApp</string>
<key>CFBundleIconFile</key>
<string>AppIcon</string>
<key>CFBundleIdentifier</key>
<string>com.example.myapp</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
Linux .desktop 文件
# myapp.desktop
[Desktop Entry]
Type=Application
Name=MyApp
Comment=A modern desktop application
Exec=myapp %u
Icon=myapp
Terminal=false
Categories=Utility;GTK;
StartupNotify=true
MimeType=x-scheme-handler/myapp;
11.6 CI/CD 跨平台构建 / CI/CD Cross-Platform Build
GitHub Actions 示例
# .github/workflows/build.yml
name: Build All Platforms
on:
push:
tags: ['v*']
jobs:
build-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: jurplel/install-qt-action@v4
with:
version: '6.6.0'
- run: |
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release
cd build
windeployqt --release myapp.exe
- uses: actions/upload-artifact@v4
with:
name: windows
path: build/
build-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: jurplel/install-qt-action@v4
with:
version: '6.6.0'
- run: |
cmake -B build -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0
cmake --build build
macdeployqt build/MyApp.app -dmg
- uses: actions/upload-artifact@v4
with:
name: macos
path: build/*.dmg
build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: jurplel/install-qt-action@v4
with:
version: '6.6.0'
- run: |
sudo apt install libfuse2
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
# AppImage 打包
wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
chmod +x linuxdeploy-x86_64.AppImage
./linuxdeploy-x86_64.AppImage --appdir AppDir --plugin qt --output appimage
- uses: actions/upload-artifact@v4
with:
name: linux
path: '*.AppImage'
注意事项 / Important Notes
⚠️ Qt DLL 版本匹配 / Qt DLL Version Match
部署时确保 Qt DLL 版本与编译时完全一致。混合版本会导致崩溃。 Ensure deployed Qt DLLs match compile-time versions exactly.
⚠️ GTK 跨平台限制 / GTK Cross-Platform Limits
GTK 在 Windows/macOS 上需要打包大量依赖(~50MB+),且外观可能与原生不符。 GTK on Windows/macOS requires many dependencies and may not look native.
⚠️ 代码签名 / Code Signing
macOS 和 Windows 都要求应用签名才能正常分发。 macOS: Apple Developer ID; Windows: Authenticode 证书。
Both macOS and Windows require code signing for distribution.
扩展阅读 / Further Reading
| 资源 / Resource | 链接 / Link |
|---|---|
| Qt 部署文档 | https://doc.qt.io/qt-6/deployment.html |
| Flatpak 文档 | https://docs.flatpak.org/ |
| Snap 文档 | https://snapcraft.io/docs |
| NSIS 文档 | https://nsis.sourceforge.io/Docs/ |
| GitHub Actions Qt | https://github.com/jurplel/install-qt-action |
← 10 - Python 绑定 | 12 - 主题与样式 →