Packaging GTK on windows documentation suggestions

For reference, here is the existing page:

It links to a blog post, which suggests creating a whole pacman package manifest and using that, or copying what gedit did which seems fairly complicated. Instead, I would suggest something like this:

Sample distribution structure (64 bit)

  • app.exe is your app
  • app_icon.svg is your app icon. Should be named to follow reverse dns notation (e.g.,,
  • 16x and 32x sized icons are needed, one for standard dpi, one for hdpi
  • The action icons are icons common gtk widgets use, you may need others, or none of them
  • bin, lib, and share correspond to the same directories in C:\msys64\mingw64
  • After copying loaders.cache, change the line from # LoaderDir = C:\msys64\mingw64\lib\gdk-pixbuf-2.0\2.10.0\loaders to # LoaderDir = "..\lib\gdk-pixbuf-2.0\2.10.0\loaders"
  • libpixbufloader-png.dll and libpixbufloader-svg.dll are common file formats, but if you use e.g. jpegs, make sure to add the corresponding dll as well

β”œβ”€β”€ bin
β”‚ β”œβ”€β”€ app.exe
β”‚ β”œβ”€β”€ libatk-1.0-0.dll
β”‚ β”œβ”€β”€ libbz2-1.dll
β”‚ β”œβ”€β”€ libcairo-2.dll
β”‚ β”œβ”€β”€ libcairo-gobject-2.dll
β”‚ β”œβ”€β”€ libdatrie-1.dll
β”‚ β”œβ”€β”€ libepoxy-0.dll
β”‚ β”œβ”€β”€ libexpat-1.dll
β”‚ β”œβ”€β”€ libffi-6.dll
β”‚ β”œβ”€β”€ libfontconfig-1.dll
β”‚ β”œβ”€β”€ libfreetype-6.dll
β”‚ β”œβ”€β”€ libfribidi-0.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
β”‚ β”œβ”€β”€ 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
β”‚ β”œβ”€β”€ libpng16-16.dll
β”‚ β”œβ”€β”€ libstdc+Β±6.dll
β”‚ β”œβ”€β”€ libthai-0.dll
β”‚ β”œβ”€β”€ libwinpthread-1.dll
β”‚ └── zlib1.dll
β”œβ”€β”€ lib
β”‚ └── gdk-pixbuf-2.0
β”‚ └── 2.10.0
β”‚ β”œβ”€β”€ loaders
β”‚ β”‚ β”œβ”€β”€ libpixbufloader-png.dll
β”‚ β”‚ └── libpixbufloader-svg.dll
β”‚ └── loaders.cache
└── share
└── icons
β”œβ”€β”€ Adwaita
β”‚ β”œβ”€β”€ 16x16
β”‚ β”‚ └── actions
β”‚ β”‚ β”œβ”€β”€ list-add-symbolic.symbolic.png
β”‚ β”‚ β”œβ”€β”€ list-remove-symbolic.symbolic.png
β”‚ β”‚ β”œβ”€β”€ pan-down-symbolic.symbolic.png
β”‚ β”‚ β”œβ”€β”€ pan-up-symbolic.symbolic.png
β”‚ β”‚ β”œβ”€β”€ window-close-symbolic.symbolic.png
β”‚ β”‚ β”œβ”€β”€ window-maximize-symbolic.symbolic.png
β”‚ β”‚ β”œβ”€β”€ window-minimize-symbolic.symbolic.png
β”‚ β”‚ └── window-restore-symbolic.symbolic.png
β”‚ └── 32x32
β”‚ └── actions
β”‚ β”œβ”€β”€ list-add-symbolic.symbolic.png
β”‚ β”œβ”€β”€ list-remove-symbolic.symbolic.png
β”‚ β”œβ”€β”€ pan-down-symbolic.symbolic.png
β”‚ β”œβ”€β”€ pan-up-symbolic.symbolic.png
β”‚ β”œβ”€β”€ window-close-symbolic.symbolic.png
β”‚ β”œβ”€β”€ window-maximize-symbolic.symbolic.png
β”‚ β”œβ”€β”€ window-minimize-symbolic.symbolic.png
β”‚ └── window-restore-symbolic.symbolic.png
└── hicolor
└── scalable
└── apps
└── app_icon.svg

In addition, you may want to create an msi installer. You can use WiX, sample manifest here (taken from my project, and therefore needs to be generalized into a more generic template):

Converting an svg to an ico (requires inkscape and imagemagick, does the glob work? Not sure, didn’t want to manually list all 14 files):
inkscape -z -e icon1.png -w 16 -h 16 icon.svg
inkscape -z -e icon2.png -w 20 -h 20 icon.svg
inkscape -z -e icon3.png -w 24 -h 24 icon.svg
inkscape -z -e icon4.png -w 30 -h 30 icon.svg
inkscape -z -e icon5.png -w 32 -h 32 icon.svg
inkscape -z -e icon6.png -w 36 -h 36 icon.svg
inkscape -z -e icon7.png -w 40 -h 40 icon.svg
inkscape -z -e icon8.png -w 48 -h 48 icon.svg
inkscape -z -e icon9.png -w 60 -h 60 icon.svg
inkscape -z -e icon10.png -w 64 -h 64 icon.svg
inkscape -z -e icon11.png -w 72 -h 72 icon.svg
inkscape -z -e icon12.png -w 80 -h 80 icon.svg
inkscape -z -e icon13.png -w 96 -h 96 icon.svg
inkscape -z -e icon14.png -w 256 -h 256 icon.svg
convert *.png icon.ico

Questions still to be answered:

  • The website says that due to the gpl license, you also need to distribute gtk etc source code. What does that entail? Is linking to gtk gitlab enough? What about your own gpl licensed source code?
  • Better mingw64/msys2 usage instructions need to be written. I withheld from doing this since I only have rust stuff, not sure how other languages locate gtk libs and stuff
  • macOS also needs better documentation + dmg template, but I haven’t gotten around to doing that for my app yet, so I have nothing for that at this time
  • When alt-tabbing my gtk app, the icon over the window preview was the generic gtk icon, not sure why
  • What other files (gtk builder xml, gsettings etc) should be shown in the sample?
  • Dark vs light theme: Should the app provide a switch between these? How should this be handled?

This looks great! Thanks for working on it.

GTK is released under the terms of the GNU Lesser General Public License; this means two things, generally:

  • you need to ensure that you can provide the source code for all the dependencies released under that licenseβ€”in this case: GLib, GTK, GdkPixbuf, and any other library released under those terms
  • you need to ensure that any change you made to GTK is also released under the same terms as GTK

Plus, you need to allow re-linking your application against a different version of GTK.

Pointing to the upstream repository, or to your own fork, is generally enough, unless somebody asks you to send them a USB drive with the sources. :slight_smile:

Indeed; it’d also be great to have instructions on using MSVC as well.

Did you call gtk_window_set_icon()?

GSettings schemas are a good topic; you could start from this StackOverflow question I answered a while ago on the topic.

This is entirely up to the application; you can toggle the preference using the GtkSettings:gtk-application-prefer-dark-theme property.

1 Like

If MSYS2 package manager supports that (this is a big β€œif”, i’m not a fan of Arch, so i don’t really know my way around pacman), it should be possible to grab the dependency tree from the package manager (staring with the packages that your application uses - hopefully, you know that at least). Then use pacman to install all of these packages into a staging directory (is that supported?) and note all the post-install scripts (also, preferably, the pre-remove and post-remove scripts; maybe even pre-install). Then install the app into that directory (again, this should be mostly what DESTDIR=... meson install installs; if meson doesn’t install something correctly, fix meson build scripts). If some of the symlinks are absolute, fix the packages to make the symlinks relative (absolute symlinks are not relocatable, that is bad!). Then note all the symlinks and write a script that restores them (this could be automated). Then write a script that does the same thing that pre-remove, post-remove, pre-install and post-install scripts do (β€œwrite”, because these scripts almost always use a POSIX shell (mostly bash), and you must assume that user’s machine doesn’t have a POSIX shell, so you’d have to write them from scratch using Windows cmd or maybe Powershell). Then pack the staging directory + symlink-restoring-script + install-scripts.

To install: unpack, restore symlinks, run the post-install script (i guess the pre-install script should be packed separately, otherwise there wouldn’t be any difference between pre-install and post-install; or maybe unpack into a staging directory first, then run pre-install, then copy the files to the target location (another big headache, by the way - built-in Windows copy utilities suck), then run post-install).
That could be wrapped into msi or exe, probably. Never tried doing that.

Anyway, this should deploy the application correctly, as if it was installed by a package manager.

As you might have guessed from all the "if"s and "probably"s, this is not a fully-solved problem.

Not the best solution - you almost certainly don’t need the full package, and it’s over complicated. Hence this document - describing what files you actually need where, so you can just copy them into a zip and be done with it. Interesting idea though!

Well, it’s a solution. It allows for creation of functional installs without possessing intimate technical knowledge of what should go where, by exploiting expert knowledge encoded into the package manager. Ever wondered why, for example, Debian tends to take the things that one compiled source package installs and split them into multiple packages (often separate package for each shared library group, one package for tools (sometimes even one package per tool, if there are many of them!), one for developer documentation, one for developer files)? Because it allows you to install only the things you need.

I’m not involved in packaging stuff, so i don’t know how well they split the packages (though if they are anything like me, the answer would be β€œvery lazily”), but there’s a good chance that the package manager does know what all your runtime dependencies are - without a lot of unnecessary extras.

There’s an option of using ldd, or ntldd, or other tools (i think it’s possible to creatively process objdump output for the same purpose) that show you what shared libraries are required for an executable, but these do not account for things like gspawn-win32-helper.exe, for plugins, for gschema files, etc.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.