From 4eae859ae8ad7072eaa74aeaee79a2c3c12c55cb Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Wed, 22 Jan 2025 15:03:55 +0200 Subject: [PATCH] Windows: Disable MinGW-w64's stdio functions in size-optimized builds This only affects builds with UCRT. With legacy MSVCRT, the replacement functions are always enabled. Omitting the MinGW-w64 replacements saves over 20 KiB per executable. The downside is that --enable-small or XZ_SMALL=ON disables thousand separator support in xz messages. If someone is OK with the slower speed of slightly smaller builds, lack of thousand separators won't matter. Don't override __USE_MINGW_ANSI_STDIO if it is already defined (via CPPFLAGS or such method). --- src/common/sysdefs.h | 30 +++++++++++++++++++++--------- src/xz/util.c | 6 +++++- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/common/sysdefs.h b/src/common/sysdefs.h index 7676009e..8e01bd17 100644 --- a/src/common/sysdefs.h +++ b/src/common/sysdefs.h @@ -23,17 +23,29 @@ # include #endif -// This #define ensures that C99 and POSIX compliant stdio functions are -// available with MinGW-w64 (both 32-bit and 64-bit). Modern MinGW-w64 adds -// this automatically, for example, when the compiler is in C99 (or later) -// mode when building against msvcrt.dll. It still doesn't hurt to be explicit -// that we always want this and #define this unconditionally. +// Choose if MinGW-w64's stdio replacement functions should be used. +// The default has varied slightly in the past so it's clearest to always +// set it explicitly. // -// With Universal CRT (UCRT) this is less important because UCRT contains -// C99-compatible stdio functions. It's still nice to #define this as UCRT -// doesn't support the POSIX thousand separator flag in printf (like "%'u"). -#ifdef __MINGW32__ +// Modern MinGW-w64 enables the replacement functions even with UCRT +// when _GNU_SOURCE is defined. That's good because UCRT doesn't support +// the POSIX thousand separator flag in printf (like "%'u"). Otherwise +// XZ Utils works with the UCRT stdio functions. +// +// The replacement functions add over 20 KiB to each executable. For +// size-optimized builds (HAVE_SMALL), disable the replacements. +// Then thousand separators aren't shown in xz's messages but this is +// a minor downside compare to the slower speed of the HAVE_SMALL builds. +// +// The legacy MSVCRT is pre-C99 and it's best to always use the stdio +// replacements functions from MinGW-w64. +#if defined(__MINGW32__) && !defined(__USE_MINGW_ANSI_STDIO) # define __USE_MINGW_ANSI_STDIO 1 +# include <_mingw.h> +# if defined(_UCRT) && defined(HAVE_SMALL) +# undef __USE_MINGW_ANSI_STDIO +# define __USE_MINGW_ANSI_STDIO 0 +# endif #endif // size_t and NULL diff --git a/src/xz/util.c b/src/xz/util.c index 3af5982e..e5485bee 100644 --- a/src/xz/util.c +++ b/src/xz/util.c @@ -25,7 +25,11 @@ static char bufs[4][128]; // for DJGPP builds. // // MSVC doesn't support thousand separators. -#if defined(__DJGPP__) || defined(_MSC_VER) +// +// MinGW-w64 supports thousand separators only with its own stdio functions +// which our sysdefs.h disables when _UCRT && HAVE_SMALL. +#if defined(__DJGPP__) || defined(_MSC_VER) \ + || (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) # define FORMAT_THOUSAND_SEP(prefix, suffix) prefix suffix # define check_thousand_sep(slot) do { } while (0) #else