From ec2e879e0dee15251a973d5d3c4b3e338ae26321 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Mon, 16 Jun 2025 18:49:36 +0200 Subject: [PATCH 1/6] Meson: Add comment about atomic ops on Windows --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index cc13180ba..dbffd8ae9 100644 --- a/meson.build +++ b/meson.build @@ -733,7 +733,7 @@ endforeach extra_link_args += pthread_link_args # Atomics are an optional feature in C11. Also need to check that C11 atomics are lock free. -# Windows can't use C11 atomics as some files are compiled with C++. +# On Windows we use the Interlocked family of functions if host_machine.system() != 'windows' if cc.links(files('meson-cc-tests/atomic-ops-c11.c'), name: 'Atomic ops: c11') conf.set('HAVE_C11_ATOMIC_PRIMITIVES', 1) From ff4f2f43017ecced24530f1a4593c2acccb075fc Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Mon, 16 Jun 2025 18:50:13 +0200 Subject: [PATCH 2/6] Win32: Implement init_once with InitOnceBeginInitialize / InitOnceComplete --- src/cairo-atomic-private.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/cairo-atomic-private.h b/src/cairo-atomic-private.h index 32cf58b63..d22d79e89 100644 --- a/src/cairo-atomic-private.h +++ b/src/cairo-atomic-private.h @@ -484,6 +484,36 @@ _cairo_atomic_ptr_cmpxchg_return_old_fallback(cairo_atomic_intptr_t *x, void *ol (void) ret__; \ } while (0) +#if defined (_WIN32) + +typedef INIT_ONCE cairo_atomic_once_t; +#define CAIRO_ATOMIC_ONCE_INIT INIT_ONCE_STATIC_INIT + +static cairo_always_inline cairo_bool_t +_cairo_atomic_init_once_enter(cairo_atomic_once_t *once) +{ + BOOL pending; + + if (unlikely (!InitOnceBeginInitialize (once, 0, &pending, NULL))) { + assert (0 && "InitOnceBeginInitialize failed"); + } + + if (likely (!pending)) + return 0; + + return 1; +} + +static cairo_always_inline void +_cairo_atomic_init_once_leave(cairo_atomic_once_t *once) +{ + if (unlikely (InitOnceComplete (once, 0, NULL))) { + assert (0 && "InitOnceComplete failed"); + } +} + +#else + typedef cairo_atomic_int_t cairo_atomic_once_t; #define CAIRO_ATOMIC_ONCE_UNINITIALIZED (0) @@ -515,6 +545,8 @@ _cairo_atomic_init_once_leave(cairo_atomic_once_t *once) assert (0 && "incorrect use of _cairo_atomic_init_once API (once != CAIRO_ATOMIC_ONCE_INITIALIZING)"); } +#endif /* !_WIN32 */ + CAIRO_END_DECLS #endif From 6989158f4cb06ef59f69380002f1c09e2a81c21e Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Mon, 16 Jun 2025 18:52:39 +0200 Subject: [PATCH 3/6] Drop support for very old GCC versions They don't support C11 anyway. Additionally, CLang defines a very conservative __GNUC__ value (which is also configurable via the -fgnuc-version= command-line argument) --- boilerplate/cairo-boilerplate.h | 2 +- src/cairo-compiler-private.h | 27 +++++++++++------------- src/cairo.h | 2 +- src/cairoint.h | 2 +- util/cairo-script/cairo-script-private.h | 6 +++--- util/cairo-trace/trace.c | 6 +++--- 6 files changed, 21 insertions(+), 24 deletions(-) diff --git a/boilerplate/cairo-boilerplate.h b/boilerplate/cairo-boilerplate.h index 736534eaf..4ecf575da 100644 --- a/boilerplate/cairo-boilerplate.h +++ b/boilerplate/cairo-boilerplate.h @@ -73,7 +73,7 @@ #define CAIRO_BOILERPLATE_DEBUG(x) #endif -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#if defined (__GNUC__) #ifdef __MINGW32__ #define CAIRO_BOILERPLATE_PRINTF_FORMAT(fmt_index, va_index) \ __attribute__((__format__(__MINGW_PRINTF_FORMAT, fmt_index, va_index))) diff --git a/src/cairo-compiler-private.h b/src/cairo-compiler-private.h index 28455f99d..a6ce2a8b8 100644 --- a/src/cairo-compiler-private.h +++ b/src/cairo-compiler-private.h @@ -54,7 +54,7 @@ #define CAIRO_STACK_ARRAY_LENGTH(T) (CAIRO_STACK_BUFFER_SIZE / sizeof(T)) -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#if defined (__GNUC__) #ifdef __MINGW32__ #define CAIRO_PRINTF_FORMAT(fmt_index, va_index) \ __attribute__((__format__(__MINGW_PRINTF_FORMAT, fmt_index, va_index))) @@ -67,8 +67,8 @@ #endif #define CAIRO_HAS_HIDDEN_SYMBOLS 1 -#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && \ - (defined(__ELF__) || defined(__APPLE__)) && \ +#if defined(__GNUC__) && \ + (defined(__ELF__) || defined(__APPLE__)) && \ !defined(__sun) #define cairo_private_no_warn __attribute__((__visibility__("hidden"))) #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) @@ -97,7 +97,7 @@ indicating that the old function has been deprecated by the new function. */ -#if __GNUC__ >= 2 && defined(__ELF__) +#if defined (__GNUC__) && defined(__ELF__) # define CAIRO_FUNCTION_ALIAS(old, new) \ extern __typeof (new) old \ __asm__ ("" #old) \ @@ -126,17 +126,21 @@ * constant-folding, with 'cairo_const 'also guaranteeing that pointer contents * do not change across the function call. */ -#if __GNUC__ >= 3 +#if defined (__GNUC__) #define cairo_pure __attribute__((pure)) #define cairo_const __attribute__((const)) #define cairo_always_inline inline __attribute__((always_inline)) +#elif defined (_MSC_VER) +#define cairo_pure +#define cairo_const +#define cairo_always_inline __forceinline #else #define cairo_pure #define cairo_const #define cairo_always_inline inline #endif -#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) +#if defined(__GNUC__) && defined(__OPTIMIZE__) #define likely(expr) (__builtin_expect (!!(expr), 1)) #define unlikely(expr) (__builtin_expect (!!(expr), 0)) #else @@ -144,7 +148,7 @@ #define unlikely(expr) (expr) #endif -#ifndef __GNUC__ +#if !defined(__GNUC__) #undef __attribute__ #define __attribute__(x) #endif @@ -161,18 +165,11 @@ #define strdup _strdup #define unlink _unlink #if _MSC_VER < 1900 - #define vsnprintf _vsnprintf + #define vsnprintf _vsnprintf // TODO #define snprintf _snprintf #endif #endif -#ifdef _MSC_VER -#ifndef __cplusplus -#undef inline -#define inline __inline -#endif -#endif - #if defined(_MSC_VER) && defined(_M_IX86) /* When compiling with /Gy and /OPT:ICF identical functions will be folded in together. The CAIRO_ENSURE_UNIQUE macro ensures that a function is always unique and diff --git a/src/cairo.h b/src/cairo.h index 89e4a070e..d53cc3d09 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -53,7 +53,7 @@ #if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(CAIRO_WIN32_STATIC_BUILD) # define _cairo_export __declspec(dllexport) # define _cairo_import __declspec(dllimport) -#elif defined(__GNUC__) && (__GNUC__ >= 4) +#elif defined(__GNUC__) # define _cairo_export __attribute__((__visibility__("default"))) # define _cairo_import #else diff --git a/src/cairoint.h b/src/cairoint.h index be1a4ba2a..b18a579be 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -175,7 +175,7 @@ do { \ static inline int cairo_const _cairo_popcount (uint32_t mask) { -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#if defined (__GNUC__) return __builtin_popcount (mask); #else register int y; diff --git a/util/cairo-script/cairo-script-private.h b/util/cairo-script/cairo-script-private.h index 96f9248d5..74ede82f5 100644 --- a/util/cairo-script/cairo-script-private.h +++ b/util/cairo-script/cairo-script-private.h @@ -98,7 +98,7 @@ #endif -#if __GNUC__ >= 3 +#if defined (__GNUC__) #define csi_pure __attribute__((pure)) #define csi_const __attribute__((const)) #else @@ -106,7 +106,7 @@ #define csi_const #endif -#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) +#if defined(__GNUC__) && defined(__OPTIMIZE__) #define _CSI_BOOLEAN_EXPR(expr) \ __extension__ ({ \ int _csi_boolean_var_; \ @@ -133,7 +133,7 @@ (type *)((char *) (ptr) - (char *) &((type *)0)->member) #endif -#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun) +#if defined(__GNUC__) && defined(__ELF__) && !defined(__sun) #define csi_private_no_warn __attribute__((__visibility__("hidden"))) #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) #define csi_private_no_warn __hidden diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c index 8bdb3f881..9b7a83370 100644 --- a/util/cairo-trace/trace.c +++ b/util/cairo-trace/trace.c @@ -100,7 +100,7 @@ */ #define CAIRO_BITSWAP8(c) ((((c) * 0x0802LU & 0x22110LU) | ((c) * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16) -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#if defined(__GNUC__) #ifdef __MINGW32__ #define CAIRO_PRINTF_FORMAT(fmt_index, va_index) \ __attribute__((__format__(__MINGW_PRINTF_FORMAT, fmt_index, va_index))) @@ -143,7 +143,7 @@ static void *_dlhandle = RTLD_NEXT; #endif #define BUCKET(b, ptr) (((uintptr_t) (ptr) >> PTR_SHIFT) % ARRAY_LENGTH (b)) -#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) +#if defined(__GNUC__) && defined(__OPTIMIZE__) #define _BOOLEAN_EXPR(expr) \ __extension__ ({ \ int _boolean_var_; \ @@ -220,7 +220,7 @@ static void _init_trace (void); #define INIT_TRACE_ONCE() pthread_once (&once_control, _init_trace) -#if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun) +#if defined(__GNUC__) && defined(__ELF__) && !defined(__sun) # define _enter_trace() INIT_TRACE_ONCE () # define _exit_trace() do { } while (0) # define _should_trace() 1 From cc51930a32b5bc69f1c73080991f0d0512cfbae6 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Mon, 16 Jun 2025 18:58:00 +0200 Subject: [PATCH 4/6] Meson: Add arguments for both C and C++ compilation C++ compilation is used on Windows --- meson.build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index dbffd8ae9..7e279a2f4 100644 --- a/meson.build +++ b/meson.build @@ -76,7 +76,7 @@ if cc.get_id() != 'msvc' endif supported_cflags = cc.get_supported_arguments(cflags) - add_project_arguments(supported_cflags, language: 'c') + add_project_arguments(supported_cflags, language: ['c', 'cpp']) # We only wish to enable attribute(warn_unused_result) if we can prevent # gcc from generating thousands of warnings about the misapplication of the @@ -95,10 +95,10 @@ if cc.get_id() == 'msvc' add_project_arguments('/wd4244', '/wd4146', # Don't warn about double -> float truncation '/wd4305', - language : 'c') + language : ['c', 'cpp']) endif -add_project_arguments('-D_GNU_SOURCE', language: 'c') +add_project_arguments('-D_GNU_SOURCE', language: ['c', 'cpp']) pkgmod = import('pkgconfig') python3 = import('python').find_installation() From 481c6c78bd1914be64acf40633e3b0ff88649538 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Mon, 16 Jun 2025 19:01:58 +0200 Subject: [PATCH 5/6] Meson: Suppress warning C5286 on MSVC This happens when converting _cairo_status to _cairo_int_status: warning C5286: implicit conversion from enum type '_cairo_int_status' to enum type '_cairo_status'; use an explicit cast to silence this warning --- meson.build | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meson.build b/meson.build index 7e279a2f4..4ac5701d0 100644 --- a/meson.build +++ b/meson.build @@ -95,6 +95,8 @@ if cc.get_id() == 'msvc' add_project_arguments('/wd4244', '/wd4146', # Don't warn about double -> float truncation '/wd4305', + # Don't warn about _cairo_status -> _cairo_int_status conversion + '/wd5286', language : ['c', 'cpp']) endif From 51be2591fedcb4e0a73f56d085965ffe97d47c06 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Mon, 16 Jun 2025 19:10:07 +0200 Subject: [PATCH 6/6] Meson: Define _CRT_SECURE_NO_WARNINGS when compiling with MSVC --- meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/meson.build b/meson.build index 4ac5701d0..ee2a4e70b 100644 --- a/meson.build +++ b/meson.build @@ -98,6 +98,7 @@ if cc.get_id() == 'msvc' # Don't warn about _cairo_status -> _cairo_int_status conversion '/wd5286', language : ['c', 'cpp']) + add_project_arguments('-D_CRT_SECURE_NO_WARNINGS', language : ['c', 'cpp']) endif add_project_arguments('-D_GNU_SOURCE', language: ['c', 'cpp'])