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