如何在 Windows 上分发 GTK+ 应用程序?

Posted

技术标签:

【中文标题】如何在 Windows 上分发 GTK+ 应用程序?【英文标题】:How to distribute a GTK+ application on Windows? 【发布时间】:2018-08-12 01:33:26 【问题描述】:

我已经在 Windows 上通过 MSYS 和 MinGW 安装了 GTK+(特别是 GTK3)。我现在想将 GTK+ dll 复制到我的应用程序目录,这样它就可以在没有全局 GTK+ 安装的计算机上运行。 GTK+ 需要哪些 dll 才能运行?

编辑: GTK+ 文档现在包含instructions,用于在 Windows 上分发所需的图标和主题。 (尽管它没有关于分发相关 DLL 文件的说明——请参阅下面的答案。)

【问题讨论】:

我通常结合使用ntldd 和反复试验。您可以通过将 PATH 设置为空然后运行您的应用程序来测试它。但是现在我在自己的构建系统中使用静态编译,所以不需要 DLL。 【参考方案1】:

事实证明,运行 ldd mygtkapp.exe(使用 MinGW 提供的 ldd)给了我运行它所需的所有 dll 的列表。为了只获取 gtk 依赖项的 dll(而不是例如 Win32 dll),我使用了以下命令:ldd mygtkapp.exe | sed -n 's/\([^ ]*\) => \/mingw.*/\1/p' | sort。我的程序使用了 Haskell 绑定,所以依赖关系可能有点不同,但这是我得到的:

libatk-1.0-0.dll
libbz2-1.dll
libcairo-2.dll
libcairo-gobject-2.dll
libepoxy-0.dll
libexpat-1.dll
libffi-6.dll
libfontconfig-1.dll
libfreetype-6.dll
libgcc_s_seh-1.dll
libgdk_pixbuf-2.0-0.dll
libgdk-3-0.dll
libgio-2.0-0.dll
libglib-2.0-0.dll
libgmodule-2.0-0.dll
libgobject-2.0-0.dll
libgraphite2.dll
libgthread-2.0-0.dll
libgtk-3-0.dll
libharfbuzz-0.dll
libiconv-2.dll
libintl-8.dll
libpango-1.0-0.dll
libpangocairo-1.0-0.dll
libpangoft2-1.0-0.dll
libpangowin32-1.0-0.dll
libpcre-1.dll
libpixman-1-0.dll
libpixman-1-0.dll
libpng16-16.dll
libstdc++-6.dll
libwinpthread-1.dll
zlib1.dll

还要注意,要制作一个完全独立的应用程序,您还需要做一些其他的事情,尤其是在您使用股票图标的情况下;有关这方面的更多详细信息,请参阅https://***.com/a/34673860/7345298。但是请注意,我需要复制 16x16 目录而不是可扩展目录。

编辑:我实际上发现以下命令也非常有用:ldd mygtkapp.exe | grep '\/mingw.*\.dll' -o | xargs -I cp "" .。此命令实际上将 dll 复制到当前目录,无需自己费力地进行操作。

【讨论】:

如何打包主题和图标? @Lothar 通常,我只关注***.com/questions/26738025/… 和gtk.org/download/windows.php#Vcpkg(请参阅“构建和分发您的应用程序”部分)。但总的来说,很难知道什么是“正确”的方法——在找到可行的方法之前,您可能需要进行一些试验。 @Lothar 这个评论线程已经很老了(距我上次发表评论已近一年),但我看到 GTK 文档现在包含 instructions 用于打包主题和图标。 我看到这种方法经常使用,比如here,但由于某种原因,ldd mygtkapp.exe 没有列出任何 gtk dll,只有 Windows 的,比如ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffb1c5f0000) ntdll.dll => /c/Windows/SysWOW64/ntdll.dll (0x77b50000) wow64.dll => /c/WINDOWS/System32/wow64.dll (0x7ffb1a820000) wow64win.dll => /c/WINDOWS/System32/wow64win.dll (0x7ffb1c270000) @Jack 你知道为什么会这样吗?【参考方案2】:

您对Windows page of the GTK website 有一些提示。这是名为 Building and distributing your application 的部分。它包含一篇关于 distributing a GTK application on Windows 的博文。

建议的解决方案是为您的应用程序创建一个 MSYS2 包,然后将其及其所有依赖项(其中包括 GTK)安装在特定目录中,以便您可以重新分发整个包。

2020-12-09 编辑:

阅读其他答案,我想补充一点,此方法不仅可以正确获取共享对象和二进制文件的依赖关系,而且还应该适用于其他类型的资源(图像、帮助文件等)所需的包,以及在运行时使用基于dlopen 的函数加载的共享对象。这是您无法通过调用 ldd 来查找依赖项来实现的。

【讨论】:

不,你把事情搞混了。 msi 工具之类的工具会将文件打包在一起以生成 msi 包。他们假设您知道要发送哪些文件。在 OP 问题中,他不知道要运送什么。您可以使用 msitools、wix、nsis 或其他任何东西作为第二步,但首先您必须确定要分发的内容,这就是我的答案。 我希望人们不要从为最终用户应用程序打包 msys2 的这种愚蠢行为开始。唯一的方法是了解需要哪些文件。 @Lothar:你没抓住重点。开发人员为她的应用程序创建 msys2 包。然后她可以使用 pacman(msys2 提供的包管理器)将她的应用程序及其依赖项安装到单独的目录中。因此,您让依赖关系求解器完成查找所需文件的工作。这是您为最终用户打包的内容。另外,使用 msys2 的人也可以轻松安装您的软件包。 那么如何在 msi 安装程序中隐藏 msys2?这不是它应该的方式。没有 pacman,也没有其他包管理器。您是书呆子,而不是 Windows 管理员。人们根本不会接受这一点——而且有充分的理由。 你能不能冷静下来谈谈技术,而不是叫我书呆子?【参考方案3】:

以下过程可用于获取必要的 DLL:

    下载Listdlls 让您的应用程序继续运行 打开 Listdlls.exe 所在的 PowerShell 窗口 使用命令 ./Listdlls.exe application_name.exe 将所有列出的路径复制到文本文件中 删除文本文件中所有包含“C:\WINDOWS*”的行 只保留文本中包含“C:\msys64*...*.dll”的行 文件 打开 Msys2 外壳 使用 $ cp "paste_all_paths_from_dlls" "destination_path"

使用$ cp 命令前的注意事项。在您的文本文件中,将路径中的“\”更改为“/”并删除换​​行符。

【讨论】:

【参考方案4】:
ldd kangaroo.exe | grep '\/mingw64\/bin\/.*dll' -o | xargs -I cp "" .

【讨论】:

这几乎是我在自己的答案中写的——唯一的区别是你使用grep -o,而我使用sed

以上是关于如何在 Windows 上分发 GTK+ 应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有 MSYS2 的 Windows 上构建 GTK+3 程序?

如何在 Windows 7+ 和 MSYS2 上的 GTK3 上获取本机 Windows 装饰

如何使用 MSYS2 在 Windows 上安装 GTK3 和 minGW

使用 Meson 在 Windows 上构建和运行 GTK 应用程序

在windows上设置Gtk开发

无法在 Fedora Eclipse 上构建 GTK+ Windows 应用程序