Should gcc-arm 12.2.rel1 work?

Documentation says gcc-arm > 10.2.1 should work, but 12.2.rel1 fails to compile v5.2.0 with:

In file included from /Applications/ArmGNUToolchain/12.2.rel1/arm-none-eabi/arm-none-eabi/include/c++/12.2.1/mutex:43,
                 from ../wiring/inc/spark_wiring_system.h:40,
                 from ../wiring/inc/spark_wiring.h:49,
                 from ./inc/application.h:42,
                 from ./inc/Particle.h:5,
                 from /Users/lars/Documents/Code/quicly/particle/firmware/main.cpp:28:
/Applications/ArmGNUToolchain/12.2.rel1/arm-none-eabi/arm-none-eabi/include/c++/12.2.1/bits/std_mutex.h: In constructor 'std::__condvar::__condvar()':
/Applications/ArmGNUToolchain/12.2.rel1/arm-none-eabi/arm-none-eabi/include/c++/12.2.1/bits/std_mutex.h:135:7: error: '__GTHREAD_COND_INIT_FUNCTION' was not declared in this scope
  135 |       __GTHREAD_COND_INIT_FUNCTION(&_M_cond);
      |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Applications/ArmGNUToolchain/12.2.rel1/arm-none-eabi/arm-none-eabi/include/c++/12.2.1/bits/std_mutex.h: In destructor 'std::__condvar::~__condvar()':
/Applications/ArmGNUToolchain/12.2.rel1/arm-none-eabi/arm-none-eabi/include/c++/12.2.1/bits/std_mutex.h:141:45: error: '__gthread_cond_destroy' was not declared in this scope; did you mean '__gthread_mutex_destroy'?
  141 |       int __e __attribute__((__unused__)) = __gthread_cond_destroy(&_M_cond);
      |                                             ^~~~~~~~~~~~~~~~~~~~~~
      |                                             __gthread_mutex_destroy
/Applications/ArmGNUToolchain/12.2.rel1/arm-none-eabi/arm-none-eabi/include/c++/12.2.1/bits/std_mutex.h: In member function 'void std::__condvar::wait(std::mutex&)':
/Applications/ArmGNUToolchain/12.2.rel1/arm-none-eabi/arm-none-eabi/include/c++/12.2.1/bits/std_mutex.h:155:11: error: '__gthread_cond_wait' was not declared in this scope; did you mean '__gthread_cond_t'?
  155 |         = __gthread_cond_wait(&_M_cond, __m.native_handle());
      |           ^~~~~~~~~~~~~~~~~~~
      |           __gthread_cond_t
/Applications/ArmGNUToolchain/12.2.rel1/arm-none-eabi/arm-none-eabi/include/c++/12.2.1/bits/std_mutex.h: In member function 'void std::__condvar::notify_one()':
/Applications/ArmGNUToolchain/12.2.rel1/arm-none-eabi/arm-none-eabi/include/c++/12.2.1/bits/std_mutex.h:177:45: error: '__gthread_cond_signal' was not declared in this scope; did you mean '__gthread_cond_t'?
  177 |       int __e __attribute__((__unused__)) = __gthread_cond_signal(&_M_cond);
      |                                             ^~~~~~~~~~~~~~~~~~~~~
      |                                             __gthread_cond_t
/Applications/ArmGNUToolchain/12.2.rel1/arm-none-eabi/arm-none-eabi/include/c++/12.2.1/bits/std_mutex.h: In member function 'void std::__condvar::notify_all()':
/Applications/ArmGNUToolchain/12.2.rel1/arm-none-eabi/arm-none-eabi/include/c++/12.2.1/bits/std_mutex.h:184:45: error: '__gthread_cond_broadcast' was not declared in this scope; did you mean '__gthread_cond_timedwait'?
  184 |       int __e __attribute__((__unused__)) = __gthread_cond_broadcast(&_M_cond);
      |                                             ^~~~~~~~~~~~~~~~~~~~~~~~
      |                                             __gthread_cond_timedwait

It will not. You should use 10.2.1, the version used by the cloud compilers. The instructions really should not say “or later” particularly for major versions, which almost never work without source modifications.

Thanks for responding. The issue I see with 10.2.1 is that linking fails, because strerror is apparently defined twice. (LTO issue?)

Did you do a make clean in the modules directory, or the equivalent option in Workbench? There could be bits left from a previous compile or when switching between versions, modular/monolithic, or lto/non-lto.

I think my tree is clean. This is the error:

/usr/local/Cellar/gcc-arm-none-eabi-1021/20201103/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld: /usr/local/Cellar/gcc-arm-none-eabi-1021/20201103/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libg_nano.a(lib_a-strerror.o): in function `strerror':
strerror.c:(.text.strerror+0x0): multiple definition of `strerror'; /Users/lars/Documents/Code/quicly/particle/bin//obj/./src/newlib_stubs.o:/Users/lars/.po-util/src/particle/firmware/modules/argon/user-part/../../../modules/shared/nRF52840/inc/user-part/newlib_stubs.inc:92: first defined here

It also links if I remove strerror from modules/shared/nRF52840/inc/user-part/newlib_stubs.inc

Maybe a submodule change? You definitely should not have to modify the source to get it to build with 10.2.1.

git submodule update --init --recursive

That wasn’t it.

This error seems to happen when I call perror in my application. Removing that call fixes the linker error,

Oh, that’s the problem. The streams stdout and stderr are not supported, so you can’t printf() or perror(). I didn’t expect that error in that case.

Me neither. And I didn’t get it with earlier versions of Device OS. (The perror is in a library that I am including in my project, so it’s not so easy to eliminate without patching upstream.)

I do think this is a bug in Device OS with the 10.2.1 toolchain, because the libg_nano that comes with gcc does define strerror already:

/usr/local/Cellar/gcc-arm-none-eabi-1021/20201103/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld: /usr/local/Cellar/gcc-arm-none-eabi-1021/20201103/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libg_nano.a(lib_a-strerror.o): in function `strerror':
strerror.c:(.text.strerror+0x0): multiple definition of `strerror'; /Users/lars/Documents/Code/quicly/particle/target/argon//obj/./src/newlib_stubs.o:/Users/lars/.particle/toolchains/deviceOS/5.2.0/modules/argon/user-part/../../../modules/shared/nRF52840/inc/user-part/newlib_stubs.inc:92: first defined here

After trying to use arm-none-eabi-gcc 12 ourselves, the issue seems to be the following:

The updated newlib that comes with version 12 uses new symbols for gthread, for example
__GTHREAD_COND_INIT_FUNCTION instead of __GTHREAD_MUTEX_INIT_FUNCTION

Particle's hal defines the abstractions in this file:
device-os/hal/src/stm32/bits/gthr-default.h

These are not fully compatible with the latest newlib.

It seems that support for the P1 has stopped, so we're out of luck trying to offer long term support to our customers, while trying to keep our build system up to date for other platforms.
Another issue is the olddated nanopb lib on P1. It was recently updated for gen3, but not backported to P1.

LTS only means that it works if you keep using outdated dependencies and compilers.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.