Merge branch 'windows-static-build-core' into 'main'

Enable full-static build on Windows

Closes #692

See merge request GNOME/glib!2438
This commit is contained in:
Philip Withnall 2022-01-26 11:38:44 +00:00
commit 5ca038cf57
13 changed files with 279 additions and 42 deletions

View File

@ -332,7 +332,9 @@ vs2017-x64:
- win32-ps
needs: []
script:
- .gitlab-ci/test-msvc.bat
# FIXME: These should use --wrap-mode=nodownload but the Windows CI machines
# arent currently set up for that.
- .gitlab-ci/test-msvc.bat ${MESON_COMMON_OPTIONS} --wrap-mode=default
artifacts:
reports:
junit: "_build/${env:CI_JOB_NAME}-report.xml"
@ -347,6 +349,25 @@ vs2017-x64:
- _build/gthread/libgthread-2.0-0.dll
- _build/gobject/libgobject-2.0-0.dll
vs2017-x64-static:
extends: .only-default
stage: build
tags:
- win32-ps
needs: []
script:
# FIXME: These should use --wrap-mode=nodownload but the Windows CI machines
# arent currently set up for that.
- .gitlab-ci/test-msvc.bat ${MESON_COMMON_OPTIONS} --wrap-mode=default --default-library=static
artifacts:
reports:
junit: "_build/${env:CI_JOB_NAME}-report.xml"
name: "glib-${env:CI_JOB_NAME}-${env:CI_COMMIT_REF_NAME}"
when: always
paths:
- _build/meson-logs
- "_build/${env:CI_JOB_NAME}-report.xml"
freebsd-12-x86_64:
stage: build
only:

View File

@ -2,11 +2,18 @@
:: vcvarsall.bat sets various env vars like PATH, INCLUDE, LIB, LIBPATH for the
:: specified build architecture
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64
@echo on
:: Remove quotes from script args
setlocal enabledelayedexpansion
set args=
for %%x in (%*) do (
set args=!args! %%~x
)
set args=%args:~1%
:: FIXME: make warnings fatal
pip3 install --upgrade --user meson==0.52.0 || goto :error
meson _build || goto :error
meson %args% _build || goto :error
ninja -C _build || goto :error
:: FIXME: dont ignore test errors

View File

@ -68,6 +68,10 @@
#include <AvailabilityMacros.h>
#endif
#define __GLIB_H_INSIDE__
#include "gconstructor.h"
#undef __GLIB_H_INSIDE__
/**
* SECTION:giomodule
* @short_description: Loadable GIO Modules
@ -1103,7 +1107,7 @@ extern GType _g_win32_network_monitor_get_type (void);
static HMODULE gio_dll = NULL;
#ifdef DLL_EXPORT
#ifndef GLIB_STATIC_COMPILATION
BOOL WINAPI DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
@ -1123,8 +1127,40 @@ DllMain (HINSTANCE hinstDLL,
return TRUE;
}
#elif defined(G_HAS_CONSTRUCTORS) /* && G_PLATFORM_WIN32 && GLIB_STATIC_COMPILATION */
extern void glib_win32_init (void);
extern void gobject_win32_init (void);
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(giomodule_init_ctor)
#endif
G_DEFINE_CONSTRUCTOR (giomodule_init_ctor)
static void
giomodule_init_ctor (void)
{
/* When built dynamically, module initialization is done through DllMain
* function which is called when the dynamic library is loaded by the glib
* module AFTER loading gobject. So, in dynamic configuration glib and
* gobject are always initialized BEFORE gio.
*
* When built statically, initialization mechanism relies on hooking
* functions to the CRT section directly at compilation time. As we don't
* control how each compilation unit will be built and in which order, we
* obtain the same kind of issue as the "static initialization order fiasco".
* In this case, we must ensure explicitly that glib and gobject are always
* well initialized BEFORE gio.
*/
glib_win32_init ();
gobject_win32_init ();
gio_win32_appinfo_init (FALSE);
}
#else /* G_PLATFORM_WIN32 && GLIB_STATIC_COMPILATION && !G_HAS_CONSTRUCTORS */
#error Your platform/compiler is missing constructor support
#endif /* GLIB_STATIC_COMPILATION */
void *
_g_io_win32_get_module (void)
{
@ -1136,7 +1172,7 @@ _g_io_win32_get_module (void)
return gio_dll;
}
#endif
#endif /* G_PLATFORM_WIN32 */
void
_g_io_modules_ensure_extension_points_registered (void)

View File

@ -3,11 +3,15 @@
/* This is the same check that's done in configure to create config.h */
#ifdef _WIN32
#ifdef GLIB_STATIC_COMPILATION
#define GLIB_TEST_EXPORT_SYMBOL extern
#else
#ifdef _MSC_VER
#define GLIB_TEST_EXPORT_SYMBOL __declspec(dllexport) extern
#else
#define GLIB_TEST_EXPORT_SYMBOL __attribute__ ((visibility ("default"))) __declspec(dllexport) extern
#endif
#endif
/* Matches GCC and Clang */
#elif defined(__GNUC__) && (__GNUC__ >= 4)
# define GLIB_TEST_EXPORT_SYMBOL __attribute__((visibility("default"))) extern

View File

@ -1,3 +1,30 @@
/* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __G_CONSTRUCTOR_H__
#define __G_CONSTRUCTOR_H__
/*
If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and
destructors, in a usable way, including e.g. on library unload. If not you're on
@ -28,6 +55,7 @@
#elif defined (_MSC_VER) && (_MSC_VER >= 1500)
/* Visual studio 2008 and later has _Pragma */
#include "gslist.h"
#include <stdlib.h>
#define G_HAS_CONSTRUCTORS 1
@ -120,3 +148,4 @@
#endif
#endif /* __GTK_DOC_IGNORE__ */
#endif /* __G_CONSTRUCTOR_H__ */

View File

@ -340,14 +340,48 @@ glib_init (void)
g_error_init ();
}
#if defined (G_OS_WIN32)
#ifdef G_PLATFORM_WIN32
HMODULE glib_dll = NULL;
void glib_win32_init (void);
void
glib_win32_init (void)
{
/* May be called more than once in static compilation mode */
static gboolean win32_already_init = FALSE;
if (!win32_already_init)
{
win32_already_init = TRUE;
g_crash_handler_win32_init ();
#ifdef THREADS_WIN32
g_thread_win32_init ();
#endif
g_clock_win32_init ();
glib_init ();
/* must go after glib_init */
g_console_win32_init ();
}
}
static void
glib_win32_deinit (gboolean detach_thread)
{
#ifdef THREADS_WIN32
if (detach_thread)
g_thread_win32_process_detach ();
#endif
g_crash_handler_win32_deinit ();
}
#ifndef GLIB_STATIC_COMPILATION
BOOL WINAPI DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved);
HMODULE glib_dll;
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
@ -357,14 +391,7 @@ DllMain (HINSTANCE hinstDLL,
{
case DLL_PROCESS_ATTACH:
glib_dll = hinstDLL;
g_crash_handler_win32_init ();
g_clock_win32_init ();
#ifdef THREADS_WIN32
g_thread_win32_init ();
#endif
glib_init ();
/* must go after glib_init */
g_console_win32_init ();
glib_win32_init ();
break;
case DLL_THREAD_DETACH:
@ -374,11 +401,7 @@ DllMain (HINSTANCE hinstDLL,
break;
case DLL_PROCESS_DETACH:
#ifdef THREADS_WIN32
if (lpvReserved == NULL)
g_thread_win32_process_detach ();
#endif
g_crash_handler_win32_deinit ();
glib_win32_deinit (lpvReserved == NULL);
break;
default:
@ -389,7 +412,35 @@ DllMain (HINSTANCE hinstDLL,
return TRUE;
}
#elif defined (G_HAS_CONSTRUCTORS)
#elif defined(G_HAS_CONSTRUCTORS) /* && G_PLATFORM_WIN32 && GLIB_STATIC_COMPILATION */
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(glib_init_ctor)
#endif
#ifdef G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA
#pragma G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(glib_init_dtor)
#endif
G_DEFINE_CONSTRUCTOR (glib_init_ctor)
static void
glib_init_ctor (void)
{
glib_win32_init ();
}
G_DEFINE_DESTRUCTOR (glib_init_dtor)
static void
glib_init_dtor (void)
{
glib_win32_deinit (FALSE);
}
#else /* G_PLATFORM_WIN32 && GLIB_STATIC_COMPILATION && !G_HAS_CONSTRUCTORS */
#error Your platform/compiler is missing constructor support
#endif /* GLIB_STATIC_COMPILATION */
#elif defined(G_HAS_CONSTRUCTORS) /* && !G_PLATFORM_WIN32 */
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(glib_init_ctor)
@ -402,6 +453,6 @@ glib_init_ctor (void)
glib_init ();
}
#else
#else /* !G_PLATFORM_WIN32 && !G_HAS_CONSTRUCTORS */
# error Your platform/compiler is missing constructor support
#endif
#endif /* G_PLATFORM_WIN32 */

View File

@ -20,6 +20,8 @@
#mesondefine GLIB_STATIC_COMPILATION
#mesondefine GOBJECT_STATIC_COMPILATION
#mesondefine G_INTL_STATIC_COMPILATION
#mesondefine FFI_STATIC_BUILD
G_BEGIN_DECLS

View File

@ -422,6 +422,28 @@ g_system_thread_free (GRealThread *thread)
void
g_system_thread_exit (void)
{
/* In static compilation, DllMain doesn't exist and so DLL_THREAD_DETACH
* case is never called and thread destroy notifications are not triggered.
* To ensure that notifications are correctly triggered in static
* compilation mode, we call directly the "detach" function here right
* before terminating the thread.
* As all win32 threads initialized through the glib API are run through
* the same proxy function g_thread_win32_proxy() which calls systematically
* g_system_thread_exit() when finishing, we obtain the same behavior as
* with dynamic compilation.
*
* WARNING: unfortunately this mechanism cannot work with threads created
* directly from the Windows API using CreateThread() or _beginthread/ex().
* It only works with threads created by using the glib API with
* g_system_thread_new(). If users need absolutely to use a thread NOT
* created with glib API under Windows and in static compilation mode, they
* should not use glib functions within their thread or they may encounter
* memory leaks when the thread finishes.
*/
#ifdef GLIB_STATIC_COMPILATION
g_thread_win32_thread_detach ();
#endif
_endthreadex (0);
}
@ -610,7 +632,7 @@ SetThreadName (DWORD dwThreadID,
typedef HRESULT (WINAPI *pSetThreadDescription) (HANDLE hThread,
PCWSTR lpThreadDescription);
static pSetThreadDescription SetThreadDescriptionFunc = NULL;
HMODULE kernel32_module = NULL;
static HMODULE kernel32_module = NULL;
static gboolean
g_thread_win32_load_library (void)

View File

@ -146,6 +146,14 @@ test_private3 (void)
thread = (HANDLE) _beginthreadex (NULL, 0, private3_func, NULL, 0, &ignore);
WaitForSingleObject (thread, INFINITE);
CloseHandle (thread);
/* FIXME: with static compilation on Windows this test will fail because
* it is mixing up glib threads with Microsoft native thread API. See
* comment in gthread-win32.c for g_system_thread_exit() implementation.
* Fix is not straightforward, possible solution could be to use FLS
* functions (instead of TLS) as proposed in
* https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1655
*/
}
#else
{

View File

@ -4521,7 +4521,23 @@ gobject_init (void)
_g_signal_init ();
}
#if defined (G_OS_WIN32)
#ifdef G_PLATFORM_WIN32
void gobject_win32_init (void);
void
gobject_win32_init (void)
{
/* May be called more than once in static compilation mode */
static gboolean win32_already_init = FALSE;
if (!win32_already_init)
{
win32_already_init = TRUE;
gobject_init ();
}
}
#ifndef GLIB_STATIC_COMPILATION
BOOL WINAPI DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
@ -4535,7 +4551,7 @@ DllMain (HINSTANCE hinstDLL,
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
gobject_init ();
gobject_win32_init ();
break;
default:
@ -4546,10 +4562,44 @@ DllMain (HINSTANCE hinstDLL,
return TRUE;
}
#elif defined (G_HAS_CONSTRUCTORS)
#elif defined(G_HAS_CONSTRUCTORS) /* && G_PLATFORM_WIN32 && GLIB_STATIC_COMPILATION */
extern void glib_win32_init (void);
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(gobject_init_ctor)
#endif
G_DEFINE_CONSTRUCTOR(gobject_init_ctor)
static void
gobject_init_ctor (void)
{
/* When built dynamically, module initialization is done through DllMain
* function which is called when the dynamic library is loaded by the glib
* module. So, in dynamic configuration glib is always initialized BEFORE
* gobject.
*
* When built statically, initialization mechanism relies on hooking
* functions to the CRT section directly at compilation time. As we don't
* control how each compilation unit will be built and in which order, we
* obtain the same kind of issue as the "static initialization order fiasco".
* In this case, we must ensure explicitly that glib is always well
* initialized BEFORE gobject.
*/
glib_win32_init ();
gobject_win32_init ();
}
#else /* G_PLATFORM_WIN32 && GLIB_STATIC_COMPILATION && !G_HAS_CONSTRUCTORS */
# error Your platform/compiler is missing constructor support
#endif /* GLIB_STATIC_COMPILATION */
#elif defined(G_HAS_CONSTRUCTORS) /* && !G_PLATFORM_WIN32 */
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(gobject_init_ctor)
#endif
G_DEFINE_CONSTRUCTOR (gobject_init_ctor)
static void
@ -4558,9 +4608,9 @@ gobject_init_ctor (void)
gobject_init ();
}
#else
#else /* !G_PLATFORM_WIN32 && !G_HAS_CONSTRUCTORS */
#error Your platform/compiler is missing constructor support
#endif
#endif /* G_PLATFORM_WIN32 */
/**
* g_type_class_add_private:

View File

@ -216,6 +216,8 @@ endif
if get_option('default_library') == 'static'
glibconfig_conf.set('GLIB_STATIC_COMPILATION', '1')
glibconfig_conf.set('GOBJECT_STATIC_COMPILATION', '1')
glibconfig_conf.set('G_INTL_STATIC_COMPILATION', '1')
glibconfig_conf.set('FFI_STATIC_BUILD', '1')
endif
# Cygwin glib port maintainers made it clear

View File

@ -1,10 +1,11 @@
[wrap-file]
directory = zlib-1.2.11
source_url = https://zlib.net/fossils/zlib-1.2.11.tar.gz
source_filename = zlib-1.2.11.tar.gz
source_hash = c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1
patch_filename = zlib_1.2.11-6_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/zlib_1.2.11-6/get_patch
patch_hash = f7c24c5698ce787294910ad431f94088102d35ddaf88542d04add1e54afa9212
patch_url = https://github.com/mesonbuild/zlib/releases/download/1.2.11-3/zlib.zip
patch_filename = zlib-1.2.11-3-wrap.zip
patch_hash = f07dc491ab3d05daf00632a0591e2ae61b470615b5b73bcf9b3f061fff65cff0
[provide]
zlib = zlib_dep

View File

@ -101,8 +101,12 @@ main (int argc,
if (!module_self)
g_error ("error: %s", g_module_error ());
/* On Windows static compilation mode, glib API symbols are not
* exported dynamically by definition. */
#if !defined(G_PLATFORM_WIN32) || !defined(GLIB_STATIC_COMPILATION)
if (!g_module_symbol (module_self, "g_module_close", (gpointer *) &f_self))
g_error ("error: %s", g_module_error ());
#endif
module_a = g_module_open_full (plugin_a, G_MODULE_BIND_LAZY, &error);
g_assert_no_error (error);