package: gcc-arm-none-eabi
Hi,
I can confirm this bug is still reproducible on current Ubuntu (26.04) with
a
newer toolchain. The same root cause documented here is hit by our CI build
of
an embedded firmware project (STM32 Cortex-M, libudpard/cyphal based)
whenever
the code uses the base-64-bit format macros from <inttypes.h>.
Environment:
$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (15:14.2.rel1-1) 14.2.1 20241119
$ grep PRETTY /etc/os-release
PRETTY_NAME="Ubuntu 26.04 LTS"
Minimal reproducer (test.c):
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
int main(void){ uint64_t x = 0x0123456789abcdefULL; printf("%016" PRIx64
"\n", x); return 0; }
Compile with the same flags we use for firmware:
$ arm-none-eabi-gcc -std=c2x -Werror -mthumb -mcpu=cortex-m7 -c test.c
test.c: In function 'main':
test.c:4:66: error: expected ')' before 'PRIx64'
4 | ... printf("%016" PRIx64 ...
| ^~~~~~~
test.c:4:1: note: 'PRIx64' is defined in header '<inttypes.h>'; this is
probably fixable by adding '#include <inttypes.h>'
(The compiler suggestion is misleading: PRIx64 IS defined in inttypes.h but
only conditionally.)
Root cause is exactly as described above: the header search picks up GCC's
own self-contained <stdint.h> ahead of the newlib one:
$ arm-none-eabi-gcc -E -v -x c /dev/null 2>&1 | sed -n "/#include <...>
search/,/End of search list/p"
/usr/lib/gcc/arm-none-eabi/14.2.1/include
/usr/lib/gcc/arm-none-eabi/14.2.1/include-fixed
/usr/lib/gcc/arm-none-eabi/14.2.1/../../../arm-none-eabi/include
so `#include <stdint.h>` resolves to
/usr/lib/gcc/arm-none-eabi/14.2.1/include/stdint.h (guarded by
`_GCC_STDINT_H`), which does not include_next <stdint.h>. newlib's
`sys/_stdint.h` (which defines `__int64_t_defined` at line 63) is therefore
never reached, and `/usr/include/newlib/inttypes.h` gates all the
PRI64/SCN64
macros behind `#if __int64_t_defined` at line 216, so none of them are
emitted.
Confirming the include resolution:
$ printf "#include <stdint.h>\n" | arm-none-eabi-gcc -MM -H -x c -o
/dev/null -
. /usr/lib/gcc/arm-none-eabi/14.2.1/include/stdint.h
Workaround, for other people hitting the same CI failure: we chain GCC's
stdint.h into newlib's by appending `#include_next <stdint.h>` to
$(arm-none-eabi-gcc -print-file-name=include/stdint.h), which restores the
behavior of the old wrapper and makes PRIx64/PRId64/PRIu64 all compile.
It would be great if the packaging could either restore the `#include_next
<stdint.h>` wrapper that Debian's `provide-stdint-for-embedded` used to
carry,
or coordinate with libnewlib so that `inttypes.h` does not depend on a macro
that only newlib's own <stdint.h> can define.
Thanks for the excellent analysis already in this bug; please let me know if
you need anything else reproduced.
*Erik Rainey*
[email protected]