After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 752837 - gobject and glib-compile-resources rely on .CRT$XCU section, no longer works with Win 10 UCRT (VS 2015)
gobject and glib-compile-resources rely on .CRT$XCU section, no longer works ...
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: win32
2.45.x
Other Windows
: Normal normal
: ---
Assigned To: gtk-win32 maintainers
gtk-win32 maintainers
: 766388 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2015-07-24 17:16 UTC by Arnav Singh
Modified: 2018-03-19 21:17 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
gobject: use a DllMain to initialize gobject on windows (3.87 KB, patch)
2015-10-09 11:26 UTC, Ignacio Casal Quinteiro (nacho)
none Details | Review
gobject: use a DllMain to initialize gobject on windows (4.06 KB, patch)
2015-10-10 11:29 UTC, Ignacio Casal Quinteiro (nacho)
committed Details | Review
gconstructor: Work around constructors being optimized away on VS2015 (2.43 KB, patch)
2015-11-06 12:59 UTC, Alexander Larsson
none Details | Review
gconstructor: Work around constructors being optimized away on MSVC (3.06 KB, patch)
2015-11-10 09:35 UTC, Fan, Chun-wei
committed Details | Review

Description Arnav Singh 2015-07-24 17:16:41 UTC
Apologies for mixing two components in the same bug report, but the underlying issue is the same even if the fix may not be.

gtypes from gobject uses G_DEFINE_CONSTRUCTOR for gobject_init_ctor - this uses __attribute__((constructor)) with GCC and the .CRT$XCU linker section with MSVC. The .CRT$XCU section trick no longer works with the new Universal CRT that ships with the Windows 10 SDK. That CRT does not use this linker section as part of its initialization routine, and in fact the linker does not even embed such a section in the binary. (In older CRTs, the CRT enumerates all linker sections starting with .CRT and executes each in alphabetical order.)

The standard Windows way of running code at library load and unload time is to use the library entry point DLLMain. glib-init.c does this already, with a `#if defined (G_OS_WIN32)` that prefers to use DllMain over G_DEFINE_CONSTRUCTOR.

The symptom of the bug for gobjects is that the constructor gobject_init_ctor does not run when gobject.dll is loaded, so static_quark_type_flags remains uninitialized, so g_type_register_fundamental() fires the assert g_assert_type_system_initialized().

Of course, since glib uses separate macros G_DEFINE_CONSTRUCTOR and G_DEFINE_DESTRUCTOR, it's not trivial to combine these into a single DllMain function if both are used, or if one is used multiple times. So a general solution for these two macros for userland code is unknown to me. However it can atleast be fixed for gobject.

I'm using this patch https://github.com/hexchat/gtk-win32/blob/2015/glib/gobject-init-ctor.patch (Note that it assumes G_OS_WIN32 is defined since that project only does Windows builds. A proper fix would check for it at both places.)

The code generated from glib-compile-resources has the same problem, which can be worked around by not relying on automatic registration and instead using --manual-register and registering manually. If a general solution for G_DEFINE_CONSTRUCTOR/DESTRUCTOR was found, then this would not be needed.
Comment 1 Arnav Singh 2015-07-25 03:33:51 UTC
Actually, the CRT does still use the .CRT section as before. The change in behavior from VS 2013 is that the function gets removed if it's not referenced anywhere else apart from the pragma that places it in the section.

For example, this will result in func_wrapper being called before main:

    static int func_wrapper(void) {
        return 0;
    }

    __pragma(section(".CRT$XCU", read)) __declspec(allocate(".CRT$XCU")) static int(*_arrayfunc1)(void) = func_wrapper;

    int main() {
        _arrayfunc1();
    }

... and this will result in func_wrapper not being called at all:


    static int func_wrapper(void) {
        return 0;
    }

    __pragma(section(".CRT$XCU", read)) __declspec(allocate(".CRT$XCU")) static int(*_arrayfunc1)(void) = func_wrapper;

    int main() {
    }

G_DEFINE_CONSTRUCTOR-annotated functions are like the latter case, since they're not directly called by any other code.

The G_DEFINE_CONSTRUCTOR macro does also place a forward declaration for the constructor function before the wrapper. I'm not sure if this was done with the intention to trick the compiler/linker into not eliding the wrapper. If so, this is apparently insufficient now.
Comment 2 Arnav Singh 2015-07-25 04:39:28 UTC
As expected, the optimization goes away when compiling without /GL (whole-program optimization).

I've also opened https://connect.microsoft.com/VisualStudio/feedback/details/1587892 for MSVC team's thoughts on the matter.
Comment 3 Matthias Clasen 2015-07-26 14:50:30 UTC
thanks for the analysis and for the msvc problem report, Arnav.
Comment 4 Fan, Chun-wei 2015-10-01 17:47:14 UTC
Hi Arnav,

For the GResources part, I think this is related to how the linker optimize things (this applies also for Visual Studio 2008+, BTW) ... as I came across a similar situation in building gtk3-demo, where I changed the linker flag to contain /opt:noref.

Can you try this: in your linker flags can you check whether you have /opt:noref instead of /opt:ref, while you still build the program using /GL compiler flag?  Doing this will be necessary when we don't use GResources with --manual-register, as you have noticed.  /opt:ref will drop any symbol from the DLL that is not referred from the "mainline code", which is what you noticed.

For the GObject DLL part, I am leaning more towards using a DllMain() on Windows (like you did), but use the constructor on other platforms (!G_OS_WIN32)-this is more or less like what Nacho did in libsoup (commit c5891e1).

Hope this helps.

With blessings, thank you!
Comment 5 Fan, Chun-wei 2015-10-01 17:52:41 UTC
(Note: /opt:ref is the default setting in a Release build, look for this under "Optimization" under "Linker" in project properties, as with /GL.  The GResource part applies to both building DLLs and executables that make use of GResource's without --manual-register)
Comment 6 Fan, Chun-wei 2015-10-07 13:56:26 UTC
Hi Arnav,

Did you manage to get a working build for GResources using /opt:noref in the linker options?

With blessings.
Comment 7 Arnav Singh 2015-10-07 16:36:27 UTC
Sorry, I've been busy with other things and haven't had a chance to test.

Even if it does work, I'm not a fan of not using the default Release flags, because it affects not just glib but also any user applications that use G_D_C. The only such application *I* care about is HexChat, and there I've already removed the use of G_D_C (it was being used for automatic registration of resources, and I've switched it to use manual registration). But from the POV of glib it is undesirable to require all user apps to do this.

That's why I'm considering it a VS bug. Unfortunately, progress on the VS bug is also currently blocked at me, because I tried to make a smaller repro for the MS representative and they suggested things to try which worked for the repro but not for glib. So I have to make instructions for them to build glib from the gtk-win32 repo which I also haven't found the time for.
Comment 8 Fan, Chun-wei 2015-10-08 02:06:48 UTC
Hi Arnav,

The thing that I see with the GResource issue is that the linker dropped the symbol because that symbol was not directly called/referenced on the main code flow of the DLL or executable, which I think is expected behavior when we have /opt:ref.  I think this optimization has more to do with the executable or DLL size, rather than executable speed.  

There are a number of situations where one needs to do /opt:noref, such as when building libepoxy and so, as there are data/vtable items in there that needs to be found when the code runs yet is not in the main code flow, so I think that is why we have such a setting in the linker.

One thing that could be done besides manual registration (which means the GResource-generated code is called/referred in the main code flow) is to try to refer to that GTesource item via a dummy call, if /opt:ref is to be insisted upon.

Hope this clears things up a bit.

With blessings.
Comment 9 Arnav Singh 2015-10-08 03:27:52 UTC
You're not telling me anything I didn't already know. See comment 2. In particular, note that VS2013 did not elid the function despite also using /opt:ref, which again is why I'm considering it a VS 2015 bug.

It may well be that the compiler team won't consider it a bug since it's a desirable optimization in the general case, and they may not want to consider a reference via #pragma section sufficient to prevent a function from being elided. In that case as I said, glib will have to disable it in its own project files, and also note somewhere that all user applications that use MSVC, glib and G_D_C will have to disable it as well.
Comment 10 Arnav Singh 2015-10-08 03:28:50 UTC
(See comment 1, not comment 2.)
Comment 11 Arnav Singh 2015-10-08 22:47:45 UTC
We were able to test it today. Either of these two options work:

- https://github.com/hexchat/gtk-win32/commit/9abfe9b - using DllMain instead of G_D_C for gobject_init_ctor

- https://github.com/hexchat/gtk-win32/commit/ff3cf79 - disabling OptimizeReferences, as you suggested.

With either approach it is also safe to re-enable WholeProgramOptimization. I haven't tested the second approach with VS 2013 and lower so it may not work there, but since it seems you're in favor of the first option it should be fine for all VS versions that you want to support.
Comment 12 Ignacio Casal Quinteiro (nacho) 2015-10-09 11:12:16 UTC
I would definitely go for the first option since anyway it is what we do with the other libraries. The patch needs some work. I'll take it as an starting point and try to provide a patch.
Comment 13 Ignacio Casal Quinteiro (nacho) 2015-10-09 11:26:24 UTC
Created attachment 312945 [details] [review]
gobject: use a DllMain to initialize gobject on windows

It seems that VS 2015 optimizes out the constructor on windows,
so it is better to use a DllMain to initialize the library
and keep using a normal constructor on the other platforms.
This research was done by  Arnav Singh.
Comment 14 Fan, Chun-wei 2015-10-10 05:20:35 UTC
Review of attachment 312945 [details] [review]:

Hi Nacho,

Thanks for giving me the say for this...

Please see the following--besides these I think this is good to go.

With blessings, thank you!

::: gobject/gtype.c
@@ +4462,3 @@
+                     LPVOID    lpvReserved);
+
+HMODULE gobject_dll;

I don't think we need this here as we aren't using the HMODULE here...

@@ -4467,0 +4458,17 @@
+#if defined (G_OS_WIN32)
+
+BOOL WINAPI DllMain (HINSTANCE hinstDLL,
... 14 more ...

Same here, as a result.
Comment 15 Fan, Chun-wei 2015-10-10 05:27:51 UTC
Hi,

By the way, I think it is a better idea that we use the DllMain() over using constructors for initializing DLLs anyways for all cases, as we get assured that the needed items are called first when the DLL is loaded.

It is another story for static libs, but since we don't support static Windows builds for GLib (due to threading), I think we don't need to worry about it here, at least for now, in GLib.

With blessings, thank you!
Comment 16 Arnav Singh 2015-10-10 05:32:57 UTC
Do you also want to point out anywhere in glib's documentation that G_D_C will be broken for user applications with VS 2015 by default (so they should either disable OptimizeReferences or not use G_D_C at all) ?

Also nacho's patch doesn't include the second change in my commit, which is to re-enable WholeProgramOptimization in gobject.vcxproj.
Comment 17 Fan, Chun-wei 2015-10-10 05:43:43 UTC
Hi Nacho,

---
@@ -4467,0 +4458,17 @@
+#if defined (G_OS_WIN32)
+
+BOOL WINAPI DllMain (HINSTANCE hinstDLL,
... 14 more ...
---

Somehow I didn't get the right area selected for this.  I was pointing to the part where we did gobject_DLL = hinstDLL;, where this is the line I don't think we need.  Sorry for any misunderstanding caused.

---

Hi Arnav,

(In reply to Arnav Singh from 
 #16)
> Do you also want to point out anywhere in glib's documentation that G_D_C
> will be broken for user applications with VS 2015 by default (so they should
> either disable OptimizeReferences or not use G_D_C at all) ?

I think this is a good idea.  That is, to tell people that they should not use G_D_C for initializing DLLs but use DllMain(), and to use /opt:noref when using it in GResources without --manual-register.

> 
> Also nacho's patch doesn't include the second change in my commit, which is
> to re-enable WholeProgramOptimization in gobject.vcxproj.

I can do that later, no worries.  Thanks for the reminder to check that...
---
With blessings, thank you!
Comment 18 Ignacio Casal Quinteiro (nacho) 2015-10-10 11:29:52 UTC
Created attachment 313014 [details] [review]
gobject: use a DllMain to initialize gobject on windows

It seems that VS 2015 optimizes out the constructor on windows,
so it is better to use a DllMain to initialize the library
and keep using a normal constructor on the other platforms.
This research was done by  Arnav Singh.
Comment 19 Ignacio Casal Quinteiro (nacho) 2015-10-10 11:30:53 UTC
Hi Fan, attached you can find the new patch with the modifications you proposed and also the missing include. Can you give it a try before I push it?
About the modifications to the project that the field from Fan :)
Comment 20 Fan, Chun-wei 2015-10-10 21:58:03 UTC
Review of attachment 313014 [details] [review]:

Hi Nacho,

I think this is good to go.  Just add a prototype for DllMain() just before it so that MinGW does not complain.

p.s. Since we need to update the docs, please don't close this bug yet after committing the patch.

With blessings, thank you!
Comment 21 Fan, Chun-wei 2015-10-11 00:23:47 UTC
Review of attachment 313014 [details] [review]:

Hi Nacho,

One more thing though, for the windows.h include, let's keep  all things lower case.

With blessings, thank you!
Comment 22 Ignacio Casal Quinteiro (nacho) 2015-10-11 08:30:18 UTC
Comment on attachment 313014 [details] [review]
gobject: use a DllMain to initialize gobject on windows

Attachment 313014 [details] pushed as 7a29771 - gobject: use a DllMain to initialize gobject on windows
Comment 23 Ignacio Casal Quinteiro (nacho) 2015-10-11 08:31:39 UTC
Hi Fan,

pushed the patch already. Fixed the lowercase include. Also about the prototype it was already there.

Cheers.
Comment 24 Alexander Larsson 2015-10-11 21:38:26 UTC
This is pretty bad, as it makes automatic use of GResources on the windows platform not work, unless every module does some manual work to use DllMain instead.

Reading https://social.msdn.microsoft.com/Forums/vstudio/en-US/2aa2e1b7-6677-4986-99cc-62f463c94ef3/linkexe-bug-optnoref-option-doesnt-work?forum=vclanguage it seems that it may be possible to make it work.

If we make resource header contain:

#pragma comment(linker, "/include:resource_constructor")

And then make sure its included from some object file that has an exported function.
Comment 25 Fan, Chun-wei 2015-10-12 06:54:08 UTC
Hi Alex,

(In reply to Alexander Larsson from comment #24)
> This is pretty bad, as it makes automatic use of GResources on the windows
> platform not work, unless every module does some manual work to use DllMain
> instead.

Not really, for the case in Nacho's patch-the issue here is about initializing the library using constructors, not about using GResources.  We are already using DllMain() in many of our libraries that support Windows, including GLib, GIO, GTK+, Clutter, GDK-Pixbuf, ATK (the former six for quite some time already) and libsoup, to initialize these libraries.  This patch here does not try to deal with GResources usage in any way, code-wise (although in the case of the GObject DLL, we use things from gconstructor.h), and I don't think we want to deal with GResources code-wise, but (MSVC-)project-wise.

The issue about GResources in this case here is not really new, it is there since at least Visual Studio 2008, due to how linker optimization works here, so the existing MSVC projects for the GTK+ stack should have dealt with these already, when applicable.

> 
> #pragma comment(linker, "/include:resource_constructor")
> 

This is going to be project-wise, as mentioned-the main thing is that one needs ensure that the needed item is in the DLL or executable, so that the program can find the needed item, hence /opt:noref in the previous comments...

Hope this clears it up a bit.

With blessings.
Comment 26 Alexander Larsson 2015-10-12 12:06:53 UTC
I'm not talking abut the modules we maintain (glib, gtk+, etc) where we've done the work to make it use DllMain for construction. I'm talking about all external modules that use gresources and use the gconstructor.h method of registering them. These will be broken on windows without per-module work by win32 porters.

I'm also interested in this because I want to use constructors to solve some issues with GType registration, where now g_type_from_name() fail if the gtype has not been used yet. This is a much more critical scenario, and it would be nice if we could rely on constructors for this.

> This is going to be project-wise, as mentioned-the main thing is that one 
> needs ensure that the needed item is in the DLL or executable, so that the 
> program can find the needed item, hence /opt:noref in the previous comments...

I think all you need to do is ensure this is in a header that is included from a compilation unit that has an exported function in it. Should not be too hard to ensure this in your modules.
Comment 27 Fan, Chun-wei 2015-10-12 13:41:20 UTC
Hi Alex,

(In reply to Alexander Larsson from comment #26)
> I'm talking about all
> external modules that use gresources and use the gconstructor.h method ...

I think this is where one needs to rely on /opt:noref or the pragma directive... if the DllMain() thing is not done, but I would use the DllMain() if it already exists.

> 
> I'm also interested in this because I want to use constructors to solve some
> issues with GType registration, where now g_type_from_name() fail if the
> gtype has not been used yet. This is a much more critical scenario, and it
> would be nice if we could rely on constructors for this.

Please let me know the parts this will be done, so I can test this as well, and see what is the best thing we can do here.

> I think all you need to do is ensure this is in a header that is included
> from a compilation unit that has an exported function in it. Should not be
> too hard to ensure this in your modules.

I was meaning the linker settings in the MSVC project settings, but doing it in your suggested way will also most probably do.

With blessings, thank you.
Comment 28 Fan, Chun-wei 2015-10-12 15:48:30 UTC
Hi Alex,

(In reply to Alexander Larsson from comment #26)
> 
> I'm also interested in this because I want to use constructors to solve some
> issues with GType registration, where now g_type_from_name() fail if the
> gtype has not been used yet. This is a much more critical scenario, and it
> would be nice if we could rely on constructors for this.

By the way, the other problem is that the constructors are compiler-specific, so it is possible that we can't tell which order the constructors are called if we have multiple constructors in a library/executable (and it is the case in Visual Studio).  This is also part of the reasons behind using a DllMain() over using C constructors (at least for Visual Studio builds) on Windows, as we are assured that the DllMain() gets called first, plus we don't have to worry about the linker optimizing items out.

There is a bug in liborc that has something do to with this as well.[1]

My *gut-guess* is, we may (or may not) be able to expand the macro to define a DllMain() instead of a constructor for Windows, but that would mean we need to:
-consolidate the things that we need multiple constructors in one function and 
 use it
-On Windows, only use this where there is no existing DllMain(), otherwise
 do the init thing in the existing DllMain().

[1]: https://bugzilla.gnome.org/show_bug.cgi?id=754027

My take at this, with blessings.
Comment 29 Alexander Larsson 2015-10-12 17:40:03 UTC
Here is my idea for using constructors to solve the GType early registration issue: bug #756451
Comment 30 Alexander Larsson 2015-10-12 17:44:26 UTC
Oh, there is *no* guaranteed order of constructor calls in generals, which make them very hard to use properly. I know that, and we should not in general try to make this more widely used by app authors. It would be nice to be able to use it internally though, such as in resources and the gtype thing (which both are extremely careful to handle the ordering issue).

For the gtype thing it is really hard to consolidate all the calls, as they happen in all the G_DECLARE_TYPE macros all over your source code.

Or maybe we can do something similar to the current pointer array in special section, only use a custom glib section which we enumerate in a dllmain function, as that way we *will* have a reference to the symbols from our dll.
Comment 31 Nirbheek Chauhan 2015-10-12 23:08:08 UTC
Is there a way around using DllMain for initialization? DllMain is never called if you compile glib statically, and in fact it shouldn't even be a defined symbol in that case since it will give a symbol collision with other libraries that might define it (often incorrectly).

In liborc, I'm pushing for us to do all initialization as part of the init function (bug 754027) which needs to be called before orc can be used anyway.
Comment 32 Nirbheek Chauhan 2015-10-12 23:10:53 UTC
(In reply to Fan, Chun-wei from comment #15)
> By the way, I think it is a better idea that we use the DllMain() over using
> constructors for initializing DLLs anyways for all cases, as we get assured
> that the needed items are called first when the DLL is loaded.
> 
> It is another story for static libs, but since we don't support static
> Windows builds for GLib (due to threading), I think we don't need to worry
> about it here, at least for now, in GLib.
> 

As far as I know, there is no problem with using GLib statically as long as you ensure that you do not link to another copy of GLib (dynamically or otherwise). I have used it in the past, and I know of people using it right now for a fully-static glib/gstreamer-using application.
Comment 33 Fan, Chun-wei 2015-10-13 10:46:05 UTC
Hi Nirbheek,

(In reply to Nirbheek Chauhan from comment #32)
> As far as I know, there is no problem with using GLib statically as long as
> you ensure that you do not link to another copy of GLib (dynamically or
> otherwise). I have used it in the past, and I know of people using it right
> now for a fully-static glib/gstreamer-using application.

Can I know what GLib version was used statically?  In October 2011, the threading support for GLib was re-written and it was decided at that time that we won't support static GLib builds as a result.  Were GLib threads used in your static application?

---

Hi Arnav (and Alex),

I think the main issue, after some further investigation, is the following:

Visual Studio 2015 changed its default LTCG setting from plain /LTCG (which was the default in Visual Studio 2013 and earlier) to /LTCG:incremental, which would cause issues in our use case (meaning that the constructor items would be optimized out as a result).  I think the best thing to do would be to update the projects to explicitly specify the LTCG setting to be /LTCG for all (release-build) cases, which I will do pretty soon.  I will also mention in bug 756451 regarding this.

This means, in Visual Studio release builds, we need to ensure that we use /opt:noref while making sure that /LTCG, not /LTCG:incremental, was used, in the linker optimization settings.

For init'ing the library itself (*besides* the things mentioned in bug 745451), I am still all for using DllMain() over constructors though.

With blessings.
Comment 34 Dan Winship 2015-10-13 12:25:22 UTC
https://msdn.microsoft.com/en-us/library/7f0aews7.aspx claims that:

  #pragma comment(linker, "/include:__mySymbol")

will force "mySymbol" to be linked in even if it's unreferenced
Comment 35 Alexander Larsson 2015-10-13 13:15:02 UTC
Dan: only if the pragma is in a compilation unit that has a symbol that is used/exported, I believe.
Comment 36 Nirbheek Chauhan 2015-10-17 01:47:58 UTC
(In reply to Fan, Chun-wei from comment #33)
> (In reply to Nirbheek Chauhan from comment #32)
> > As far as I know, there is no problem with using GLib statically as long as
> > you ensure that you do not link to another copy of GLib (dynamically or
> > otherwise). I have used it in the past, and I know of people using it right
> > now for a fully-static glib/gstreamer-using application.
> 
> Can I know what GLib version was used statically?  In October 2011, the
> threading support for GLib was re-written and it was decided at that time
> that we won't support static GLib builds as a result.  Were GLib threads
> used in your static application?
> 

GLib 2.40.2 (released in 2014), and threading was definitely used since the application uses GStreamer which makes heavy use of threads. As far as I know, it's been working fine. Most of my work/conversation regarding making this work is at: https://bugzilla.gnome.org/show_bug.cgi?id=698118#c7

My patch is actually incomplete since it doesn't call g_thread_win32_thread_detach() appropriately, but that can be fixed as is detailed in that bug.
Comment 37 Alexander Larsson 2015-10-27 15:05:17 UTC
So, i just build gtk3 with visual studio 2015 and it seems that gtk3-demo is broken for this exact reason (it can't find its resources). We really need a better fix for this.
Comment 38 Fan, Chun-wei 2015-10-27 15:34:09 UTC
Hi Alex,

Does your linker optimization settings use /LTCG rather than /LTCG:incremental under the entry "Link time code generation"?  If not, can you re-link the demos (gtk3-demo, gtk3-demo-application and gtk3-icon-browser) using /LTCG?

The patch for the projects to use that option was only pushed a few days ago into gtk-3-18 and master and there was no release for those branches yet.

If /LTCG:incremental is supposed to generate the same final binary as /LTCG, this would count as a Visual Studio bug.

With blessings, thank you
Comment 39 Alexander Larsson 2015-10-28 14:09:30 UTC
I built latest git master with VS2015 which has the fixes, and it works. I still think we should try to fix the issue in a better way rather than tweaking the optimization flags in every project using gtk.
Comment 40 Fan, Chun-wei 2015-10-28 14:26:55 UTC
Hi Alex,

(In reply to Alexander Larsson from comment #39)
> I still think we should try to fix the issue in a better way

Agreed.  A compromise such as using --manual-register comes to mind (which, Arnav probably mentioned), but probably we need to dig deeper as the main issue is that the linker is dropping any code that is not referred to by the main code flow...

With blessings, thank you!
Comment 41 Alexander Larsson 2015-10-28 15:37:02 UTC
One issue with --manual-register is that it is hard to know where to call it if you're e.g. a library.

Another workaround would be if the generated header just had some define that we could reference *anywhere* in your code, such that we get a reference to the constructor and avoid dropping it. That way you don't have to find a place to call it before any of your code runs.
Comment 42 Arnav Singh 2015-10-28 15:50:45 UTC
If you'll check the workarounds section in the VS bug, I'd managed to trick the compiler into including it by adding a reference in unreachable code as part of the G_D_C expansion itself (though surprisingly it only worked with optimizations and broke when optimizations were disabled.) But maybe it'll give you some ideas.
Comment 43 Alexander Larsson 2015-11-06 12:59:39 UTC
Created attachment 314986 [details] [review]
gconstructor: Work around constructors being optimized away on VS2015

Whole program optimization is enabled by default in visual studio
2015, and this causes constructors (for e.g. resources) to be
optimized away as they are not referenced from elsewhere.

This works around this by some pragma magic.
Comment 44 Alexander Larsson 2015-11-06 13:03:46 UTC
The patch above is based on some experiments i did in the gtk tree on vs2015. It seems to work in both debug and release modes (with the whole-program-optimize change reverted). I didn't do a full build with this glib patch applied and all the resource files re-generated though, as I'm having some issue with that.

Could some of the more experienced win32 guys test this?

Also, what is the general opinion on dropping support for pre-VS2008, so that we can rely in __pragma() and drop the ugly #pragma stuff in the constructor code. Does anyone run VS2005 anymore?
Comment 45 Fan, Chun-wei 2015-11-06 13:51:53 UTC
Hi Alex,

(In reply to Alexander Larsson from comment #44)
> 
> Could some of the more experienced win32 guys test this?

I can look at this in the next few days or so... We could be able to use /opt:ref at the end for release builds.

Arnav, can you try this out as well?

> Also, what is the general opinion on dropping support for pre-VS2008, so
> that we can rely in __pragma() and drop the ugly #pragma stuff in the
> constructor code. Does anyone run VS2005 anymore?

I am personally ok, as I have VS2008 and later.  But I think it's better to add John Emmas here to this discussion.

With blessings, thank you
Comment 46 Nirbheek Chauhan 2015-11-06 14:37:30 UTC
(In reply to Alexander Larsson from comment #44)
> Also, what is the general opinion on dropping support for pre-VS2008, so
> that we can rely in __pragma() and drop the ugly #pragma stuff in the
> constructor code. Does anyone run VS2005 anymore?

I have worked with some companies that use Glib and have large codebases that still use VS2003. However, I have a feeling that we can just drop support for pre-VS2008 if we want to and force these companies to upgrade and continue using older Glib versions while they make the transition.
Comment 47 John E 2015-11-06 17:59:01 UTC
It might help if I explain why developers must sometimes stick with a specific version of MSVC. It rarely has anything to do with the compiler, in my experience.

My apps get built using VS2005 (which uses Windows CRT 8.0). My apps get distributed using an installer called InstallShield. And InstallShield has a very nice feature of being able to install (i.e. bundle) a specific CRT. But in my case, the latest CRT it knows about is CRT 8.0. I could upgrade InstallShield - but InstallShield is horrendously expensive (and none of the cheaper installers support this bundling feature AFAIK).

So why is the bundling feature useful? Mostly because it guarantees that our customers will run with the same CRT that we use for development. And because of this, we can almost always reproduce bugs reported by a customer. So when a development team chooses to stay with an older compiler, it isn't because they're all stick-in-the-muds. There can be tangible benefits for stability (especially given the plethora of different Windows OS's in use).

Of course, none of this is glib's responsibility (i.e. we can't expect to keep blocking progress if glib needs to move on) but it seems this is simply being done to remove some "ugly" #pragma stuff. If a compromise was possible, that would definitely be appreciated. And in the meantime I suppose I'll need to start looking for an alternative installer!!
Comment 48 Alexander Larsson 2015-11-06 21:02:12 UTC
The pragma thing isn't just about it being "ugly". It we didn't have to support that we could make the constructor stuff a regular macro in gmacros.h that was " fully supported" rather than being this internal header that gets copied into the output of the resource compiler.

On the other hand, maybe we *don't* want people to start using constructors in larger numbers, seeing as they are very tricky to use right due to undefined ordering and running really early.
Comment 49 Fan, Chun-wei 2015-11-10 09:35:00 UTC
Created attachment 315176 [details] [review]
gconstructor: Work around constructors being optimized away on MSVC

Hello Alex,

(In reply to Alexander Larsson from comment #44)
> The patch above is based on some experiments i did in the gtk tree on
> vs2015. It seems to work in both debug and release modes (with the
> whole-program-optimize change reverted). I didn't do a full build with this
> glib patch applied and all the resource files re-generated though, as I'm
> having some issue with that.
> 
> Could some of the more experienced win32 guys test this?

I have tested your patch, but it needed some updates as the symbol mangling is different between x86 and x64 builds (otherwise the x64 builds would get linker errors for the __pragma(linker, "/include:...) directive).  so here is the updated patch.

This issue really hits release builds, not debug, as optimizations are disabled in debug builds.  By the way, this patch will also allow one to use /opt:ref even on older Visual Studio as well, so I have updated the commit comments a bit to reflect that.

Through testing, using the GTK+ demos as well as the gio/resources test program, one is able to run them successfully with the resources found in the optimized builds with the default optimization settings.

With blessings, thank you!
Comment 50 Alexander Larsson 2015-11-11 07:31:21 UTC
Review of attachment 315176 [details] [review]:

This looks good to me, lets get it in.
Comment 51 Fan, Chun-wei 2015-11-12 07:14:02 UTC
Hi Alex,

Thanks for the review, I pushed the patch modified a bit so that it is more easily maintainable, as db4df99.  Sorry, I didn't manage to change the author name to yours-the credit should certainly belong to you.  Sorry about that.

---
Hi Arnav,

Can you try the build again with the default optimization settings and see whether all goes well with you?  Please let us know, so that we can close this bug.
---

With blessings, thank you!
Comment 52 Arnav Singh 2015-11-12 08:09:14 UTC
Since you've changed glib to use DllMain, and I've changed HexChat to use manual resource registration (which I prefer anyway), I don't have any code left that uses G_D_C. If you're satisfied with your testing then feel free to close this bug.
Comment 53 Fan, Chun-wei 2015-11-12 08:40:00 UTC
Hi Arnav,

Thanks though.  Let's close this bug.

With blessings.
Comment 54 Fan, Chun-wei 2016-05-16 14:28:08 UTC
*** Bug 766388 has been marked as a duplicate of this bug. ***
Comment 55 Xavier Claessens 2018-03-19 21:17:42 UTC
(In reply to Fan, Chun-wei from comment #15)
> It is another story for static libs, but since we don't support static
> Windows builds for GLib (due to threading), I think we don't need to worry
> about it here, at least for now, in GLib.

Static build is indeed broken since then because of the name collision dllmain. maybe VS got fixed since 2015 and we can revert the patch?

Also do you remember what's the threading issue you were talking about? Maybe fixed too?