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

22

我已经通过MSYS和MinGW在Windows上安装了GTK+(特别是GTK3)。现在我想将GTK+的dll文件复制到我的应用程序目录,以便在没有全局GTK+安装的计算机上运行它。哪些dll文件是GTK+操作所必需的?

编辑: GTK+文档现在包含在Windows上分发所需的图标和主题的说明。(虽然它没有为分发相关的DLL文件提供说明——请参见下面的答案。)


3
我通常使用ntldd和试错的结合方式。你可以通过将路径设置为空,然后运行你的应用程序来测试它。但是现在我在自己的构建系统中使用静态编译,因此不需要DLL文件。 - David Grayson
4个回答

14

原来运行ldd mygtkapp.exe(使用MinGW提供的ldd)可以列出所有需要运行它的dll。为了仅获取GTK依赖项(而不是例如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://dev59.com/918d5IYBdhLWcg3wgya4#34673860。不过要注意,我需要复制16x16目录而不是可缩放目录。

编辑:我发现以下命令也非常有用:ldd mygtkapp.exe | grep '\/mingw.*\.dll' -o | xargs -I{} cp "{}" .。这个命令会将dll文件复制到当前目录,避免了手工操作的繁琐过程。


@Lothar 这个评论线程已经很老了(距离我上次评论已经将近一年),但是我看到 GTK 文档现在包含了说明,可以打包主题和图标。 - bradrn
我经常看到这种方法的使用,比如这里,但不知何故ldd mygtkapp.exe没有列出任何gtk dll,只有windows dll,例如: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
@Jack,你最终找出这是为什么发生的了吗? - muszeo
如果我没记错的话,我当时使用了一个用D语言编写的Gtk+包装器,并且它使用了LoadLibrary()函数,所以ldd工具没有将它们列出来,于是我进入该包装器的源代码,并成功地找到了该包装器正在使用LoadLibrary()加载的dll字符串列表,将它们放在与目标可执行文件相同的文件夹中,它就能够完美地工作了。 - Jack
如果您只看到Windows DLL,请打开“msys2 MingGW终端”并重新运行上述命令,它将列出所有所需的DLL。 - coletrain
显示剩余2条评论

12

您可以在GTK网站的Windows页面上找到一些提示,这是名为“构建和分发您的应用程序”的部分。其中包含有关在Windows上分发GTK应用程序的博客文章。

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

2020-12-09编辑:

阅读其他答案后,我想补充说明,此方法不仅可以获取共享对象和二进制文件的依赖项,还可以处理其他类型的资源(图像、帮助文件等),这些资源在所需软件包中,以及在运行时使用基于dlopen的函数加载的共享对象。这是您无法通过只调用ldd查找依赖项来实现的。


4
不,你混淆了概念。像 msi 工具这样的工具会将文件打包在一起生成 msi 包。它们假定你知道要传送哪些文件。在 OP 的问题中,他不知道要传送什么。你可以在第二步使用 msitools、wix、nsis 或其他工具,但首先你必须确定你要分发什么,这就是我的答案所涉及的内容。 - liberforce
4
@Lothar:你没理解重点。开发者为她的应用程序创建msys2软件包。然后,她可以使用msys2提供的软件包管理器pacman,在单独的目录中安装她的应用程序及其依赖项。因此,您可以让依赖项求解器查找所需的文件。这就是您为最终用户打包的内容。而且,作为额外的好处,使用msys2的人们也可以轻松地安装您的软件包。 - liberforce
5
请冷静下来,用技术术语与我交谈,而不要称呼我为书呆子。 - liberforce
非常好的答案 :) 还有其他选项,但这似乎是最好的选择(也是最省力的选择) - tagelicht
他们在GTK名称中去掉了“+”符号。 - Melroy van den Berg
显示剩余4条评论

2
以下步骤可用于获取所需的DLL文件:
  1. 下载Listdlls
  2. 保持您的应用程序运行
  3. 打开包含Listdlls.exe的PowerShell窗口
  4. 使用命令./Listdlls.exe 应用程序名称.exe
  5. 将所有列出的路径复制到文本文件中
  6. 删除文本文件中包含"C:\WINDOWS*"的所有行
  7. 仅留下包含"C:\msys64*...*.dll"的行
  8. 打开Msys2 Shell
  9. 使用$ cp "从dlls粘贴所有路径" "目标路径"
在使用$cp命令之前,请注意以下几点。 在文本文件中,将路径中的"\"改为"/",并删除换行符。

0
ldd kangaroo.exe | grep '\/mingw64\/bin\/.*dll' -o | xargs -I{} cp "{}" .

2
这基本上就是我在自己的答案中写的内容——唯一的区别是你使用了 grep -o,而我使用了 sed - bradrn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接