diff --git a/.gitignore b/.gitignore index eda54ed0867910797b5d1b96b8086f45c1bcc58f..744d70fe9092b547608fa22be694026c3b5e963a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,6 @@ tags *.pc .*.swp .sw? -*.rc *.gcno *.gcda *.gcov diff --git a/build-aux/meson.build b/build-aux/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..7f3f2ffda33f6904817207cefccde8f22ba8508a --- /dev/null +++ b/build-aux/meson.build @@ -0,0 +1 @@ +subdir('win32') diff --git a/build-aux/win32/app.c b/build-aux/win32/app.c new file mode 100644 index 0000000000000000000000000000000000000000..e158c3b4d62e22fdf9fe68ffe4c790da7c948d39 --- /dev/null +++ b/build-aux/win32/app.c @@ -0,0 +1,162 @@ +/* + * 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 . + * + * Author: Luca Bacci + */ + +#include "config.h" + +#include + +#include +#include +#include +#include + +#ifdef _MSC_VER +#include +#endif + +static void +set_process_wide_settings (void) +{ +#if defined (_M_IX86) || defined (__i386__) + /* https://learn.microsoft.com/en-us/archive/blogs/michael_howard/faq-about-heapsetinformation-in-windows-vista-and-heap-based-buffer-overruns */ + /* https://web.archive.org/web/20080825034220/https://blogs.msdn.com/sdl/archive/2008/06/06/corrupted-heap-termination-redux.aspx */ + HeapSetInformation (NULL, HeapEnableTerminationOnCorruption, NULL, 0); + + /* https://learn.microsoft.com/en-us/archive/blogs/michael_howard/new-nx-apis-added-to-windows-vista-sp1-windows-xp-sp3-and-windows-server-2008 */ + SetProcessDEPPolicy (PROCESS_DEP_ENABLE | PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION); +#endif + + SetErrorMode (GetErrorMode () | SEM_FAILCRITICALERRORS); +} + +static void +set_crt_non_interactive (void) +{ + /* The Debug CRT may show UI dialogs even in console applications. + * Direct to stderr instead. + */ + _CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_FILE); + + _CrtSetReportFile (_CRT_ERROR, _CRTDBG_FILE_STDERR); + _CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_FILE); + + _CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDERR); + _CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE); +} + +static void +set_stderr_unbuffered_mode (void) +{ + /* MSVCRT.DLL can open stderr in full-buffering mode. That depends on + * the type of output device; for example, it's fully buffered for + * named pipes but not for console devices. + * + * Having a fully buffered stderr is not a good default since we can + * loose important messages before a crash. Moreover, POSIX forbids + * full buffering on stderr. So here we set stderr to unbuffered mode. + * + * Note: line buffering mode would be good enough, but the Windows C + * RunTime library implements it the same as full buffering: + * + * "for some systems, _IOLBF provides line buffering. However, for + * Win32, the behavior is the same as _IOFBF: Full Buffering" + * + * https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setvbuf#remarks + * + * References: + * + * - https://sourceforge.net/p/mingw/mailman/message/27121137/ + */ +#if !defined (_UCRT) + int ret = setvbuf (stderr, NULL, _IONBF, 0); + assert (ret == 0); +#endif +} + +static void +early_flush_exit_handler (void) +{ + /* There are two ways to flush open streams: calling fflush with NULL + * argument and calling _flushall. The former flushes output streams + * only, the latter flushes both input and output streams. + * We should not do anything with input streams here since flushing + * means * discarding * data. + */ + fflush (NULL); +} + +static void +register_early_flush_at_exit (void) +{ + /* Implement the two-phase flushing at process exit. + * + * The C RunTime library flushes open streams within its DllMain handler. + * This goes against the rules for DllMain, as each stream is protected + * by a lock and locks must not be acquired in DllMain. + * + * So we flush from app code using an atexit handler. The handler runs when + * the application is in a fully working state and thus is completely safe. + * + * This ensures that all important data is flushed. Anything that is written + * after exit will be flushed lately by the C RunTime library (and therefore + * may be skipped). + * + * See comments in "%ProgramFiles(x86)%\Windows Kits\10\Source\\ + * \ucrt\stdio\fflush.cpp" for more informations. + * + * References: + * + * - https://devblogs.microsoft.com/oldnewthing/20070503-00/?p=27003 + * - https://devblogs.microsoft.com/oldnewthing/20100122-00/?p=15193 + * - https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices + */ + int ret = atexit (early_flush_exit_handler); + assert (ret == 0); +} + +/* Boilerplate for CRT constructor */ + +#ifdef _MSC_VER +static void startup (void); + +__pragma (section (".CRT$XCT", long, read)) + +__declspec (allocate (".CRT$XCT")) +const void (*ptr_startup) (void) = startup; + +#ifdef _M_IX86 +__pragma (comment (linker, "/INCLUDE:" "_ptr_startup")) +#else +__pragma (comment (linker, "/INCLUDE:" "ptr_startup")) +#endif +#else +static void __attribute__((constructor)) startup (void); +#endif + +static void +startup (void) +{ + set_crt_non_interactive (); + set_process_wide_settings (); + set_stderr_unbuffered_mode (); + register_early_flush_at_exit (); +} diff --git a/build-aux/win32/app.manifest.xml b/build-aux/win32/app.manifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..57ec3d31d00995238687713649f316e71e1fd4e5 --- /dev/null +++ b/build-aux/win32/app.manifest.xml @@ -0,0 +1,40 @@ + + + + + UTF-8 + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build-aux/win32/app.rc b/build-aux/win32/app.rc new file mode 100644 index 0000000000000000000000000000000000000000..ce9785df1ca77f7ea780f07f783ec35a2cc503d3 --- /dev/null +++ b/build-aux/win32/app.rc @@ -0,0 +1,6 @@ +#pragma code_page(65001) + +#define WIN32_LEAN_AND_MEAN +#include + +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "app.manifest.xml" diff --git a/build-aux/win32/lib.rc.in b/build-aux/win32/lib.rc.in new file mode 100644 index 0000000000000000000000000000000000000000..0dac990ba2e13b365d5ed946da9bdb0a305e254f --- /dev/null +++ b/build-aux/win32/lib.rc.in @@ -0,0 +1,35 @@ +#pragma code_page(65001) + +#define WIN32_LEAN_AND_MEAN +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @MAJOR@,@MINOR@,@MICRO@,0 + PRODUCTVERSION @MAJOR@,@MINOR@,@MICRO@,0 + FILEFLAGSMASK 0 + FILEFLAGS 0 + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT2_UNKNOWN + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", "The GLib developer community" + VALUE "FileDescription", "@DESCRIPTION@" + VALUE "FileVersion", "@MAJOR@.@MINOR@.@MICRO@" + VALUE "InternalName", "@NAME@" + VALUE "LegalCopyright", "© @COPYRIGHTYEAR@ the GLib developer community. © 1995-2011 Peter Mattis, Spencer Kimball, Josh MacDonald and others." + VALUE "OriginalFilename", "@FILENAME@" + VALUE "ProductName", "GLib" + VALUE "ProductVersion", "@MAJOR@.@MINOR@.@MICRO@" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END + END diff --git a/build-aux/win32/meson.build b/build-aux/win32/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..cf8c56ffa81715b930d5486f03345e767dd1366b --- /dev/null +++ b/build-aux/win32/meson.build @@ -0,0 +1,23 @@ + +if host_system == 'windows' + static_lib = static_library('os-profile-app-static-lib', + sources: ['app.c'], + include_directories: [configinc]) + + resources = windows.compile_resources('app.rc', + depend_files: ['app.manifest.xml']) + + app_profile_dep = declare_dependency(link_whole: [static_lib], + sources: [resources]) +else + app_profile_dep = declare_dependency() +endif + +rc_conf_base = configuration_data({ + 'MAJOR': major_version, + 'MINOR': minor_version, + 'MICRO': micro_version, + 'COPYRIGHTYEAR': '2025', +}) + +lib_rc_in = files('lib.rc.in') diff --git a/fuzzing/meson.build b/fuzzing/meson.build index addbe907172539dd8d6c97b86e22974d150e7d6c..a66c2dd2150b9d5880bee4ee87aec17646fe47ae 100644 --- a/fuzzing/meson.build +++ b/fuzzing/meson.build @@ -47,7 +47,7 @@ fuzz_targets = [ 'fuzz_variant_text', ] -deps = [libgmodule_dep, libgio_dep, libglib_dep, libgobject_dep] +deps = [libgmodule_dep, libgio_dep, libglib_dep, libgobject_dep, app_profile_dep] extra_sources = [] extra_c_args = cc.get_supported_arguments('-Werror=unused-function') diff --git a/gio/gio.rc.in b/gio/gio.rc.in deleted file mode 100644 index 3b19b3ee130eb43a77d3ac2e01400ae6a01a53d3..0000000000000000000000000000000000000000 --- a/gio/gio.rc.in +++ /dev/null @@ -1,30 +0,0 @@ -#include - -VS_VERSION_INFO VERSIONINFO - FILEVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0 - PRODUCTVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0 - FILEFLAGSMASK 0 - FILEFLAGS 0 - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN - BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "The GLib developer community" - VALUE "FileDescription", "Gio" - VALUE "FileVersion", "@GLIB_VERSION@.0" - VALUE "InternalName", "libgio-2.0-@LT_CURRENT_MINUS_AGE@" - VALUE "LegalCopyright", "Copyright 2006-2011 Red Hat, Inc. and others." - VALUE "OriginalFilename", "libgio-2.0-@LT_CURRENT_MINUS_AGE@.dll" - VALUE "ProductName", "GLib" - VALUE "ProductVersion", "@GLIB_VERSION@" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END - END diff --git a/gio/meson.build b/gio/meson.build index 201d2935fd16397b7536564722f294f79aaf27b8..8730291b37476d3ecccdc706cbf23fbd71208c8a 100644 --- a/gio/meson.build +++ b/gio/meson.build @@ -426,6 +426,7 @@ if host_system != 'windows' endif gio_launch_desktop = executable('gio-launch-desktop', launch_desktop_sources, + dependencies: [app_profile_dep], include_directories : glibinc, install : true, install_dir : multiarch_libexecdir, @@ -473,13 +474,21 @@ else ) if glib_build_shared - gio_win_rc = configure_file( - input: 'gio.rc.in', + gio_rc_conf = configuration_data({ + 'NAME': 'GIO', + 'FILENAME': (cc.get_argument_syntax() == 'msvc' ? '' : 'lib') + 'gio-' + glib_api_version + '-' + soversion.to_string() + '.dll', + 'DESCRIPTION': 'Gio is a library providing general purpose I/O, networking, IPC, settings, and other high level application functionality', + }) + gio_rc_conf.merge_from(rc_conf_base) + lib_rc = configure_file( + input: lib_rc_in, output: 'gio.rc', - configuration: glibconfig_conf, + configuration: gio_rc_conf, ) - gio_win_res = windows.compile_resources(gio_win_rc) - win32_sources += [gio_win_res] + win32_sources += [windows.compile_resources(lib_rc, + # Workaround for https://github.com/llvm/llvm-project/issues/63426 + args: ['-c', '65001'], + )] endif gio_win32_include_headers = files( @@ -1039,14 +1048,14 @@ gio_tool = executable('gio', gio_tool_sources, c_args : gio_c_args, # intl.lib is not compatible with SAFESEH link_args : noseh_link_args, - dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep]) + dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep, app_profile_dep]) executable('gresource', 'gresource-tool.c', install : true, install_tag : 'bin', # intl.lib is not compatible with SAFESEH link_args : noseh_link_args, - dependencies : [libelf, libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep]) + dependencies : [libelf, libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep, app_profile_dep]) gio_querymodules = executable('gio-querymodules', 'gio-querymodules.c', 'giomodule-priv.c', install : true, @@ -1055,7 +1064,7 @@ gio_querymodules = executable('gio-querymodules', 'gio-querymodules.c', 'giomodu c_args : gio_c_args, # intl.lib is not compatible with SAFESEH link_args : noseh_link_args, - dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep]) + dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep, app_profile_dep]) glib_compile_schemas = executable('glib-compile-schemas', ['glib-compile-schemas.c'], @@ -1064,7 +1073,7 @@ glib_compile_schemas = executable('glib-compile-schemas', install_tag : 'bin', # intl.lib is not compatible with SAFESEH link_args : noseh_link_args, - dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep, gvdb_dep]) + dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep, gvdb_dep, app_profile_dep]) glib_compile_resources = executable('glib-compile-resources', [gconstructor_as_data_h, 'glib-compile-resources.c'], @@ -1073,7 +1082,7 @@ glib_compile_resources = executable('glib-compile-resources', c_args : gio_c_args, # intl.lib is not compatible with SAFESEH link_args : noseh_link_args, - dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep, gvdb_dep]) + dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep, gvdb_dep, app_profile_dep]) install_data('gresource.dtd', install_dir: get_option('datadir') / dtds_subdir, install_tag: 'devel', @@ -1094,7 +1103,7 @@ executable('gsettings', 'gsettings-tool.c', c_args : gio_c_args, # intl.lib is not compatible with SAFESEH link_args : noseh_link_args, - dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep]) + dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep, app_profile_dep]) install_data('gschema.dtd', install_dir : get_option('datadir') / schemas_subdir, install_tag : 'devel', @@ -1111,7 +1120,7 @@ executable('gdbus', 'gdbus-tool.c', c_args : gio_c_args, # intl.lib is not compatible with SAFESEH link_args : noseh_link_args, - dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep]) + dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep, app_profile_dep]) if host_system != 'windows' and not glib_have_cocoa executable('gapplication', 'gapplication-tool.c', @@ -1120,7 +1129,7 @@ if host_system != 'windows' and not glib_have_cocoa c_args : gio_c_args, # intl.lib is not compatible with SAFESEH link_args : noseh_link_args, - dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep]) + dependencies : [libgio_dep, libgobject_dep, libgmodule_dep, libglib_dep, app_profile_dep]) endif if enable_systemtap diff --git a/gio/tests/meson.build b/gio/tests/meson.build index e719008e472870604c8faade600ff0f681e5d854..efd5e2ff7984368d4a5f50dfcd27c869e383ca27 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -635,7 +635,7 @@ if host_machine.system() != 'windows' # This test is currently unreliable executable('gdbus-overflow', 'gdbus-overflow.c', c_args : test_c_args, - dependencies : common_gio_tests_deps, + dependencies : common_gio_tests_deps + [app_profile_dep], install_dir : installed_tests_execdir, install_tag : 'tests', install : installed_tests_enabled) @@ -1129,7 +1129,7 @@ foreach program_name, extra_args : test_extra_programs program_name : executable(program_name, sources: [source, extra_sources], c_args : test_c_args, - dependencies : common_gio_tests_deps + extra_args.get('dependencies', []), + dependencies : common_gio_tests_deps + extra_args.get('dependencies', []) + [app_profile_dep], install_dir : installed_tests_execdir, install_tag : 'tests', install : install, @@ -1168,7 +1168,7 @@ foreach test_name, extra_args : gio_tests exe = executable(test_name, [source, extra_sources], c_args : test_c_args + extra_args.get('c_args', []), cpp_args : test_cpp_args + extra_args.get('cpp_args', []), - dependencies : common_gio_tests_deps + extra_args.get('dependencies', []), + dependencies : common_gio_tests_deps + extra_args.get('dependencies', []) + [app_profile_dep], install_rpath : extra_args.get('install_rpath', ''), install_dir: installed_tests_execdir, install_tag: 'tests', diff --git a/gio/tests/static-link/meson.build b/gio/tests/static-link/meson.build index c0b638fe6cf0eed8f4ae1b8b49ac8248016167d4..558840d0e673d4b07da0762645f9466af6d87418 100644 --- a/gio/tests/static-link/meson.build +++ b/gio/tests/static-link/meson.build @@ -3,6 +3,9 @@ project('test-static-link', 'c') # This is a dummy project that static links against installed gio. # See gio/tests/static-link.py. app = executable('test-static-link', 'app.c', - dependencies : dependency('gio-2.0', static : true) + dependencies : [ + dependency('gio-2.0', static : true), + app_profile_dep, + ] ) test('test-static-link', app) diff --git a/girepository/compiler/meson.build b/girepository/compiler/meson.build index eb704761e2c57c4a78e3fbe141a2c887a13f3d98..c3fce078e1c0bb6e0c8d78c6ad6472f9f76dc055 100644 --- a/girepository/compiler/meson.build +++ b/girepository/compiler/meson.build @@ -20,6 +20,7 @@ gicompilerepository = executable('gi-compile-repository', 'compiler.c', libgirepository_dep, libgirepository_internals_dep, libgio_dep, + app_profile_dep, ], install: true, c_args: custom_c_args, diff --git a/girepository/decompiler/meson.build b/girepository/decompiler/meson.build index b6090f61f6b531395be61bb08cac064042b2e119..a2fb904b48bd15b5b94e72d5f10b517b1348e799 100644 --- a/girepository/decompiler/meson.build +++ b/girepository/decompiler/meson.build @@ -20,6 +20,7 @@ gidecompiletypelib = executable('gi-decompile-typelib', 'decompiler.c', libgirepository_dep, libgirepository_internals_dep, libgio_dep, + app_profile_dep, ], install: true, c_args: custom_c_args, diff --git a/girepository/inspector/meson.build b/girepository/inspector/meson.build index 4467e6df80b6079d4a55fef3d4a2cdd065dd1ff5..81d43e3eb840fd60561604191ff91bb0d02e6c69 100644 --- a/girepository/inspector/meson.build +++ b/girepository/inspector/meson.build @@ -19,6 +19,7 @@ giinspecttypelib = executable('gi-inspect-typelib', 'inspector.c', dependencies: [ libgirepository_dep, libgio_dep, + app_profile_dep, ], install: true, c_args: custom_c_args, diff --git a/girepository/meson.build b/girepository/meson.build index b08801891b6b05a3a70fb97284afe1d1113c4b82..3d1793e355a696bf1a966f917b8acd1fb949371c 100644 --- a/girepository/meson.build +++ b/girepository/meson.build @@ -225,7 +225,8 @@ executable('gi-dump-types', dependencies: [ libgirepository_dep, libgiounix_dep, - libgiowin32_dep + libgiowin32_dep, + app_profile_dep, ], ) diff --git a/girepository/tests/meson.build b/girepository/tests/meson.build index b804346fb48c0af49e027e6f44df636dfa4841e2..4d3f64a6d3311a9c2c234112cd782d131628e0dc 100644 --- a/girepository/tests/meson.build +++ b/girepository/tests/meson.build @@ -96,7 +96,7 @@ test_env = environment() 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, libgirepository_dep] +test_deps = [libm, thread_dep, libgirepository_dep, app_profile_dep] test_cargs = ['-DG_LOG_DOMAIN="GIRepository"', '-UG_DISABLE_ASSERT', warning_sign_conversion_args] test_cpp_args = test_cargs diff --git a/glib/glib-mirroring-tab/meson.build b/glib/glib-mirroring-tab/meson.build index 4b14ecf3be80a90b0f222509cabcbabdb58908cc..2900be203d3bc352e8731cc62361f6bd6b675a23 100644 --- a/glib/glib-mirroring-tab/meson.build +++ b/glib/glib-mirroring-tab/meson.build @@ -1,5 +1,5 @@ gen_mirroring_tab = executable('gen-mirroring-tab', ['gen-mirroring-tab.c', 'packtab.c'], - dependencies : [libglib_dep], + dependencies : [libglib_dep, app_profile_dep], install: false, ) \ No newline at end of file diff --git a/glib/glib.rc.in b/glib/glib.rc.in deleted file mode 100644 index c69f644011612c64247acffbd142104ae97f6372..0000000000000000000000000000000000000000 --- a/glib/glib.rc.in +++ /dev/null @@ -1,30 +0,0 @@ -#include - -VS_VERSION_INFO VERSIONINFO - FILEVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0 - PRODUCTVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0 - FILEFLAGSMASK 0 - FILEFLAGS 0 - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN - BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "The GLib developer community" - VALUE "FileDescription", "GLib" - VALUE "FileVersion", "@GLIB_VERSION@.0" - VALUE "InternalName", "libglib-2.0-@LT_CURRENT_MINUS_AGE@" - VALUE "LegalCopyright", "Copyright 1995-2011 Peter Mattis, Spencer Kimball, Josh MacDonald and others." - VALUE "OriginalFilename", "libglib-2.0-@LT_CURRENT_MINUS_AGE@.dll" - VALUE "ProductName", "GLib" - VALUE "ProductVersion", "@GLIB_VERSION@" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END - END diff --git a/glib/gtestutils.c b/glib/gtestutils.c index 99d6e4c4dd9d9733db5f511936ca4f56ccc1d8bb..5affaddecdb183a943bfb0c0de1a1d91c292740f 100644 --- a/glib/gtestutils.c +++ b/glib/gtestutils.c @@ -205,6 +205,8 @@ * process will inherit the parent's stderr. Otherwise, the child's * stderr will not be visible, but it will be captured to allow * later tests with [func@GLib.test_trap_assert_stderr]. + * @G_TEST_SUBPROCESS_INHERIT_DESCRIPTORS: If this flag is given, the + * child process will inherit the parent’s open file descriptors. * * Flags to pass to [func@GLib.test_trap_subprocess] to control input and output. * @@ -4175,7 +4177,7 @@ g_test_trap_subprocess_with_envp (const char *test_path, g_ptr_array_add (argv, NULL); flags = G_SPAWN_DO_NOT_REAP_CHILD; - if (test_log_fd != -1) + if ((test_flags & G_TEST_SUBPROCESS_INHERIT_DESCRIPTORS) || test_log_fd != -1) flags |= G_SPAWN_LEAVE_DESCRIPTORS_OPEN; if (test_flags & G_TEST_SUBPROCESS_INHERIT_STDIN) flags |= G_SPAWN_CHILD_INHERITS_STDIN; diff --git a/glib/gtestutils.h b/glib/gtestutils.h index 6dae09cf7b113550c7580c07b2a2c469534dfd85..ca9782ae78394c520eb9b07c66bd80cb1eacf427 100644 --- a/glib/gtestutils.h +++ b/glib/gtestutils.h @@ -540,7 +540,8 @@ typedef enum { G_TEST_SUBPROCESS_DEFAULT GLIB_AVAILABLE_ENUMERATOR_IN_2_74 = 0, G_TEST_SUBPROCESS_INHERIT_STDIN = 1 << 0, G_TEST_SUBPROCESS_INHERIT_STDOUT = 1 << 1, - G_TEST_SUBPROCESS_INHERIT_STDERR = 1 << 2 + G_TEST_SUBPROCESS_INHERIT_STDERR = 1 << 2, + G_TEST_SUBPROCESS_INHERIT_DESCRIPTORS GLIB_AVAILABLE_ENUMERATOR_IN_2_88 = 1 << 3, } G_GNUC_FLAG_ENUM GTestSubprocessFlags; GLIB_AVAILABLE_IN_2_38 diff --git a/glib/meson.build b/glib/meson.build index 209bcbfd119b68998ff87b609e00a0e8a55b92f9..8b1ce5c7720198b2a53ff22311e12cc74ecc4a15 100644 --- a/glib/meson.build +++ b/glib/meson.build @@ -355,14 +355,23 @@ platform_deps = [] if host_system == 'windows' if glib_build_shared - glib_win_rc = configure_file( - input: 'glib.rc.in', + glib_rc_conf = configuration_data({ + 'NAME': 'GLib', + 'FILENAME': (cc.get_argument_syntax() == 'msvc' ? '' : 'lib') + 'glib-' + glib_api_version + '-' + soversion.to_string() + '.dll', + 'DESCRIPTION': 'GLib is a general-purpose, portable utility library', + }) + glib_rc_conf.merge_from(rc_conf_base) + lib_rc = configure_file( + input: lib_rc_in, output: 'glib.rc', - configuration: glibconfig_conf, + configuration: glib_rc_conf, ) - glib_win_res = windows.compile_resources(glib_win_rc) - glib_sources += [glib_win_res] + glib_sources += [windows.compile_resources(lib_rc, + # Workaround for https://github.com/llvm/llvm-project/issues/63426 + args: ['-c', '65001'], + )] endif + glib_sources += files('gwin32.c', 'gspawn-win32.c', 'giowin32.c') platform_deps = [winsock2, cc.find_library('winmm')] if cc.get_id() == 'msvc' or cc.get_id() == 'clang-cl' @@ -496,23 +505,23 @@ if host_system == 'windows' install : true, win_subsystem : 'windows', include_directories : configinc, - dependencies : [libglib_dep]) + dependencies : [libglib_dep, app_profile_dep]) gspawn_helpers += executable('gspawn-win32-helper-console', 'gspawn-win32-helper.c', install : true, c_args : ['-DHELPER_CONSOLE'], include_directories : configinc, - dependencies : [libglib_dep]) + dependencies : [libglib_dep, app_profile_dep]) else gspawn_helpers += executable('gspawn-win64-helper', 'gspawn-win32-helper.c', install : true, win_subsystem : 'windows', include_directories : configinc, - dependencies : [libglib_dep]) + dependencies : [libglib_dep, app_profile_dep]) gspawn_helpers += executable('gspawn-win64-helper-console', 'gspawn-win32-helper.c', install : true, c_args : ['-DHELPER_CONSOLE'], include_directories : configinc, - dependencies : [libglib_dep]) + dependencies : [libglib_dep, app_profile_dep]) endif else gtester = executable('gtester', 'gtester.c', @@ -520,7 +529,7 @@ else install_tag : 'bin-devel', c_args : ['-UG_DISABLE_ASSERT'], include_directories : configinc, - dependencies : [libglib_dep]) + dependencies : [libglib_dep, app_profile_dep]) # Provide tools for others when we're a subproject and they use the Meson GNOME module meson.override_find_program('gtester', gtester) diff --git a/glib/tests/meson.build b/glib/tests/meson.build index c4fec0c13c08724f4b3dbe55d7c732df35a0fec8..301c06c9d4f2baa9835480c181a967b6b03959e6 100644 --- a/glib/tests/meson.build +++ b/glib/tests/meson.build @@ -400,8 +400,8 @@ test_env = environment() 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_deps = [libm, thread_dep, libglib_dep, app_profile_dep] +test_deps_static = [libm, thread_dep, libglib_static_dep, app_profile_dep] test_cargs = ['-DG_LOG_DOMAIN="GLib"', '-UG_DISABLE_ASSERT'] test_cpp_args = test_cargs diff --git a/glib/tests/win32.c b/glib/tests/win32.c index 5cef08a2e5ec352027c5bc013be07b0ab06b0385..760bf77d59e7b75048d74bef3983628615ecc94f 100644 --- a/glib/tests/win32.c +++ b/glib/tests/win32.c @@ -25,8 +25,15 @@ #include #include +#include + #include +#include +#include +#include +#include #include +#include /* for RTL_OSVERSIONINFO */ #define COBJMACROS #include @@ -138,6 +145,267 @@ test_clear_com (void) CoUninitialize (); } +static void +test_subprocess_stderr_buffering_mode (void) +{ + int ret = fprintf (stderr, "hello world\n"); + g_assert_cmpint (ret, >, 0); + + /* We want to exit without flushing stdio streams. We could + * use _Exit here, but the C standard doesn't specify whether + * _Exit flushes stdio streams or not. + * The Windows C RunTime library doesn't flush streams, but + * we should not rely on implementation details which may + * change in the future. Use TerminateProcess. + */ + TerminateProcess (GetCurrentProcess (), 0); +} + +static void +test_stderr_buffering_mode (void) +{ + /* MSVCRT.DLL can open stderr in full-buffering mode. + * This can cause loss of important messages before + * a crash. Additionally, POSIX disallows full buffering + * of stderr, so this is not good for portability. + * We have a workaround in the app-profile dependency + * that we add to each executable. + */ + g_test_trap_subprocess ("/win32/subprocess/stderr-buffering-mode", + 0, + G_TEST_SUBPROCESS_DEFAULT); + g_test_trap_assert_passed (); + g_test_trap_assert_stderr ("hello world?\n"); +} + +#ifndef _WIN32_WINNT_WIN10 +#define _WIN32_WINNT_WIN10 0x0A00 +#endif +#ifndef STATUS_SUCCESS +#define STATUS_SUCCESS 0 +#endif + +static void +test_manifest_os_compatibility (void) +{ + const WORD highest_known_major_minor_word = _WIN32_WINNT_WIN10; + + HMODULE module_handle = LoadLibraryEx (L"NTDLL.DLL", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + if (module_handle == NULL) + { + g_error ("%s (%s) failed: %s", + "LoadLibraryEx", "NTDLL.DLL", + g_win32_error_message (GetLastError ())); + } + + typedef NTSTATUS (WINAPI *ptr_RtlGetVersion_t) (RTL_OSVERSIONINFOW *); + + ptr_RtlGetVersion_t ptr_RtlGetVersion = + (ptr_RtlGetVersion_t) GetProcAddress (module_handle, "RtlGetVersion"); + if (ptr_RtlGetVersion == NULL) + { + g_error ("%s (%s, %s) failed: %s", + "GetProcAddress", "NTDLL.DLL", "RtlGetVersion", + g_win32_error_message (GetLastError ())); + } + + /* RtlGetVersion is not subject to compatibility settings + * present in the activation context, it always returns + * the real OS version. + */ + RTL_OSVERSIONINFOW rtl_os_version_info; + rtl_os_version_info.dwOSVersionInfoSize = sizeof (rtl_os_version_info); + + NTSTATUS status = ptr_RtlGetVersion (&rtl_os_version_info); + if (status != STATUS_SUCCESS) + { + g_error ("%s failed", + "RtlGetVersion"); + } + + /* Now verify if the activation context contains up-to-date + * compatibility info. + */ + OSVERSIONINFO os_version_info; + os_version_info.dwOSVersionInfoSize = sizeof (os_version_info); + + BOOL success = GetVersionEx (&os_version_info); + if (!success) + { + g_error ("%s failed: %s", + "GetVersionEx", + g_win32_error_message (GetLastError ())); + } + + if (rtl_os_version_info.dwMajorVersion != os_version_info.dwMajorVersion || + rtl_os_version_info.dwMinorVersion != os_version_info.dwMinorVersion || + rtl_os_version_info.dwBuildNumber != os_version_info.dwBuildNumber) + { + WORD rtl_major_minor_word = MAKEWORD ((BYTE)rtl_os_version_info.dwMinorVersion, + (BYTE)rtl_os_version_info.dwMajorVersion); + + if (rtl_major_minor_word > highest_known_major_minor_word) + g_error ("Please, update the manifest XML and the test's constant"); + + g_assert_cmpuint (rtl_os_version_info.dwMajorVersion, ==, os_version_info.dwMajorVersion); + g_assert_cmpuint (rtl_os_version_info.dwMinorVersion, ==, os_version_info.dwMinorVersion); + g_assert_cmpuint (rtl_os_version_info.dwBuildNumber, ==, os_version_info.dwBuildNumber); + } + + FreeLibrary (module_handle); +} + +typedef struct { + FILE *stream; + bool done; + GMutex mutex; + GCond cond; +} StreamLockData_t; + +static gpointer +thread_acquire_stdio_stream_lock (gpointer user_data) +{ + StreamLockData_t *data = (StreamLockData_t *) user_data; + FILE *stream = data->stream; + + /* For the test to be effective, this thread must be holding + * the stream lock when the subprocess "main function" (i.e. + * test_subprocess_early_flush) returns. + * + * This simulates a thread doing I/O on a stream at the time + * exit invokes ExitProcess. Note that _lock_file is exactly + * what stdio functions call internally. + */ + + _lock_file (stream); + + g_mutex_lock (&data->mutex); + data->done = true; + g_cond_signal (&data->cond); + g_mutex_unlock (&data->mutex); + data = NULL; + + /* Sleep a bit to let the main thread exit. Note: if somehow + * the main thread doesn't exit in time, this test will + * succeed but won't actually verify anything. + */ + g_usleep (1 * G_USEC_PER_SEC); + + _unlock_file (stream); + + return NULL; +} + +static void +test_subprocess_early_stdio_flush (void) +{ + int64_t fd; + FILE *stream; + int ret; + + fd = g_ascii_strtoull (g_getenv ("G_TEST_PIPE_FD"), NULL, 10); + g_assert_cmpuint (fd, >=, 0); + g_assert_cmpuint (fd, <=, INT_MAX); + + stream = _fdopen ((int) fd, "w"); + g_assert_nonnull (stream); + + ret = setvbuf (stream, NULL, _IOFBF, 1024); + g_assert_cmpint (ret, ==, 0); + + ret = fprintf (stream, "hello world"); + g_assert_cmpint (ret, ==, (int) strlen ("hello world")); + g_assert_false (ferror (stream)); + + StreamLockData_t data; + memset (&data, 0, sizeof (data)); + data.stream = stream; + data.done = false; + + GThread *thread = g_thread_new ("lock stdio stream", + thread_acquire_stdio_stream_lock, + (gpointer) &data); + g_thread_unref (thread); + + /* Wait until the worker thread has acquired the stream lock. + */ + g_mutex_lock (&data.mutex); + while (!data.done) + g_cond_wait (&data.cond, &data.mutex); + g_mutex_unlock (&data.mutex); + + /* If the early flush is not implemented, the C RunTime will attempt + * to acquire the stream's internal CRITICAL_SECTION from DllMain. + * Then the process will be terminated abruptly (with the same exit + * code passed to exit) leaving stream unflushed. + */ +} + +static gpointer +thread_read_pipe (gpointer user_data) +{ + int fd = GPOINTER_TO_INT (user_data); + const char *iter = "hello world"; + int size = (int) strlen (iter); + + while (size > 0) + { + char buffer[20]; + int ret = _read (fd, buffer, sizeof (buffer)); + + g_assert_cmpint (ret, >, 0); + g_assert_cmpint (ret, <=, size); + + g_assert_cmpmem (buffer, ret, iter, ret); + + iter += ret; + size -= ret; + } + + return NULL; +} + +static void +test_early_stdio_flush (void) +{ + int pipe_fds[2]; + int pipe_read; + int pipe_write; + char buffer[10]; + GStrv envp = NULL; + GError *error = NULL; + int ret; + + ret = _pipe (pipe_fds, 1024, _O_BINARY); + if (ret < 0) + g_error ("%s failed: %s", "_pipe", g_strerror (errno)); + + pipe_read = pipe_fds[0]; + pipe_write = pipe_fds[1]; + + g_snprintf (buffer, sizeof (buffer), "%i", pipe_write); + envp = g_get_environ (); + envp = g_environ_setenv (g_steal_pointer (&envp), "G_TEST_PIPE_FD", buffer, TRUE); + + GThread *thread = g_thread_new ("read pipe", + thread_read_pipe, + GINT_TO_POINTER (pipe_read)); + + typedef const char * const * GStrvConst_t; + g_test_trap_subprocess_with_envp ("/win32/subprocess/early-stdio-flush", + (GStrvConst_t) envp, 0, + G_TEST_SUBPROCESS_INHERIT_DESCRIPTORS); + g_test_trap_assert_passed (); + + g_close (pipe_write, &error); + g_assert_no_error (error); + + g_thread_join (thread); + + g_close (pipe_read, NULL); + g_strfreev (envp); +} + int main (int argc, char *argv[]) @@ -161,5 +429,11 @@ main (int argc, g_test_add_func ("/win32/subprocess/illegal_instruction", test_illegal_instruction); g_test_add_func ("/win32/com/clear", test_clear_com); + g_test_add_func ("/win32/subprocess/stderr-buffering-mode", test_subprocess_stderr_buffering_mode); + g_test_add_func ("/win32/stderr-buffering-mode", test_stderr_buffering_mode); + g_test_add_func ("/win32/manifest-os-compatibility", test_manifest_os_compatibility); + g_test_add_func ("/win32/subprocess/early-stdio-flush", test_subprocess_early_stdio_flush); + g_test_add_func ("/win32/early-stdio-flush", test_early_stdio_flush); + return g_test_run(); } diff --git a/gmodule/gmodule.rc.in b/gmodule/gmodule.rc.in deleted file mode 100644 index c3d762da908308420f435d6d509c4c44175bc4a7..0000000000000000000000000000000000000000 --- a/gmodule/gmodule.rc.in +++ /dev/null @@ -1,30 +0,0 @@ -#include - -VS_VERSION_INFO VERSIONINFO - FILEVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0 - PRODUCTVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0 - FILEFLAGSMASK 0 - FILEFLAGS 0 - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN - BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "The GLib developer community" - VALUE "FileDescription", "GModule" - VALUE "FileVersion", "@GLIB_VERSION@.0" - VALUE "InternalName", "libgmodule-2.0-@LT_CURRENT_MINUS_AGE@" - VALUE "LegalCopyright", "Copyright 1998-2011 Tim Janik and others." - VALUE "OriginalFilename", "libgmodule-2.0-@LT_CURRENT_MINUS_AGE@.dll" - VALUE "ProductName", "GLib" - VALUE "ProductVersion", "@GLIB_VERSION@" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END - END diff --git a/gmodule/meson.build b/gmodule/meson.build index 37a8fa42d5e5bade394abf4dcebf097a7f522532..5a226319c06e9b5471a99a2767be6a1bc228f8c2 100644 --- a/gmodule/meson.build +++ b/gmodule/meson.build @@ -79,13 +79,21 @@ gmodule_visibility_h = custom_target( gmodule_sources = [gmodule_c, gmodule_visibility_h, gmodule_deprecated_c] if host_system == 'windows' and glib_build_shared - gmodule_win_rc = configure_file( - input: 'gmodule.rc.in', + gmodule_rc_conf = configuration_data({ + 'NAME': 'GModule', + 'FILENAME': (cc.get_argument_syntax() == 'msvc' ? '' : 'lib') + 'gmodule-' + glib_api_version + '-' + soversion.to_string() + '.dll', + 'DESCRIPTION': 'Portable API for dynamically loading modules', + }) + gmodule_rc_conf.merge_from(rc_conf_base) + lib_rc = configure_file( + input: lib_rc_in, output: 'gmodule.rc', - configuration: glibconfig_conf, + configuration: gmodule_rc_conf, ) - gmodule_win_res = windows.compile_resources(gmodule_win_rc) - gmodule_sources += [gmodule_win_res] + gmodule_sources += [windows.compile_resources(lib_rc, + # Workaround for https://github.com/llvm/llvm-project/issues/63426 + args: ['-c', '65001'], + )] endif libgmodule = library('gmodule-2.0', diff --git a/gmodule/tests/meson.build b/gmodule/tests/meson.build index e7d7b3dd1e150b303252ed59b9ae8463e009eddc..64e6040e06529e8ea7b51aa43542a8f57602abe0 100644 --- a/gmodule/tests/meson.build +++ b/gmodule/tests/meson.build @@ -74,7 +74,7 @@ test_env = environment() 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, libgmodule_dep] +test_deps = [libm, thread_dep, libglib_dep, libgmodule_dep, app_profile_dep] test_cargs = ['-DG_LOG_DOMAIN="GModule"', '-UG_DISABLE_ASSERT', warning_sign_conversion_args] test_cpp_args = test_cargs diff --git a/gobject/gobject.rc.in b/gobject/gobject.rc.in deleted file mode 100644 index 1c73e934b20bbe0e04c83c2ccba59f4ca944e853..0000000000000000000000000000000000000000 --- a/gobject/gobject.rc.in +++ /dev/null @@ -1,30 +0,0 @@ -#include - -VS_VERSION_INFO VERSIONINFO - FILEVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0 - PRODUCTVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0 - FILEFLAGSMASK 0 - FILEFLAGS 0 - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN - BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "The GLib developer community" - VALUE "FileDescription", "GObject" - VALUE "FileVersion", "@GLIB_VERSION@.0" - VALUE "InternalName", "libgobject-2.0-@LT_CURRENT_MINUS_AGE@" - VALUE "LegalCopyright", "Copyright 1998-2011 Tim Janik, Red Hat, Inc. and others" - VALUE "OriginalFilename", "libgobject-2.0-@LT_CURRENT_MINUS_AGE@.dll" - VALUE "ProductName", "GLib" - VALUE "ProductVersion", "@GLIB_VERSION@" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END - END diff --git a/gobject/meson.build b/gobject/meson.build index 91823af79a739e092dec244e59d3a51faea9bf45..54266f32c2ba0d6f65fa470ac536206512ab30ef 100644 --- a/gobject/meson.build +++ b/gobject/meson.build @@ -61,13 +61,21 @@ gobject_sources += files( ) if host_system == 'windows' and glib_build_shared - gobject_win_rc = configure_file( - input: 'gobject.rc.in', + gobject_rc_conf = configuration_data({ + 'NAME': 'GObject', + 'FILENAME': (cc.get_argument_syntax() == 'msvc' ? '' : 'lib') + 'gobject-' + glib_api_version + '-' + soversion.to_string() + '.dll', + 'DESCRIPTION': 'The base type system and object class', + }) + gobject_rc_conf.merge_from(rc_conf_base) + lib_rc = configure_file( + input: lib_rc_in, output: 'gobject.rc', - configuration: glibconfig_conf, + configuration: gobject_rc_conf, ) - gobject_win_res = windows.compile_resources(gobject_win_rc) - gobject_sources += [gobject_win_res] + gobject_sources += [windows.compile_resources(lib_rc, + # Workaround for https://github.com/llvm/llvm-project/issues/63426 + args: ['-c', '65001'], + )] endif if enable_dtrace @@ -171,7 +179,7 @@ meson.override_dependency('gobject-2.0', libgobject_dep) gobject_query = executable('gobject-query', 'gobject-query.c', install : true, install_tag : 'bin-devel', - dependencies : [libglib_dep, libgobject_dep]) + dependencies : [libglib_dep, libgobject_dep, app_profile_dep]) install_data('gobject_gdb.py', install_dir : glib_pkgdatadir / 'gdb', diff --git a/gobject/tests/meson.build b/gobject/tests/meson.build index 214df48459a04ae91a46900544fe6b8cb15ef12e..e26acf12748615763fd3a6bd515e2a1761eb239c 100644 --- a/gobject/tests/meson.build +++ b/gobject/tests/meson.build @@ -28,35 +28,10 @@ marshalers_c = custom_target('marshalers_c', ], ) -# We must embed custom-dispatch.exe with an application -# manifest to pacify UAC in order to run on 32-bit Windows -# builds, otherwise the test will not run as UAC will kill it. -extra_custom_dispatch_objs = [] -if embed_uac_manifest - uac_exe_pkg = 'gobject' - uac_exe_name = 'custom-dispatch' - - # Well, we have to forgo the xxx.exe.manifest in the output listing, since - # compile_resources doesn't like to consume targets with multiple outputs, - # and the xxx.exe.manifest and xxx.rc are tied together - uac_rc = custom_target( - '@0@.rc'.format(uac_exe_name), - output: ['@0@.rc'.format(uac_exe_name)], - command: [gen_uac_manifest, - '-p=@0@'.format(uac_exe_pkg), - '-n=@0@'.format(uac_exe_name), - '--pkg-version=@0@'.format(meson.project_version()), - '--output-dir=@OUTDIR@'], - ) - extra_custom_dispatch_objs = import('windows').compile_resources(uac_rc) -endif - gobject_tests = { 'notify-init' : {}, 'notify-init2' : {}, - 'custom-dispatch' : { - 'extra_objs' : extra_custom_dispatch_objs, - }, + 'custom-dispatch' : {}, 'qdata' : {}, 'accumulator' : { 'source' : ['accumulator.c', marshalers_h, marshalers_c], @@ -178,13 +153,12 @@ test_env = environment() 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, libgobject_dep] +test_deps = [libm, thread_dep, libglib_dep, libgobject_dep, app_profile_dep] test_cargs = ['-DG_LOG_DOMAIN="GLib-GObject"', '-UG_DISABLE_ASSERT', warning_sign_conversion_args] test_cpp_args = test_cargs foreach test_name, extra_args : gobject_tests source = extra_args.get('source', test_name + '.c') - extra_objs = extra_args.get('extra_objs', []) install = installed_tests_enabled and extra_args.get('install', true) if install @@ -201,7 +175,7 @@ foreach test_name, extra_args : gobject_tests ) endif - exe = executable(test_name, source, extra_objs, + exe = executable(test_name, source, c_args : test_cargs + extra_args.get('c_args', []), cpp_args : test_cpp_args + extra_args.get('cpp_args', []), dependencies : test_deps + extra_args.get('dependencies', []), diff --git a/gobject/tests/performance/meson.build b/gobject/tests/performance/meson.build index 0147f7c85e79c517c449116eb79207513ddbb8ac..ae1a2094338cdee7efe744546a2b023c665e343e 100644 --- a/gobject/tests/performance/meson.build +++ b/gobject/tests/performance/meson.build @@ -11,7 +11,7 @@ test_env = environment() 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, libgobject_dep] +test_deps = [libm, thread_dep, libglib_dep, libgobject_dep, app_profile_dep] test_cargs = ['-DG_LOG_DOMAIN="GLib-GObject"', '-UG_DISABLE_ASSERT'] foreach test_name, extra_args : gobject_tests diff --git a/gthread/gthread.rc.in b/gthread/gthread.rc.in deleted file mode 100644 index 9e45fdff9581f55c2e2f68efc56d2e52208dd8b1..0000000000000000000000000000000000000000 --- a/gthread/gthread.rc.in +++ /dev/null @@ -1,30 +0,0 @@ -#include - -VS_VERSION_INFO VERSIONINFO - FILEVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0 - PRODUCTVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0 - FILEFLAGSMASK 0 - FILEFLAGS 0 - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN - BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "The GLib developer community" - VALUE "FileDescription", "GThread" - VALUE "FileVersion", "@GLIB_VERSION@.0" - VALUE "InternalName", "libgthread-2.0-@LT_CURRENT_MINUS_AGE@" - VALUE "LegalCopyright", "Copyright 1995-2011 Peter Mattis, Spencer Kimball, Josh MacDonald, Sebastian Wilhelmi and others." - VALUE "OriginalFilename", "libgthread-2.0-@LT_CURRENT_MINUS_AGE@.dll" - VALUE "ProductName", "GLib" - VALUE "ProductVersion", "@GLIB_VERSION@" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END - END diff --git a/gthread/meson.build b/gthread/meson.build index 9b492eed64eb24d7ffad73d16aa9a085485d5cee..62fbe47fb51601149088fef021d250d09fb97d07 100644 --- a/gthread/meson.build +++ b/gthread/meson.build @@ -3,13 +3,21 @@ gthread_sources = ['gthread-impl.c'] if host_system == 'windows' and glib_build_shared - gthread_win_rc = configure_file( - input: 'gthread.rc.in', + gthread_rc_conf = configuration_data({ + 'NAME': 'GThread', + 'FILENAME': (cc.get_argument_syntax() == 'msvc' ? '' : 'lib') + 'gthread-' + glib_api_version + '-' + soversion.to_string() + '.dll', + 'DESCRIPTION': 'Portable threading API', + }) + gthread_rc_conf.merge_from(rc_conf_base) + lib_rc = configure_file( + input: lib_rc_in, output: 'gthread.rc', - configuration: glibconfig_conf, + configuration: gthread_rc_conf, ) - gthread_win_res = windows.compile_resources(gthread_win_rc) - gthread_sources += [gthread_win_res] + gthread_sources += [windows.compile_resources(lib_rc, + # Workaround for https://github.com/llvm/llvm-project/issues/63426 + args: ['-c', '65001'], + )] endif libgthread = library('gthread-2.0', diff --git a/gthread/tests/meson.build b/gthread/tests/meson.build index 66b50caf76b7907563757623d44c2db6e7640c6f..ebb67929c95f74740426324357de2103c5633e1e 100644 --- a/gthread/tests/meson.build +++ b/gthread/tests/meson.build @@ -6,7 +6,7 @@ test_env = environment() test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) -test_deps = [thread_dep, libglib_dep, libgthread_dep] +test_deps = [thread_dep, libglib_dep, libgthread_dep, app_profile_dep] test_cargs = ['-DG_LOG_DOMAIN="GLib-GThread"', '-UG_DISABLE_ASSERT', warning_sign_conversion_args] test_cpp_args = test_cargs diff --git a/meson.build b/meson.build index f30ca58066951c8c7a92ce37c707d309b1a00d77..f6b9f5135d1d5bdb37bf7f936fcf10444d49711e 100644 --- a/meson.build +++ b/meson.build @@ -2717,6 +2717,7 @@ pkg = import('pkgconfig') windows = import('windows') gnome = import('gnome') +subdir('build-aux') subdir('tools') subdir('glib') subdir('gobject') diff --git a/tools/generate-uac-manifest.py b/tools/generate-uac-manifest.py deleted file mode 100644 index a99f0a92f781c337f20743cbad53e7f2473bcddd..0000000000000000000000000000000000000000 --- a/tools/generate-uac-manifest.py +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright © 2021 Chun-wei Fan. -# -# SPDX-License-Identifier: LGPL-2.1-or-later -# -# Original author: Chun-wei Fan - -""" -This script generates a Windows manifest file and optionally a resource file to -determine whether a specified program requires UAC elevation -""" - -import os -import argparse - -DOMAIN_NAME = "gnome" - - -def main(): - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument( - "-p", "--package", required=True, help="package name of the executable" - ) - parser.add_argument("-n", "--name", required=True, help="name of executable") - parser.add_argument( - "--pkg-version", required=True, dest="version", help="version of package" - ) - parser.add_argument( - "--require-admin", - action="store_true", - dest="admin", - default=False, - help="require admin access to application", - ) - parser.add_argument( - "--input-resource-file", - dest="resource", - default=None, - help="existing .rc file to embed UAC manifest (do not generate a new .rc file), must have included windows.h in it", - ) - parser.add_argument( - "--output-dir", - dest="outdir", - default=None, - help="directory to output resulting files", - ) - args = parser.parse_args() - - if args.resource is not None: - if not os.path.isfile(args.resource): - raise FileNotFoundError( - "Specified resource file '%s' does not exist" % args.resource - ) - - generate_manifest(args.package, args.name, args.version, args.admin, args.outdir) - write_rc_file(args.name, args.resource, args.outdir) - - -def generate_manifest(package, name, version, admin, outdir): - if version.count(".") == 0: - manifest_package_version = version + ".0.0.0" - elif version.count(".") == 1: - manifest_package_version = version + ".0.0" - elif version.count(".") == 2: - manifest_package_version = version + ".0" - elif version.count(".") == 3: - manifest_package_version = version - else: - parts = version.split(".") - manifest_package_version = "" - for x in (0, 1, 2, 3): - if x == 0: - manifest_package_version += parts[x] - else: - manifest_package_version += "." + parts[x] - - if outdir is not None: - output_file_base_name = os.path.join(outdir, name) - else: - output_file_base_name = name - - outfile = open(output_file_base_name + ".exe.manifest", "w+") - outfile.write("\n") - outfile.write( - "\n" - ) - outfile.write(" \n") - outfile.write(" \n") - outfile.write(" \n") - outfile.write(" \n") - outfile.write(" \n") - outfile.write(" \n") - outfile.write(" \n") - outfile.write(" \n") - outfile.write("\n") - outfile.close() - - -def write_rc_file(name, resource, outdir): - if outdir is not None: - output_file_base_name = os.path.join(outdir, name) - else: - output_file_base_name = name - - if resource is None: - outfile = open(output_file_base_name + ".rc", "w+") - outfile.write("#define WIN32_LEAN_AND_MEAN\n") - outfile.write("#include \n") - else: - if resource != output_file_base_name + ".rc": - outfile = open(output_file_base_name + ".rc", "w+") - else: - outfile = open(output_file_base_name + ".final.rc", "w+") - srcfile = open(resource, "r") - outfile.write(srcfile.read()) - srcfile.close() - - outfile.write("\n") - outfile.write( - 'CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "%s.exe.manifest"' % name - ) - outfile.close() - - -if __name__ == "__main__": - main() diff --git a/tools/meson.build b/tools/meson.build index 257312ebf93fc6c04aa4ecd503cef4181b4bff69..e80d4be982541072840dbb285f4caca8c02fba6c 100644 --- a/tools/meson.build +++ b/tools/meson.build @@ -24,11 +24,3 @@ if host_system != 'windows' endif gen_visibility_macros = find_program('gen-visibility-macros.py') - -# This is only needed for 32-bit (x86) Windows builds -if host_system == 'windows' and host_machine.cpu_family() == 'x86' - embed_uac_manifest = true - gen_uac_manifest = find_program('generate-uac-manifest.py') -else - embed_uac_manifest = false -endif