microsoft/vcpkg

gtk missing resources

NNemec opened this issue Β· 15 comments

My gtk application ported to Windows via vcpkg crashes because it misses an essential resource ("image-missing.png"). As I found, that file is contained beneath gtk/icons and referenced in the file gtk/gtk.gresource.xml - which to my understanding should be compiled via glib-compile-resources and linked into the library. The CMakeLists.txt contained in vcpkg/ports/gtk does not mention any of this, so I assume it is simply not yet implemented.

  1. Missing resource files, we need to install them.
  2. Need to modify the resource mapping table file, like: resource:///org/gtk/libgtk <-> C:\\vcpkg\\buildtrees\\gtk\src to resource:///org/gtk/libgtk <-> C:\\vcpkg\\installed\\x86-windows\\share\\gtk\\src
    It looks like the mapping table generated in the Makefile(Line 7882).

Just wondering: isn't it possible to compile the resources and link them into the library?

@NNemec I don't think so. Compiling resource files into the library will cause the size of the library to grow, and this is not what the author intended.

The best way I can find to work around this until it's fixed is to grab the latest versions of mingw-w64-x86_64-adwaita-icon-theme and mingw-w64-x86_64-hicolor-icon-theme from MSYS2 and extract the icons folder from each of them into installed\x86-windows\share/installed\x64-windows\share.

@ketsuban I don't agree with you.
Since vcpkg has export function, these absolute paths will be wrong when exporting gtk.
Therefore, we need to make sure that gtk can use relative paths so that we can use it.

This smells like a buildsystem issue from the port. Its seriously infuriating that Microsoft would ship a piece of software that's completely broken cause of their botched port... Seriously, you took a piece of software, ripped the entirety of its Build system, didn't even check that the examples work and happily made it available in your pkg manager... Congrats, you became a linux distribution πŸŽ‰

Anyhow, an upstream meson port just landed in the latest gtk3 release, 3.24.9 so vcpkg should be able to switch to something that isn't broken by default in the hopes that it fixes this.

Hello everyone, I tried to solve this issue with PR #7942, I wrote a test program and it seems to work fine.
But I am not familiar with gtk, I am not sure I can fix this issue. Can anyone help with the test?

My code here:

#include <gtk/gtk.h>
#include <libintl.h>
#define _(x) gettext (x)
#define N_(x) (x)

#define GETTEXT_PACKAGE "gtk-hello"
#define LOCALEDIR "mo"

const char *greetings[] = { "Hello World",
				 "Witaj ?wiecie",
				 "δΈ–η•Œγ«δ»Šζ—₯は" };

const char* choose_greeting()
{
	return greetings[g_random_int_range(0, G_N_ELEMENTS(greetings))];
}

static void cb_button_click(GtkButton *button, gpointer data)
{
	GtkWidget *label = GTK_WIDGET(data);

	g_assert(label != NULL);
	gtk_label_set_text(GTK_LABEL(label), choose_greeting());
}

static gboolean cb_delete(GtkWidget *window, gpointer data)
{
	gtk_main_quit();
	return FALSE;
}

int main(int argc, char *argv[])
{
	GtkWidget* window, *button, *label, *vbox;

	bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
	bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
	textdomain(GETTEXT_PACKAGE);

	gtk_init(&argc, &argv);

	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	button = gtk_button_new_with_label(_("Hello World"));
	label = gtk_label_new(choose_greeting());
	vbox = gtk_vbox_new(FALSE, 0);

	gtk_container_add(GTK_CONTAINER(window), vbox);
	gtk_container_add(GTK_CONTAINER(vbox), label);
	gtk_container_add(GTK_CONTAINER(vbox), button);

	g_signal_connect(G_OBJECT(window), "delete-event",
		G_CALLBACK(cb_delete), NULL);

	g_signal_connect(G_OBJECT(button), "clicked",
		G_CALLBACK(cb_button_click), label);

	gtk_widget_show_all(window);
	gtk_main();

	return 0;
}

Hello @JackBoosY and @ras0219-msft.

I've been willing to take a shoot at this problem to help unblock one of the biggest issues in the Rust GUI story. Currently I've been working on a vcpkg integration within Cargo called AutoVcpkg, and it currently works very well, the last missing piece is solving this issue with these missing assets.

I'll be testing @JackBoosY PR in the next days, hope this will help accelerate the fix and merge.

Also, I would like to express how important vcpkg is and take the time to thank you guys for putting the time and effort on this. Unfortunately some projects chose to go with weird build systems that nobody uses instead of using a factual standard like CMake. That unfortunately requires a lot more effort bringing these libraries mainstream, but at least it looks like vcpkg now can also manage these lesser build systems.

And more, there are some people that apparently even being part of open source projects, do not understand how open source work happens - or is that only when a company put actual resources on it? Anyway, please ignore these people and keep the good work.

@fungos Thanks for your contribution!
For most ports, limited by their knowledge, we are likely to cause errors when upgrading or adding features, so we hope that the official will handle these updates to ensure port quality.

For gtk, I found that gtk completely removed the msvc project in its source and converted to makefile project in the next major version update, so I think my PR is experimental.

Which version they changed to Makefile? I know next release is going with a thing called Meson, which is sad.

Anyway, I tried your PR and got everything compiling, but nothing linking as I didn't find yet how to fix the libraries path to use the vcpkg libraries previously built.

To get there I needed to patch a few things you can see below:

    set(GTK_PROPS_FILE ${SOURCE_PATH}/build/win32/vs15/gtk3-version-paths.props)
    set(GTK_PROPS_FILE_BAK ${SOURCE_PATH}/build/win32/vs15/gtk3-version-paths.props.bak)
    # Bakup prop file
    if (NOT EXISTS ${GTK_PROPS_FILE_BAK})
        configure_file(${GTK_PROPS_FILE} ${GTK_PROPS_FILE_BAK} COPYONLY)
    endif()
    # Set install path
    configure_file(${GTK_PROPS_FILE_BAK} ${GTK_PROPS_FILE} COPYONLY)
    file(READ ${GTK_PROPS_FILE} GTK_PROPS)
    file(TO_NATIVE_PATH ${CURRENT_PACKAGES_DIR} NATIVE_PATH_REL)
    file(TO_NATIVE_PATH ${CURRENT_PACKAGES_DIR}/debug NATIVE_PATH_DBG)
    string(REPLACE "<GlibEtcInstallRoot>$(SolutionDir)\\..\\..\\..\\..\\vs$(VSVer)\\$(Platform)</GlibEtcInstallRoot>"
                "<GlibEtcInstallRoot>$(SolutionDir)..\\..\\..\\..\\..\\..\\..\\installed\\x64-windows\\include</GlibEtcInstallRoot>"
                GTK_PROPS "${GTK_PROPS}"
    )
    string(REPLACE "<CopyDir>..\\..\\..\\..\\vs$(VSVer)\\$(Platform)<\/CopyDir>"
                "<CopyDir Condition=\"\'$(Configuration)|$(Platform)\'==\'Release|Win32\' Or \'$(Configuration)|$(Platform)\'==\'Release|x64\'\">${NATIVE_PATH_REL}<\/CopyDir>\r\n    <CopyDir Condition=\"\'$(Configuration)|$(Platform)\'==\'Debug|Win32\' Or \'$(Configuration)|$(Platform)\'==\'Debug|x64\'\">${NATIVE_PATH_DBG}<\/CopyDir>"
                GTK_PROPS "${GTK_PROPS}"
    )
    file(WRITE ${GTK_PROPS_FILE} "${GTK_PROPS}")


    set(GTK_PROPS_FILE ${SOURCE_PATH}/build/win32/vs15/gtk3-build-defines.props)
    set(GTK_PROPS_FILE_BAK ${SOURCE_PATH}/build/win32/vs15/gtk3-build-defines.props.bak)
    # Bakup prop file
    if (NOT EXISTS ${GTK_PROPS_FILE_BAK})
        configure_file(${GTK_PROPS_FILE} ${GTK_PROPS_FILE_BAK} COPYONLY)
    endif()
    # Set install path
    configure_file(${GTK_PROPS_FILE_BAK} ${GTK_PROPS_FILE} COPYONLY)
    file(READ ${GTK_PROPS_FILE} GTK_PROPS)
    string(REPLACE 
            "<AdditionalIncludeDirectories>..\\..\\..;$(GlibEtcInstallRoot)\\include\\gdk-pixbuf-2.0;$(GlibEtcInstallRoot)\\include\\pango-1.0;$(GlibEtcInstallRoot)\\include\\atk-1.0;$(GlibEtcInstallRoot)\\include\\cairo;$(GlibEtcInstallRoot)\\include\\gio-win32-2.0;$(GlibEtcInstallRoot)\\include\\glib-2.0;$(GlibEtcInstallRoot)\\lib\\glib-2.0\\include;$(GlibEtcInstallRoot)\\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>"
            "<AdditionalIncludeDirectories>..\\..\\..;$(GlibEtcInstallRoot)\\gdk-pixbuf;$(GlibEtcInstallRoot)\\pango;$(GlibEtcInstallRoot)\\atk;$(GlibEtcInstallRoot)\\cairo;$(GlibEtcInstallRoot)\\gio;$(GlibEtcInstallRoot)\\glib;$(GlibEtcInstallRoot);$(GlibEtcInstallRoot)\\..\\lib\\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>"
                GTK_PROPS "${GTK_PROPS}"
    )
    file(WRITE ${GTK_PROPS_FILE} "${GTK_PROPS}")

    file(COPY ${CMAKE_CURRENT_LIST_DIR}/msvc_recommended_pragmas.h DESTINATION ${SOURCE_PATH}/gdk)
    file(COPY ${CMAKE_CURRENT_LIST_DIR}/msvc_recommended_pragmas.h DESTINATION ${SOURCE_PATH}/gtk)
    file(COPY ${CMAKE_CURRENT_LIST_DIR}/msvc_recommended_pragmas.h DESTINATION ${SOURCE_PATH}/demos/icon-browser)
    file(COPY ${CMAKE_CURRENT_LIST_DIR}/msvc_recommended_pragmas.h DESTINATION ${SOURCE_PATH}/demos/gtk-demo)

Note that in the above I did hardcode x64-windows, because I didn't took the time to find the right variable to use, I was just trying to get it building. :)

I also had to copy a msvc_recommended_pragmas.h that I copied and modified from gdkmm, into a few directories, this can be improved copying into a single place and fixing include paths.

This is the header I used with some new pragmas added:

#ifndef _MSC_VER
#pragma error "This header is for Microsoft VC only."
#endif /* _MSC_VER */

/* Make MSVC more pedantic, this is a recommended pragma list
 * from _Win32_Programming_ by Rector and Newcomer.
 */
#pragma warning(error:4002) /* too many actual parameters for macro */
#pragma warning(error:4003) /* not enough actual parameters for macro */
#pragma warning(1:4010)     /* single-line comment contains line-continuation character */
#pragma warning(error:4013) /* 'function' undefined; assuming extern returning int */
#pragma warning(1:4016)     /* no function return type; using int as default */
#pragma warning(error:4020) /* too many actual parameters */
#pragma warning(error:4021) /* too few actual parameters */
#pragma warning(error:4027) /* function declared without formal parameter list */
#pragma warning(error:4029) /* declared formal parameter list different from definition */
#pragma warning(error:4033) /* 'function' must return a value */
#pragma warning(error:4035) /* 'function' : no return value */
#pragma warning(error:4045) /* array bounds overflow */
#pragma warning(error:4047) /* different levels of indirection */
#pragma warning(error:4049) /* terminating line number emission */
#pragma warning(error:4053) /* An expression of type void was used as an operand */
#pragma warning(error:4071) /* no function prototype given */
#pragma warning(disable:4101) /* unreferenced local variable */
#pragma warning(error:4150)

#pragma warning(disable:4244)	/* No possible loss of data warnings */
#pragma warning(disable:4305)   /* No truncation from int to char warnings */

/* vcpkg */
#pragma warning(disable:4018)   /* signed/unsigned */
#pragma warning(disable:4090)   /* const qualifiers */
#pragma warning(disable:4098)   /* void function returning value - wtf gtk */
#pragma warning(disable:4996)   /* deprecated */
#pragma warning(disable:4133)   /* incompatible types */
#pragma warning(disable:4715)   /* control paths retrun */
#pragma warning(disable:4146)   /* unary operator */
#pragma warning(disable:4267)   /* downcast loss */
#pragma warning(disable:4273)   /* dll */

#pragma warning(error:4819) /* The file contains a character that cannot be represented in the current code page */

/* work around Microsoft's premature attempt to deprecate the C-Library */
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NONSTDC_NO_WARNINGS

Can you please fix the hardcoded x64-windows with the right variable and try these changes on your PR? Then I can make another testing round.

@fungos It seems that the official has removed the makefile for windows in the latest version.

My PR is experimental, so it can only be used in the current version.
We tend to use CMakeLists.txt to build gtk, but it seems that many important steps are missing.
If you can list the build steps, I can rewrite CMakeLists.txt to solve this issue.

And vcpkg also supports building ports using meson, but I'm not familiar with it (see port fribidi).

So, my PR draft above is able to build GTK 3.24.10 using meson build and the icon files are correctly installed in share. Differently from @alatiera suggestion, the issue is surprise surprise broken on their end, not by default though.

Their project configuration is broken. The icons are delivered and installed by the project icon-browser, which is a demo project and as normally expected in practice a demo thing is not supposed to be essential. But then, the final install step for GTK would try to update the icon cache by running gtk-update-icon-cache and would error out because the demo wasn't build.

Well the irony, if someone there just once tried to build GTK without demos, they would have caught this issue with their broken shit.

Differently from @alatiera suggestion, the issue is surprise surprise broken on their end, not by default though.

If it's not broken by default you did something to break it though?

Gtk does include some core icons but they are expected to be bundled in the resources, not sure why icon browser is deciding to install them to the filesystem

if someone there just once tried to build GTK without demos

It would still work, because we'd have adwaita-icon-theme and the embedded icons

Can't find the upstream issue for this btw

I hope this issue will be resolved as soon as possible, because it has been going on for a long time, but I am very busy.
Can any contributor take it over? I can give some help.

Since gtk's build system has been replaced with the officially recommended meson, please reopen it if this issue exists.