Skip to content
FelipeAlafy edited this page Nov 26, 2021 · 9 revisions

From Linux for Windows 64 Bit

(You should be able to compile for 32 bit by replacing all occurrences of x86_64 with i686 or something to that effect.)

Compilation

Get the go package: go get github.com/gotk3/gotk3/gtk

Install w64-mingw32 compiler and the w64-mingw32 GTK3 libraries. This is dependent on your distribution. See below for how to achieve this in Archlinux.

Build gotk3 (This might build stuff in your /usr/x86_64-w64-mingw32 path, so try with sudo if it doesn't work):

PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
CGO_ENABLED=1 \
CC=x86_64-w64-mingw32-cc \
GOOS=windows \
GOARCH=amd64 \
go install github.com/gotk3/gotk3/gtk

Finally, cross-compile your app:

CGO_ENABLED=1 \
CC=x86_64-w64-mingw32-cc \
GOOS=windows \
GOARCH=amd64 \
go build -ldflags -H=windowsgui

You should now find the .exe in the project directory.

If you do need a CMD window with your app's GUI (e.g. for easier user-side debugging), remove the -ldflags -H=windowsgui option.

Deployment

To package your app copy the GTK3 DLLs (and those of any other C libraries you might be using) from your mingw32 bin path (here: /usr/x86_64-w64-mingw32/bin/) to your app path:

cp /usr/x86_64-w64-mingw32/bin/{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-3-0.dll,libgdk_pixbuf-2.0-0.dll,libgio-2.0-0.dll,libgit2.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,libjasper-1.dll,libjpeg-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,libwinpthread-1.dll,zlib1.dll} path/to/my/app/

Don't forget to copy any resources as well (Glade files, configs, etc).

You should then be able to test-run your app with wine:

wine app.exe

If you're still getting missing-DLL errors in the shape of err:module:import_dll Library libxyz.dll (which is needed by L"Z:\\home\\me\\path\\to\\my\\app\\libxyz.dll") not found, then simply also copy those from your mingw32 bin path.

The resulting Windows dist folder weighs on the order of ~35MB here.

Library installation in Archlinux

In Archlinux with an AUR-capable package manager like yaourt installation of the mingw32 libs is relatively easy:

yaourt -S --asdeps mingw-w64-cairo-bootstrap mingw-w64-freetype2-bootstrap (There are circular dependencies that yaourt can't resolve on its own, so install the bootstrapped versions of these two packages as dependencies first)

yaourt -S mingw-w64-gtk3 (This pulls a lot of dependencies and it all takes a while to build. You could optionally add the --noconfirm flag, but this is potentially dangerous. You should always skim the PKGBUILD before installation from AUR to make sure it's not malicious.)

Alternative build using containers

Obtaining the mingw32 libraries if your distro doesn't package them can be a nightmare. On Arch, the AUR packages don't build properly and there are also security considerations - if you want to do CI you'd need to set up a custom cache, otherwise future updates could inject malware into your build. The aforementioned commands also might not work everywhere because different distro packages install the libs to different places on the filesystem.

One alternative some users have used is cross-compiling from within a Linux container. Then you can use the container's package manager to install libs, etc. without changing your local system. As an added benefit, Fedora comes with a wrapper to automatically generate an installer for Windows. Here is an example script that uses Buildah to cross-compile a gotk3 program for Windows. You could also achieve this with a Dockerfile. Be sure to edit the variables at the top of the file before running it:

winbuild.sh

If you need more control over the nsiswrapper part, you can run it once without the --run flag, save the resulting installer.nsi file, and edit it to your liking (you can customize things like the program name in Windows, storage location, icon, etc.). Then instead of the nsiswrapper command in the script you'd run makensis installer.nsi.

Using docker

  • Install docker on your current desktop.
  • Run container:
sudo docker run -it fedora /bin/bash
  • Install mingw on fedora
yum install mingw64-gtk3 go glib2-devel
  • Fix some errors:
bash -c "sed -i -e 's/-Wl,-luuid/-luuid/g' /usr/x86_64-w64-mingw32/sys-root/mingw/lib/pkgconfig/gdk-3.0.pc"
cd root
mkdir go
cd go
mkdir src pkg bin
cd src
  • Now you can configure git in this container to clone your repo or move or otherwise download it.
  • cd to your program.
  • Setup PKG and Gotk3, this will take about 8 minutes.
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/sys-root/mingw/lib/pkgconfig CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc GOOS=windows GOARCH=amd64 go install -v github.com/gotk3/gotk3/gtk`
CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc GOOS=windows GOARCH=amd64 go build -ldflags -H=windowsgui
  • Copy GTK Libs to your program.
yes | cp -r /usr/x86_64-w64-mingw32/sys-root/mingw/* .
  • Change to other shell
  • Get image id from current container
sudo docker ps -alq
  • Copy your program from container to your machine.
sudo docker cp <replace-with-your-image-id>:/root/go/src/path-to-your-program/ Destination-to-copy/

Attention: to run on windows install GTK-for-Windows-Runtime-Environment-Installer, and after that you're able to run your program.

Thanks Tom Schoonjans and Ghost. Original Post.