Merge branch 'libglib-static-dep-for-tests' into 'main'

Meson: Add libglib_static dependency for use in tests

See merge request GNOME/glib!4651
This commit is contained in:
Philip Withnall
2025-05-30 22:15:31 +00:00
8 changed files with 210 additions and 174 deletions

View File

@@ -458,48 +458,6 @@ glib_win32_deinit (gboolean detach_thread)
g_crash_handler_win32_deinit ();
}
#ifndef GLIB_STATIC_COMPILATION
BOOL WINAPI DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved);
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
glib_dll = hinstDLL;
glib_win32_init ();
break;
case DLL_THREAD_DETACH:
#ifdef THREADS_WIN32
g_thread_win32_thread_detach ();
#endif
break;
case DLL_PROCESS_DETACH:
glib_win32_deinit (lpvReserved == NULL);
break;
default:
/* do nothing */
;
}
return TRUE;
}
#else
#ifndef G_HAS_CONSTRUCTORS
#error static compilation on Windows requires constructor support
#endif
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(glib_priv_constructor)
#endif
@@ -518,7 +476,7 @@ glib_priv_constructor (void)
}
#ifndef G_HAS_TLS_CALLBACKS
#error static compilation on Windows requires TLS callbacks support
#error Compilation on Windows requires TLS callbacks support
#endif
G_DEFINE_TLS_CALLBACK (glib_priv_tls_callback)
@@ -548,8 +506,6 @@ glib_priv_tls_callback (LPVOID hinstance,
}
}
#endif /* GLIB_STATIC_COMPILATION */
#elif defined(G_HAS_CONSTRUCTORS) /* && !G_PLATFORM_WIN32 */
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA

View File

@@ -1,80 +0,0 @@
/* gwin32-private.c - private glib functions for gwin32.c
*
* Copyright 2019 Руслан Ижбулатов
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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/>.
*/
/* Copy @cmdline into @debugger, and substitute @pid for `%p`
* and @event for `%e`.
* If @debugger_size (in wchar_ts) is overflowed, return %FALSE.
* Also returns %FALSE when `%` is followed by anything other
* than `e` or `p`.
*/
static gboolean
_g_win32_subst_pid_and_event_w (wchar_t *local_debugger,
gsize debugger_size,
const wchar_t *cmdline,
DWORD pid,
guintptr event)
{
gsize i = 0, dbg_i = 0;
/* These are integers, and they can't be longer than 20 characters
* even when they are 64-bit and in decimal notation.
* Use 30 just to be sure.
*/
#define STR_BUFFER_SIZE 30
wchar_t pid_str[STR_BUFFER_SIZE] = {0};
gsize pid_str_len;
wchar_t event_str[STR_BUFFER_SIZE] = {0};
gsize event_str_len;
_snwprintf_s (pid_str, STR_BUFFER_SIZE, G_N_ELEMENTS (pid_str), L"%lu", pid);
pid_str[G_N_ELEMENTS (pid_str) - 1] = 0;
pid_str_len = wcslen (pid_str);
_snwprintf_s (event_str, STR_BUFFER_SIZE, G_N_ELEMENTS (pid_str), L"%Iu", event);
event_str[G_N_ELEMENTS (pid_str) - 1] = 0;
event_str_len = wcslen (event_str);
#undef STR_BUFFER_SIZE
while (cmdline[i] != 0 && dbg_i < debugger_size)
{
if (cmdline[i] != L'%')
local_debugger[dbg_i++] = cmdline[i++];
else if (cmdline[i + 1] == L'p')
{
gsize j = 0;
while (j < pid_str_len && dbg_i < debugger_size)
local_debugger[dbg_i++] = pid_str[j++];
i += 2;
}
else if (cmdline[i + 1] == L'e')
{
gsize j = 0;
while (j < event_str_len && dbg_i < debugger_size)
local_debugger[dbg_i++] = event_str[j++];
i += 2;
}
else
return FALSE;
}
if (dbg_i < debugger_size)
local_debugger[dbg_i] = 0;
else
return FALSE;
return TRUE;
}

View File

@@ -70,6 +70,8 @@
#endif
#include "glib.h"
#include "gwin32.h"
#include "gwin32private.h"
#include "gthreadprivate.h"
#include "glib-init.h"
@@ -1065,7 +1067,66 @@ static DWORD *exceptions_to_catch = NULL;
static HANDLE debugger_wakeup_event = 0;
static DWORD debugger_spawn_flags = 0;
#include "gwin32-private.c"
/* Copy @cmdline into @debugger, and substitute @pid for `%p`
* and @event for `%e`.
* If @debugger_size (in wchar_ts) is overflowed, return %FALSE.
* Also returns %FALSE when `%` is followed by anything other
* than `e` or `p`.
*/
bool
g_win32_substitute_pid_and_event (wchar_t *local_debugger,
gsize debugger_size,
const wchar_t *cmdline,
DWORD pid,
guintptr event)
{
gsize i = 0, dbg_i = 0;
/* These are integers, and they can't be longer than 20 characters
* even when they are 64-bit and in decimal notation.
* Use 30 just to be sure.
*/
#define STR_BUFFER_SIZE 30
wchar_t pid_str[STR_BUFFER_SIZE] = {0};
gsize pid_str_len;
wchar_t event_str[STR_BUFFER_SIZE] = {0};
gsize event_str_len;
_snwprintf_s (pid_str, STR_BUFFER_SIZE, G_N_ELEMENTS (pid_str), L"%lu", pid);
pid_str[G_N_ELEMENTS (pid_str) - 1] = 0;
pid_str_len = wcslen (pid_str);
_snwprintf_s (event_str, STR_BUFFER_SIZE, G_N_ELEMENTS (pid_str), L"%Iu", event);
event_str[G_N_ELEMENTS (pid_str) - 1] = 0;
event_str_len = wcslen (event_str);
#undef STR_BUFFER_SIZE
while (cmdline[i] != 0 && dbg_i < debugger_size)
{
if (cmdline[i] != L'%')
local_debugger[dbg_i++] = cmdline[i++];
else if (cmdline[i + 1] == L'p')
{
gsize j = 0;
while (j < pid_str_len && dbg_i < debugger_size)
local_debugger[dbg_i++] = pid_str[j++];
i += 2;
}
else if (cmdline[i + 1] == L'e')
{
gsize j = 0;
while (j < event_str_len && dbg_i < debugger_size)
local_debugger[dbg_i++] = event_str[j++];
i += 2;
}
else
return FALSE;
}
if (dbg_i < debugger_size)
local_debugger[dbg_i] = 0;
else
return FALSE;
return TRUE;
}
static char *
copy_chars (char *buffer,
@@ -1295,9 +1356,9 @@ g_crash_handler_win32_init (void)
debugger_wakeup_event = CreateEvent (&sa, FALSE, FALSE, NULL);
/* Put process ID and event handle into debugger commandline */
if (!_g_win32_subst_pid_and_event_w (debugger, G_N_ELEMENTS (debugger),
debugger_env, GetCurrentProcessId (),
(guintptr) debugger_wakeup_event))
if (!g_win32_substitute_pid_and_event (debugger, G_N_ELEMENTS (debugger),
debugger_env, GetCurrentProcessId (),
(guintptr) debugger_wakeup_event))
{
CloseHandle (debugger_wakeup_event);
debugger_wakeup_event = 0;

42
glib/gwin32private.h Normal file
View File

@@ -0,0 +1,42 @@
/*
* Copyright © 2025 Luca Bacci
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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/>.
*
* Author: Luca Bacci <luca.bacci@outlook.com>
*/
#ifndef __G_WIN32PRIVATE_H__
#define __G_WIN32PRIVATE_H__
#ifdef G_PLATFORM_WIN32
#include "config.h"
#include <windows.h>
#include <stdbool.h>
bool
g_win32_substitute_pid_and_event (wchar_t *local_debugger,
gsize debugger_size,
const wchar_t *cmdline,
DWORD pid,
guintptr event);
#endif /* G_PLATFORM_WIN32 */
#endif /* __G_WIN32PRIVATE_H__ */

View File

@@ -437,6 +437,26 @@ libglib_dep = declare_dependency(
# We sadly need to export configinc here because everyone includes <glib/*.h>
include_directories : [configinc, glibinc])
libglib_static_dep = declare_dependency(
compile_args: ['-DGLIB_STATIC_COMPILATION'],
objects: libglib.extract_all_objects(recursive: true),
dependencies: [
atomic_dep,
gnulib_libm_dependency,
libiconv,
libintl_deps,
libm,
librt,
libsysprof_capture_dep,
pcre2,
platform_deps,
thread_dep,
],
link_with: [charset_lib, gnulib_lib],
sources: glib_built_headers,
include_directories: [configinc, glibinc],
)
pkg.generate(libglib,
libraries : [libintl_deps],
libraries_private : [win32_ldflags],

View File

@@ -251,6 +251,7 @@ if host_machine.system() == 'windows'
'win32' : {
'dependencies' : [wincodecs],
},
'win32-private' : {},
}
else
glib_tests += {
@@ -396,6 +397,7 @@ test_env.set('G_TEST_SRCDIR', meson.current_source_dir())
test_env.set('G_TEST_BUILDDIR', meson.current_build_dir())
test_deps = [libm, thread_dep, libglib_dep]
test_deps_static = [libm, thread_dep, libglib_static_dep]
test_cargs = ['-DG_LOG_DOMAIN="GLib"', '-UG_DISABLE_ASSERT']
test_cpp_args = test_cargs
@@ -448,12 +450,14 @@ foreach test_name, extra_args : glib_tests
)
endif
base_deps = test_name.contains('-private') ? test_deps_static : test_deps
exe = executable(test_name, source,
c_args : test_cargs + extra_args.get('c_args', []),
cpp_args : test_cpp_args + extra_args.get('cpp_args', []),
link_args : extra_args.get('link_args', []),
override_options : extra_args.get('override_options', []),
dependencies : test_deps + extra_args.get('dependencies', []),
dependencies : base_deps + extra_args.get('dependencies', []),
link_with : extra_args.get('link_with', []),
install_dir: installed_tests_execdir,
install_tag: 'tests',

View File

@@ -0,0 +1,77 @@
/*
* Copyright © 2019 Руслан Ижбулатов
* Copyright © 2025 Luca Bacci
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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/>.
*/
#include "config.h"
#include <glib.h>
#include <glib/gwin32private.h>
#include <windows.h>
static void
test_substitute_pid_and_event (void)
{
const wchar_t not_enough[] = L"too long when %e and %p are substituted";
wchar_t debugger_3[3];
wchar_t debugger_not_enough[G_N_ELEMENTS (not_enough)];
wchar_t debugger_enough[G_N_ELEMENTS (not_enough) + 1];
char *debugger_enough_utf8;
wchar_t debugger_big[65535] = {0};
char *debugger_big_utf8;
gchar *output;
guintptr be = (guintptr) 0xFFFFFFFF;
DWORD bp = MAXDWORD;
/* %f is not valid */
g_assert_false (g_win32_substitute_pid_and_event (debugger_3, G_N_ELEMENTS (debugger_3),
L"%f", 0, 0));
g_assert_false (g_win32_substitute_pid_and_event (debugger_3, G_N_ELEMENTS (debugger_3),
L"string longer than 10", 0, 0));
/* 200 is longer than %e, so the string doesn't fit by 1 byte */
g_assert_false (g_win32_substitute_pid_and_event (debugger_not_enough, G_N_ELEMENTS (debugger_not_enough),
not_enough, 10, 200));
/* This should fit */
g_assert_true (g_win32_substitute_pid_and_event (debugger_enough, G_N_ELEMENTS (debugger_enough),
not_enough, 10, 200));
debugger_enough_utf8 = g_utf16_to_utf8 (debugger_enough, -1, NULL, NULL, NULL);
g_assert_cmpstr (debugger_enough_utf8, ==, "too long when 200 and 10 are substituted");
g_free (debugger_enough_utf8);
g_assert_true (g_win32_substitute_pid_and_event (debugger_big, G_N_ELEMENTS (debugger_big),
L"multipl%e big %e %entries and %pids are %provided here", bp, be));
debugger_big_utf8 = g_utf16_to_utf8 (debugger_big, -1, NULL, NULL, NULL);
output = g_strdup_printf ("multipl%llu big %llu %lluntries and %luids are %lurovided here", (guint64) be, (guint64) be, (guint64) be, bp, bp);
g_assert_cmpstr (debugger_big_utf8, ==, output);
g_free (debugger_big_utf8);
g_free (output);
}
int
main (int argc,
char *argv[])
{
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/win32/substitute-pid-and-event", test_substitute_pid_and_event);
return g_test_run();
}

View File

@@ -33,48 +33,6 @@
static char *argv0 = NULL;
#include "../gwin32-private.c"
static void
test_subst_pid_and_event (void)
{
const wchar_t not_enough[] = L"too long when %e and %p are substituted";
wchar_t debugger_3[3];
wchar_t debugger_not_enough[G_N_ELEMENTS (not_enough)];
wchar_t debugger_enough[G_N_ELEMENTS (not_enough) + 1];
char *debugger_enough_utf8;
wchar_t debugger_big[65535] = {0};
char *debugger_big_utf8;
gchar *output;
guintptr be = (guintptr) 0xFFFFFFFF;
DWORD bp = MAXDWORD;
/* %f is not valid */
g_assert_false (_g_win32_subst_pid_and_event_w (debugger_3, G_N_ELEMENTS (debugger_3),
L"%f", 0, 0));
g_assert_false (_g_win32_subst_pid_and_event_w (debugger_3, G_N_ELEMENTS (debugger_3),
L"string longer than 10", 0, 0));
/* 200 is longer than %e, so the string doesn't fit by 1 byte */
g_assert_false (_g_win32_subst_pid_and_event_w (debugger_not_enough, G_N_ELEMENTS (debugger_not_enough),
not_enough, 10, 200));
/* This should fit */
g_assert_true (_g_win32_subst_pid_and_event_w (debugger_enough, G_N_ELEMENTS (debugger_enough),
not_enough, 10, 200));
debugger_enough_utf8 = g_utf16_to_utf8 (debugger_enough, -1, NULL, NULL, NULL);
g_assert_cmpstr (debugger_enough_utf8, ==, "too long when 200 and 10 are substituted");
g_free (debugger_enough_utf8);
g_assert_true (_g_win32_subst_pid_and_event_w (debugger_big, G_N_ELEMENTS (debugger_big),
L"multipl%e big %e %entries and %pids are %provided here", bp, be));
debugger_big_utf8 = g_utf16_to_utf8 (debugger_big, -1, NULL, NULL, NULL);
output = g_strdup_printf ("multipl%llu big %llu %lluntries and %luids are %lurovided here", (guint64) be, (guint64) be, (guint64) be, bp, bp);
g_assert_cmpstr (debugger_big_utf8, ==, output);
g_free (debugger_big_utf8);
g_free (output);
}
/* Crash with access violation */
static void
test_access_violation (void)
@@ -194,8 +152,6 @@ main (int argc,
return 0;
}
g_test_add_func ("/win32/substitute-pid-and-event", test_subst_pid_and_event);
g_test_add_func ("/win32/veh/access_violation", test_veh_crash_access_violation);
g_test_add_func ("/win32/veh/illegal_instruction", test_veh_crash_illegal_instruction);
g_test_add_func ("/win32/veh/debug", test_veh_debug);