GTK3-cross-compile

Cross-compile a GTK3 app from Linux to Windows
git clone git://git.wrycode.com/wrycode/GTK3-cross-compile.git
Log | Files | Refs | README

commit 73d34c68cce7f27baaa7a70a38478faa61f97f7f
parent 8b1a44d06e4810d811be324f46a6cc23e687b8b4
Author: Nick Econopouly <wry@mm.st>
Date:   Wed,  5 Aug 2020 15:17:28 -0400

Remove stale links from README

Diffstat:
MREADME | 189++++++++++++++++++++++++++++++++++++++-----------------------------------------
1 file changed, 92 insertions(+), 97 deletions(-)

diff --git a/README b/README @@ -4,42 +4,35 @@ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -1 Introduction -══════════════ - - One of my research projects involves writing a Windows app for a - department at my school. I only run Linux. - - Here I’ve compiled the steps necessary to build and run a GUI [GTK3] - program on both Linux and Windows.This includes the frills most - Windows users expect, like a graphical installer, an icon on the - executable, and a program that looks like it was made for Windows. - - You can view the results of the tutorial in [this repository]. - - Create the demo C program from [the GTK documentation] and save it as - `main.c'. - - To compile the code on Linux, a simple - ┌──── - │ $ gcc -o main main.c `pkg-config --libs gtk+-3.0 --cflags gtk+-3.0` - └──── - will do the trick (you need pkg-config, GCC, and GTK3 installed). Test - the executable to make sure it works: - ┌──── - │ $ ./main - └──── +One of my research projects involves writing a Windows app for a +department at my school, but I only run Linux. I saved the steps for +building a GUI [GTK3] program on both Linux and Windows. This includes +the frills most Windows users expect, like a graphical installer, an +icon on the executable, and a program that looks like it was made for +Windows. + +As a starter program, create the demo C program from [the GTK +documentation] and save it as `main.c'. + +To compile the code on Linux, a simple +┌──── +│ $ gcc -o main main.c `pkg-config --libs gtk+-3.0 --cflags gtk+-3.0` +└──── +will do the trick (you need pkg-config, GCC, and GTK3 installed). Test +the executable to make sure it works: +┌──── +│ $ ./main +└──── [GTK3] <https://www.gtk.org/> -[this repository] <https://github.com/wrycode/GTK-demo-C> - [the GTK documentation] <https://developer.gnome.org/gtk3/stable/gtk-getting-started.html> -1.1 Windows setup -───────────────── + +Windows setup +═════════════ To build for Windows, you need to use [MinGW] to compile the executable, and then you need to bundle the MinGW GTK dlls so they’re @@ -59,77 +52,79 @@ [MinGW] <http://www.mingw.org/> -[Buildah] See section 1.2 +[Buildah] See section Automation + Buildah -1.1.1 Compiling for Windows -╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +Compiling for Windows +───────────────────── - On a Linux system with MinGW installed, you can compile the same + On a Linux system with MinGW installed you can compile the same program with something like: ┌──── │ $ x86_64-w64-mingw32-gcc -o main main.c `mingw64-pkg-config --cflags gtk+-3.0 --libs gtk+-3.0` └──── You should now have an executable called `main.exe'. Obviously this - won’t work on Linux, but it also won’t work on Windows until you make - the GTK libraries available to it at runtime. + executable won’t work on Linux, but it also won’t work on Windows + until you make the GTK libraries available to it at runtime. -1.1.2 Bundle GTK libraries -╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +Bundle GTK libraries +──────────────────── Make a subdirectory called `windows' and copy the `.exe' into it. Now copy the MinGW libraries over to the same folder. Unfortunately, different Linux distributions have different locations (and sometimes - even different names for the MinGW executables). On Fedora, they’re + even different names) for the MinGW executables. On Fedora, they’re found at `/usr/x86_64-w64-mingw32/sys-root/mingw/*'. -1.1.3 Test on Windows -╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +Test on Windows +─────────────── If you copy the whole `windows' folder to a Windows computer or VM, the program should now run as expected. Magically enough, [WINE] is - also able to run the program from Linux (although I don’t recommend - testing with WINE). + also able to run the program from Linux. + + However, the program looks bad because + • it uses GNOME’s Adwaita theme (which looks bad on Windows) + • it uses GTK to render the client-side decorations (the top of the + window with the exit button) + • there’s no icon for the program in Windows’ taskbar + • the program runs with a black command prompt window in the + background. - However, the program looks like bad because it uses GNOME’s Adwaita - theme (which looks bad on Windows), it uses GTK to render the - client-side decorations (the top of the window with the exit button), - there’s no icon for the program in Windows’ taskbar, and the program - runs with a black command prompt window in the - background. Furthermore, it’s not ideal to distribute the program by - zipping up this folder and sharing it. + Furthermore, it’s not ideal to distribute the program by zipping up + this folder and sharing it. [WINE] <https://en.wikipedia.org/wiki/Wine_(software)> -1.1.4 Fix Icon -╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +Fix Icon +──────── Download or create an icon. From within the code you can set the icon for the program like this: ┌──── │ GdkPixbuf *icon; - │ icon = create_pixbuf("icon.ico"); + │ icon = create_pixbuf("icon.ico"); │ gtk_window_set_icon(GTK_WINDOW(window), icon); └──── The code for `create_pixbuf' is: ┌──── │ GdkPixbuf *create_pixbuf(const gchar * filename) { - │ + │ │ GdkPixbuf *pixbuf; │ GError *error = NULL; │ pixbuf = gdk_pixbuf_new_from_file(filename, &error); - │ + │ │ if (!pixbuf) { - │ + │ │ fprintf(stderr, "%s\n", error->message); │ g_error_free(error); │ } - │ + │ │ return pixbuf; │ } └──── @@ -137,7 +132,7 @@ This will change the icon of the program while it’s running. It shows up correctly in the Windows taskbar and window decorations, but it won’t change the icon of the actual `.exe'. I still recommend - including this code, because it works to set the icon on Linux desktop + including this code because it works to set the icon on Linux desktop environments. To change the icon of the executable file on Windows, we have to use @@ -155,7 +150,7 @@ └──── Now we can add the `icon.res' resource file to the executable by - slightly modifying our GCC call: + slightly modifying our GCC command: ┌──── │ $ x86_64-w64-mingw32-gcc -o main main.c icon.res `mingw64-pkg-config --cflags gtk+-3.0 --libs gtk+-3.0` @@ -165,14 +160,14 @@ Windows. -1.1.5 Remove Command Prompt window -╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +Remove Command Prompt window +──────────────────────────── Just add the `-mwindows' flag to your compile command. -1.1.6 Fix Window Decorations -╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +Fix Window Decorations +────────────────────── You can disable the GTK client-side decorations by adding the following line to the code: @@ -185,8 +180,8 @@ bar. -1.1.7 Switch to a Windows GTK theme -╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +Switch to a Windows GTK theme +───────────────────────────── Adwaita looks bad on Windows. Search [Gnome-Look] for a different GTK3 theme to use with your app. You can choose a flatter, lighter theme or @@ -212,13 +207,13 @@ [Gnome-Look] <https://www.gnome-look.org/> -1.1.8 Generate an installer -╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +Generate an installer +───────────────────── - Here’s how to make an installer, so your users don’t have to manually - unzip this `windows/' folder, using a script called - [nsiswrapper]. Nsiswrapper generates an [NSIS] script and optionally - compiles it using `makensis'. + Here’s how to make an installer using a script called [nsiswrapper], + so your users don’t have to manually unzip this `windows/' + folder. Nsiswrapper generates an [NSIS] script and optionally compiles + it using `makensis'. `cd' into the `windows/' directory, and run: @@ -240,8 +235,8 @@ [NSIS] <https://sourceforge.net/projects/nsis/> -1.2 Automation + Buildah -──────────────────────── +Automation + Buildah +════════════════════ You may have noticed that I’ve been using Fedora to compile this program. I’m actually running Arch Linux, but MinGW packages aren’t @@ -265,79 +260,79 @@ │ setup () { │ # Create a fedora container │ container=$(buildah from fedora) - │ - │ # Install dependencies - │ buildah run $container dnf -y install mingw64-gtk3 mingw32-binutils mingw32-nsiswrapper - │ + │ + │ # Install dependencies + │ buildah run $container dnf -y install mingw64-gtk3 mingw32-binutils mingw32-nsiswrapper + │ │ # Fix typo in mingw library │ buildah run $container bash -c "sed -i -e 's/-Wl,-luuid/-luuid/g' /usr/x86_64-w64-mingw32/sys-root/mingw/lib/pkgconfig/gdk-3.0.pc" - │ + │ │ # Cache image to avoid re-downloading dependencies every time │ buildah commit $container my-gtk-app - │ + │ │ # Clean up │ buildah rm $container │ } - │ + │ │ build () { │ # Create a new container from the base one we created │ container=$(buildah from localhost/my-gtk-app) - │ + │ │ # Folder to hold everything needed for the windows installer: │ output_folder=windows │ yes | rm -r $output_folder │ mkdir $output_folder - │ + │ │ # Directory of your package in the container │ folder=/root/app - │ + │ │ # Copy program into container │ buildah copy $container . $folder - │ + │ │ # Name for the executable file on Windows │ executable_name="Demo.exe" - │ + │ │ # make some folders we'll need │ buildah run $container bash -c "cd $folder && mkdir -p $output_folder/share/themes $output_folder/etc/gtk-3.0" - │ + │ │ # generate a RC file with the windres utility to embed an icon into the .exe later on │ buildah run $container bash -c "cd $folder && x86_64-w64-mingw32-windres icon.rc -O coff -o icon.res" - │ + │ │ # copy some project resources │ buildah run $container bash -c "cd $folder && cp -r Windows10 $output_folder/share/themes && \ │ cp settings.ini $output_folder/etc/gtk-3.0/ &&\ │ cp icon.ico $output_folder" - │ + │ │ # Compile program │ buildah run $container bash -c "cd $folder && x86_64-w64-mingw32-gcc -mwindows -o $executable_name main.c icon.res \`mingw64-pkg-config --cflags gtk+-3.0 --libs gtk+-3.0\`" - │ + │ │ # Copy executable into installation folder │ buildah run $container bash -c "cd $folder && cp $executable_name $output_folder" - │ + │ │ # Copy mingw dlls into installation folder │ # This part may need to be personalized │ buildah run $container bash -c "yes | cp -r /usr/x86_64-w64-mingw32/sys-root/mingw/{bin/*.dll,share} $folder/$output_folder/" - │ + │ │ # Generate an installer │ buildah run $container bash -ic "cd $folder/$output_folder && nsiswrapper --run $executable_name ./*" - │ + │ │ # Copy the output from the container │ cp -ru $(buildah unshare buildah mount $container)$folder/$output_folder . - │ + │ │ # Clean up │ buildah rm $container │ } - │ + │ │ # This just checks whether the container already exists on your drive │ buildah inspect localhost/my-gtk-app &>/dev/null │ return_value=$? - │ + │ │ if [ $return_value -eq 1 ] │ then │ echo "Initial container setup" │ setup │ fi - │ + │ │ # Build project │ build └──── @@ -351,8 +346,8 @@ <https://github.com/containers/buildah/blob/master/docs/tutorials/01-intro.md> -1.3 References -────────────── +References +══════════ • [windows - How do I add an icon to a mingw-gcc compiled executable? - Stack Ov…]