From 0a386dbe6cf14d76f39a735edf30d4ba5a19e1cc Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 20 Jun 2022 13:18:14 -0400 Subject: [PATCH] build: make Zephyr stdint convention enforcing configurable There are few cases where removing this enforcement is desirable: - linking against binary C++ libs with incompatible type mangling - linking against system provided headers i.e. native_posix - compiling with legacy code that assumes a different convention So let's create a Kconfig symbol for it. This is IMHO a good compromize compared to using the %"PRId32" abomination everywhere otherwise. Signed-off-by: Nicolas Pitre --- CMakeLists.txt | 5 +---- Kconfig.zephyr | 16 ++++++++++++++++ include/zephyr/kernel.h | 8 ++++++++ include/zephyr/toolchain/gcc.h | 13 +++++++++++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4865e3557a8..c6574ca191c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -283,10 +283,7 @@ zephyr_compile_options($<$:$ # @Intent: Enforce standard integer type correspondence to match Zephyr usage. # (must be after compiler specific flags) -if(NOT CONFIG_ARCH_POSIX) - # `zephyr_stdint.h` is not included for the POSIX (native) arch because it - # compiles with the host toolchain/headers and there can be conflicts if we - # arbitrarily redefine our own type system (see #37718). +if(CONFIG_ENFORCE_ZEPHYR_STDINT) zephyr_compile_options("SHELL: $ ${ZEPHYR_BASE}/include/zephyr/toolchain/zephyr_stdint.h") endif() diff --git a/Kconfig.zephyr b/Kconfig.zephyr index 0cf29caac12..411f1dd153f 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -608,6 +608,22 @@ config WARN_EXPERIMENTAL Print a warning when the Kconfig tree is parsed if any experimental features are enabled. +config ENFORCE_ZEPHYR_STDINT + bool + prompt "Enforce Zephyr convention for stdint" + depends on !ARCH_POSIX + default y + help + This enforces the Zephyr stdint convention where int32_t = int, + int64_t = long long, and intptr_t = long so that short string + format length modifiers can be used universally across ILP32 + and LP64 architectures. Sometimes this is not possible e.g. when + linking against a binary-only C++ library whose type mangling + is incompatible with the Zephyr convention, or if the build + environment doesn't allow such enforcement, in which case this + should be turned off with the caveat that argument type validation + on Zephyr code will be skipped. + endmenu diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index 6c2891d7846..57d0ed6d7eb 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -25,6 +25,14 @@ extern "C" { #endif +/* + * Zephyr currently assumes the size of a couple standard types to simplify + * print string formats. Let's make sure this doesn't change without notice. + */ +BUILD_ASSERT(sizeof(int32_t) == sizeof(int)); +BUILD_ASSERT(sizeof(int64_t) == sizeof(long long)); +BUILD_ASSERT(sizeof(intptr_t) == sizeof(long)); + /** * @brief Kernel APIs * @defgroup kernel_apis Kernel APIs diff --git a/include/zephyr/toolchain/gcc.h b/include/zephyr/toolchain/gcc.h index c0acdb54f0a..bb5e3cc0b1d 100644 --- a/include/zephyr/toolchain/gcc.h +++ b/include/zephyr/toolchain/gcc.h @@ -213,7 +213,20 @@ do { \ #define __may_alias __attribute__((__may_alias__)) #ifndef __printf_like +#ifdef CONFIG_ENFORCE_ZEPHYR_STDINT #define __printf_like(f, a) __attribute__((format (printf, f, a))) +#else +/* + * The Zephyr stdint convention enforces int32_t = int, int64_t = long long, + * and intptr_t = long so that short string format length modifiers can be + * used universally across ILP32 and LP64 architectures. Without that it + * is possible for ILP32 toolchains to have int32_t = long and intptr_t = int + * clashing with the Zephyr convention and generating pointless warnings + * as they're still the same size. Inhibit the format argument type + * validation in that case and let the other configs do it. + */ +#define __printf_like(f, a) +#endif #endif #define __used __attribute__((__used__))