强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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

特性 / FeatureWindowsmacOSLinux
Qt 部署windeployqtmacdeployqtlinuxdeployqt / AppImage
GTK 部署MSYS2手动打包Flatpak / Snap / 原生
安装器NSIS / WiX / Inno SetupDMG / pkgdeb / rpm / AppImage
文件位置%APPDATA%~/Library/Application Support~/.config
桌面集成开始菜单快捷方式.app Bundle.desktop 文件
自动启动注册表 RunLogin Items~/.config/autostart
通知WinRT NotificationNSUserNotificationlibnotify
系统托盘QSystemTrayIconNSStatusItemAppIndicator

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 Qthttps://github.com/jurplel/install-qt-action

10 - Python 绑定 | 12 - 主题与样式