# 如何快速有效部署GTK应用程序到Windows平台?(08/03/2020 更新)

# 背景介绍

自从启动开发 袋鼠数据库工具 以来,我遇到的最大困难就是如何打包 袋鼠数据库工具 应用给用户,经借用强大的谷歌寻找解决方案,最终寻找到了一位日本友人分享的文章Windows平台 GTK+3 安装包教程 (opens new window),文章提供了一份最清晰的 Windows 平台 GTK3 应用部署目录结构,一切问题迎刃而解,所以成功部署 GTK 应用的荣耀应该属于该文章作者。

# 前置条件

文本所介绍的 GTK 应用打包教程基于构建环境 MSYS2 (opens new window),请提前准备好构建环境。

# 解决方案

# 准备应用目录结构

为了成功部署 GTK 应用,应用的最终安装目录结构必须参考 Linux 系统目录结构,目录结构如下:

[安装目录]
    ├─bin
    ├─etc
    │  └─gtk-3.0
    ├─lib
    └─share
        ├─doc
        ├─glib-2.0
        │  └─schemas
        ├─icons
        │  ├─Adwaita
        │  └─hicolor
        ├─locale
        └─themes
            ├─Default
            ├─MS-Windows
            └─Windows10
(adsbygoogle = window.adsbygoogle || []).push({});

# 复制第三方依赖库

List of GTK dependencies GTK 框架依赖的第三方库:

  • GLib
  • cairo
  • Pango
  • ATK
  • gdk-pixbuf

为了启动 GTK 应用,您也需要如下第三方库:

  • gettext-runtime
  • fontconfig
  • freetype
  • expat
  • libpng
  • zlib

如何获取依赖库列表并复制到打包目录?

解决方案就是一系列 Linux 命令工具组合,详细如下:

ldd "${SOURCEDIR}/build/src/kangaroo.exe" | grep '\/mingw64\/bin\/.*dll' -o | xargs -I{} cp -f "{}" "${TARGETDIR}/bin/"

执行完上述命令就够了吗? 不够!!!

GTK 框架中一些地三方依赖库,比如 gdk-pixbuf / libgda,通过插件扩展的方式实现其功能,所以我们必须找出它们来,并把它们的插件文件和依赖库都找到并复制到打包目录:

ldd /mingw64/bin/libpq.dll | grep '\/mingw64\/bin\/.*dll' -o | xargs -I{} cp -f "{}" "${TARGETDIR}/bin/"

# 复制应用资源文件

  • /etc

    • /gtk-3.0/settings.ini : 应用级别的配置文件
    • *: 其它未列出的文件
  • /lib

    • /gdk-pixbuf-2.0 : GDK-Pixbuf 模块: SVG 支持库
    • /gtk-3.0 : GTK+-IM 模块
    • /pango : Pango 模块
    • : 扩展开发需要导入的库、头文件、pkg-config(.pc)配置文件等... 仅用于开发用途
  • /share

    • /doc : 应用文档,如许可证和版权协议等
    • /gtk-3.0 : GTK3 相关的资源文件(gkt3-demo)
    • /gtk-doc : gtk-doc 生存的网页文档
    • /icons : 框架和应用的图标文件
    • /locale : 框架和应用的本地化文件(用于支持多语言)
    • /themes : 架和应用的样式文件
    • *: 其它未列出的文件

# 通过运行时依赖视图比较打包完整性

在全功能模式下,分别在用户环境和测试环境启动应用,用工具 Process Explorer (opens new window) 查看运行时依赖视图(加载的DLL清单),对比依赖库数量是否一致,通过比较打包目录内的dll查漏补缺;

(adsbygoogle = window.adsbygoogle || []).push({});

# 袋鼠数据库的完整打包脚本,可微调直接复用

#!/usr/bin/env sh
#
# Copyright(C) 2018-2020 taozuhong(https://github.com/taozuhong)
# Important:
#   These functions are a part of the Kangaroo tool suite;
#   copyright taozuhong. 2018-2020.  All rights reserved.
#
# Author:    taozuhong
# Created:   1.8.2019
#
SOURCEDIR="$( cd "$(dirname "$0")/../" ; pwd -P )"
TARGETDIR="${SOURCEDIR}/build/windows"
VERSION="0.7.2.$(date +%y%m%d)"
# 检查并创建打包目录
echo -n "检查并创建打包目录......"
if [ ! -d "$TARGETDIR" ]; then
  mkdir $TARGETDIR
  mkdir "${TARGETDIR}/bin/"
  mkdir "${TARGETDIR}/lib/"
  mkdir -p "${TARGETDIR}/share/glib-2.0/schemas"
  mkdir "${TARGETDIR}/share/doc"
  mkdir "${TARGETDIR}/share/themes"
  mkdir "${TARGETDIR}/etc/"
else 
  if [ ! -d "${TARGETDIR}/bin" ]; then
    mkdir "${TARGETDIR}/bin/"
  fi
  if [ ! -d "${TARGETDIR}/lib" ]; then
    mkdir "${TARGETDIR}/lib/"
  fi
  if [ ! -d "${TARGETDIR}/share" ]; then
    mkdir -p "${TARGETDIR}/share/glib-2.0/schemas"
    mkdir "${TARGETDIR}/share/"
    mkdir "${TARGETDIR}/share/doc"
    mkdir "${TARGETDIR}/share/themes"
  fi
  if [ ! -d "${TARGETDIR}/etc" ]; then
    mkdir "${TARGETDIR}/etc/"
  fi
fi
echo "[完成]"
# 复制应用第三方依赖库
echo -n "复制应用第三方依赖库......"
ldd "${SOURCEDIR}/build/src/kangaroo.exe" | grep "$MSYSTEM_PREFIX\/bin\/.*dll" -o | xargs -I{} cp -f "{}" "${TARGETDIR}/bin/"
ldd $MSYSTEM_PREFIX/bin/libjson-glib-1.0-0.dll | grep "$MSYSTEM_PREFIX\/bin\/.*dll" -o | xargs -I{} cp -f "{}" "${TARGETDIR}/bin/"
ldd $MSYSTEM_PREFIX/bin/libsoup-2.4-1.dll | grep "$MSYSTEM_PREFIX\/bin\/.*dll" -o | xargs -I{} cp -f "{}" "${TARGETDIR}/bin/"
ldd $MSYSTEM_PREFIX/bin/libgtksourceview-4-0.dll | grep "$MSYSTEM_PREFIX\/bin\/.*dll" -o | xargs -I{} cp -f "{}" "${TARGETDIR}/bin/"
cp -f "${SOURCEDIR}/build/src/kangaroo.exe" "${TARGETDIR}/bin/"
cp -f "${SOURCEDIR}/data/assets/kangaroo.ico" "${TARGETDIR}/bin/"
cp -f $MSYSTEM_PREFIX/bin/librsvg-2-2.dll "${TARGETDIR}/bin/"
cp -f $MSYSTEM_PREFIX/bin/libgthread-2.0-0.dll "${TARGETDIR}/bin/"
cp -f $MSYSTEM_PREFIX/bin/libcroco-0.6-3.dll "${TARGETDIR}/bin/"
cp -f $MSYSTEM_PREFIX/bin/libtasn1-6.dll "${TARGETDIR}/bin/"
cp -f $MSYSTEM_PREFIX/bin/libproxy-1.dll "${TARGETDIR}/bin/"
cp -f $MSYSTEM_PREFIX/bin/libp11-kit-0.dll "${TARGETDIR}/bin/"
cp -f $MSYSTEM_PREFIX/bin/libnettle-7.dll "${TARGETDIR}/bin/"
cp -f $MSYSTEM_PREFIX/bin/libhogweed-5.dll "${TARGETDIR}/bin/"
cp -f $MSYSTEM_PREFIX/bin/libgnutls-30.dll "${TARGETDIR}/bin/"
cp -f $MSYSTEM_PREFIX/bin/libgmp-10.dll "${TARGETDIR}/bin/"
echo "[完成]"
# 复制 GDBus/Helper 及其依赖库
echo -n "复制 GDBus/Helper 及其依赖库......"
cp -f $MSYSTEM_PREFIX/bin/gdbus.exe "${TARGETDIR}/bin/"
ldd $MSYSTEM_PREFIX/bin/gdbus.exe | grep "$MSYSTEM_PREFIX\/bin\/.*dll" -o | xargs -I{} cp -f "{}" "${TARGETDIR}/bin/"
cp -f $MSYSTEM_PREFIX/bin/gspawn-win64-helper.exe "${TARGETDIR}/bin/"
ldd $MSYSTEM_PREFIX/bin/gspawn-win64-helper.exe | grep "$MSYSTEM_PREFIX\/bin\/.*dll" -o | xargs -I{} cp -f "{}" "${TARGETDIR}/bin/"
echo "[完成]"
# 复制 libgda / 提供者及其依赖库(MySQL/PostgreSQL/JDBC/...)
echo -n "复制 libgda / 提供者及其依赖库......"
cp -f $MSYSTEM_PREFIX/bin/libpq.dll "${TARGETDIR}/bin/"
cp -f $MSYSTEM_PREFIX/bin/mariadb.dll "${TARGETDIR}/bin/"
ldd $MSYSTEM_PREFIX/bin/libpq.dll | grep "$MSYSTEM_PREFIX\/bin\/.*dll" -o | xargs -I{} cp -f "{}" "${TARGETDIR}/bin/"
ldd $MSYSTEM_PREFIX/bin/mariadb.dll | grep "$MSYSTEM_PREFIX\/bin\/.*dll" -o | xargs -I{} cp -f "{}" "${TARGETDIR}/bin/"
if [ -d "${SOURCEDIR}/libs/plugin" ]; then
  cp -rf "${SOURCEDIR}/libs/plugin" "${TARGETDIR}/lib"
fi
echo "[完成]"
# 复制 GTK 运行时依赖资源
echo -n "复制 GTK 运行时依赖资源......"
cp -rf $MSYSTEM_PREFIX/lib/gdk-pixbuf-2.0 "${TARGETDIR}/lib/"
cp -rf $MSYSTEM_PREFIX/lib/libgda-5.0 "${TARGETDIR}/lib/"
cp -rf $MSYSTEM_PREFIX/lib/gio "${TARGETDIR}/lib/"
cp -rf $MSYSTEM_PREFIX/etc/gtk-3.0 "${TARGETDIR}/etc/"
cp -rf $MSYSTEM_PREFIX/share/icons "${TARGETDIR}/share/"
cp -rf $MSYSTEM_PREFIX/share/locale "${TARGETDIR}/share/"
cp -rf $MSYSTEM_PREFIX/share/gtksourceview-4 "${TARGETDIR}/share/"
glib-compile-schemas $MSYSTEM_PREFIX/share/glib-2.0/schemas
cp -f $MSYSTEM_PREFIX/share/glib-2.0/schemas/gschema* "${TARGETDIR}/share/glib-2.0/schemas"
cp -rf $MSYSTEM_PREFIX/share/themes/Default "${TARGETDIR}/share/themes/"
cp -rf $MSYSTEM_PREFIX/share/themes/MS-Windows "${TARGETDIR}/share/themes/"
find "${TARGETDIR}/lib" -type f -path '*.dll.a' -exec rm '{}' \;
echo "[完成]"
# 下载许可证文件: LGPL-3.0
echo -n "下载许可证文件......"
if [ ! -f "${TARGETDIR}/share/doc/lgpl-3.0.txt" ]; then
  curl "https://www.gnu.org/licenses/lgpl-3.0.txt" -o "${TARGETDIR}/share/doc/lgpl-3.0.txt"
fi
if [ -f "${TARGETDIR}/share/doc/lgpl-3.0.txt" ]; then
  echo "[完成]"
else
  echo "[失败]"
fi
上次更新: 2023-10-17T03:57:42.000Z