Better Firmware with LLVM/Clang | Interrupt

Thanks for the response Chris. I tried that option too, still no luck. This is the console output.

~/.../example/freertos-example-llvm >>> COMPILER=clang scan-build --use-cc=/usr/bin/clang make
scan-build: Using '/usr/bin/clang-10' for static analysis
/usr/bin/../lib/clang/ccc-analyzer
===Clang Compiler Detected===
===GCC Compiler Detected===
Compiling src/builtin_scanbuild_examples.c
/home/rajah/workspace/interrupt/example/freertos-example-llvm/src/builtin_scanbuild_examples.c:11:13: warning: Dereference of null pointer (loaded from variable 'pointer')
  result += *pointer;
            ^~~~~~~~
/home/rajah/workspace/interrupt/example/freertos-example-llvm/src/builtin_scanbuild_examples.c:18:12: warning: Division by zero
    rv = 1 / denominator;
         ~~^~~~~~~~~~~~~
2 warnings generated.
Compiling src/main.c
Compiling src/memory_leak_examples.c
/home/rajah/workspace/interrupt/example/freertos-example-llvm/src/memory_leak_examples.c:11:3: warning: Attempt to free released memory
  free(ptr);
  ^~~~~~~~~
/home/rajah/workspace/interrupt/example/freertos-example-llvm/src/memory_leak_examples.c:16:12: warning: Use of memory after it is freed
    sum += ptr[i];
           ^~~~~~
/home/rajah/workspace/interrupt/example/freertos-example-llvm/src/memory_leak_examples.c:31:9: warning: Assigned value is garbage or undefined
    sum += ptr[i];
        ^  ~~~~~~
/home/rajah/workspace/interrupt/example/freertos-example-llvm/src/memory_leak_examples.c:47:12: warning: Potential leak of memory pointed to by 'ptr'
    return 1;
           ^
/home/rajah/workspace/interrupt/example/freertos-example-llvm/src/memory_leak_examples.c:65:5: warning: Attempt to free released memory
    memory_pool_free(ptr);
    ^~~~~~~~~~~~~~~~~~~~~
/home/rajah/workspace/interrupt/example/freertos-example-llvm/include/example_project/memory_pool.h:13:26: note: expanded from macro 'memory_pool_free'
#define memory_pool_free free
                         ^
/home/rajah/workspace/interrupt/example/freertos-example-llvm/src/memory_leak_examples.c:68:3: warning: Use of memory after it is freed
  memset(ptr, 0x5e, size);
  ^~~~~~~~~~~~~~~~~~~~~~~
6 warnings generated.
Compiling src/memory_pool.c
Compiling src/mutex_examples.c
Compiling src/stub_functions.c
Compiling src/freertos_lock_port.c
Compiling src/startup.c
Compiling freertos_kernel/tasks.c
Compiling freertos_kernel/queue.c
Compiling freertos_kernel/list.c
Compiling freertos_kernel/timers.c
Compiling freertos_kernel/portable/GCC/ARM_CM4F/port.c
Compiling freertos_kernel/portable/MemMang/heap_1.c
Linking library
ld.lld: error: unable to find library -lgcc
clang-10: error: ld.lld command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:148: /home/rajah/workspace/interrupt/example/freertos-example-llvm/build/nrf52.elf] Error 1
scan-build: 8 bugs found.
scan-build: Run 'scan-view /tmp/scan-build-2020-06-05-165601-6412-1' to examine bug reports.

This is the console output when I just run make. Looks like arm-none-eabi-ld/gcc is able to find gcc library.

~/.../example/freertos-example-llvm >>> make
arm-none-eabi-gcc
===GCC Compiler Detected===
Linking library
/usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/bin/ld: warning: /usr/lib/gcc/arm-none-eabi/10.1.0/thumb/v7e-m+fp/hard/libgcc.a(_udivmoddi4.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/bin/ld: warning: /usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-aeabi_memclr.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/bin/ld: warning: /usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-aeabi_memcpy.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/bin/ld: warning: /usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-malloc.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/bin/ld: warning: /usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-mallocr.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/bin/ld: warning: /usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-mlock.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/bin/ld: warning: /usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-sbrkr.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/bin/ld: warning: /usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-freer.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/bin/ld: warning: /usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-impure.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/bin/ld: warning: /usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-lock.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
/usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/bin/ld: warning: /usr/lib/gcc/arm-none-eabi/10.1.0/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-reent.o) uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
Generated build/nrf52.elf

Does clang require a separate step to install compatible libraries? I wonder if this related to Arch/linux. Do you have a linux machine or Arch VM on your end?

Thanks,
Rajah

Hi Chris,

Thanks for all your support and help. I was able to get past the gcc library issue. I added -v to linker flags in the Makefile to show the link invocation command (see below)

"/usr/bin/ld.lld" /home/rajah/workspace/interrupt/example/freertos-example- 
llvm/build/src/builtin_scanbuild_examples.o /home/rajah/workspace/interrupt/example/freertos- 
example-llvm/build/src/main.o /home/rajah/workspace/interrupt/example/freertos-example- 
llvm/build/src/memory_leak_examples.o /home/rajah/workspace/interrupt/example/freertos-example- 
llvm/build/src/memory_pool.o /home/rajah/workspace/interrupt/example/freertos-example- 
llvm/build/src/mutex_examples.o /home/rajah/workspace/interrupt/example/freertos-example- 
llvm/build/src/stub_functions.o /home/rajah/workspace/interrupt/example/freertos-example- 
llvm/build/src/freertos_lock_port.o /home/rajah/workspace/interrupt/example/freertos-example- 
llvm/build/src/startup.o /home/rajah/workspace/interrupt/example/freertos-example- 
llvm/build/freertos_kernel/tasks.o /home/rajah/workspace/interrupt/example/freertos-example- 
llvm/build/freertos_kernel/queue.o /home/rajah/workspace/interrupt/example/freertos-example- 
llvm/build/freertos_kernel/list.o /home/rajah/workspace/interrupt/example/freertos-example- 
llvm/build/freertos_kernel/timers.o /home/rajah/workspace/interrupt/example/freertos-example- 
llvm/build/freertos_kernel/portable/GCC/ARM_CM4F/port.o 
/home/rajah/workspace/interrupt/example/freertos-example- 
llvm/build/freertos_kernel/portable/MemMang/heap_1.o /usr/lib/gcc/arm-none-eabi/10.1.0/thumb/v7e- 
m+fp/hard/libgcc.a -lgcc --gc-sections -Map /home/rajah/workspace/interrupt/example/freertos- 
example-llvm/build/nrf52.map -lc -lm -Bstatic -L/usr/lib/clang/10.0.0/lib/baremetal -L/usr/arm-none- 
eabi/lib/thumb/v7e-m+fp/hard -T /home/rajah/workspace/interrupt/example/freertos-example- 
llvm/nrf52.ld -o /home/rajah/workspace/interrupt/example/freertos-example-llvm/build/nrf52.elf

From the invocation, I was able to verify that libgcc.a can be found in
/usr/lib/gcc/arm-none-eabi/10.1.0/thumb/v7e-m+fp/hard/libgcc.a

However, the -L flag to the linker only list the following search directories.
-L/usr/lib/clang/10.0.0/lib/baremetal
-L/usr/arm-none-eabi/lib/thumb/v7e-m+fp/hard

The first path does not exist on my arch system and the second one exits, but does not have libgcc.a. I copied libgcc.a from /usr/lib/gcc/arm-none-eabi/10.1.0/thumb/v7e-m+fp/hard/ to /usr/arm-none-eabi/lib/thumb/v7e-m+fp/hard. I am able to generate the elf file after this. However, I am still not sure how arm-none-eabi-gcc/ld is able to find gcc library without copying. I suspect it may have something to do with how scan-build hijacks CC in the Makefile. I hope this helps others facing similar issues.

Thanks,
Rajah

System details:
Linux 5.6.15-1-MANJARO #1 SMP PREEMPT Wed May 27 20:38:56 UTC 2020 x86_64 GNU/Linux
Clang compiler details:
clang version 10.0.0
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Clang linker details:
LLD 10.0.0 (compatible with GNU linkers)
arm-none-eabi-gcc details:
arm-none-eabi-gcc (Arch Repository) 10.1.0
arm-none-eabi-ld details:
GNU ld (GNU Binutils) 2.34

1 Like

Hi @mcrajah,

That’s great you were able to figure it out!! The path to libgcc is determined using gcc’s -print-libgcc-file-name command option described here in the article. It sounds like for your setup that may be what was failing.

Do note that the arm-none-eabi package available via pacman is not an officially supported release of ARM gcc and is usually a version ahead of the official ARM release. While it can be interesting to use that build to pre-test new compiler releases, there’s usually configuration issues and new errors that arise as a result. For projects, I’d recommend using one of the official releases available here instead.

Hi chrisc
Thank you for the good content.
Could I post this on my blog by translating the post into Korean and adding the content?

Hi @Hyunyong-Park, you’re welcome to translate and re-post the content, but you will have to attribute it to us and link back to the original. Thank you!

Thank you for the great article! :smiley_cat:
May I ask a question regarding the freertos-example-llvm from the article ?

I get the following error when I run COMILER=clang make inside the freertos-example-llvm root.

/home/lonelyjoe/workspace/embedded/interrupt/example/freertos-example-llvm/src/main.c:5:10: fatal error: 'malloc.h' file not
      found
#include <malloc.h>
         ^~~~~~~~~~
1 error generated.
Makefile:171: recipe for target '/home/lonelyjoe/workspace/embedded/interrupt/example/freertos-example-llvm/build/src/main.o' failed
make: *** [/home/lonelyjoe/workspace/embedded/interrupt/example/freertos-example-llvm/build/src/main.o] Error 1

I found out that my ARM_CORTEXM_MULTI_DIR (thumb/v7e-m/fpv4-sp/hard) neither contains libm.a nor libc.a. Still, running COMPILER=gcc make works without issues…
May I ask for tips on how to generate libm.a & libc.a for the cortex-m target ?

Thank you :slight_smile:

I setup a clean Linux install to debug this. Here’s what I found:

  1. You need to install the arm-none-eabi-gcc build from ARM rather than from the Debian package archives. The latter is missing the sysroot, which we use to find the right header files. Head to ARM’s website to download the latest. Make sure it’s on your PATH, or set the ARM_GNU_CC make variable accordingly.
  2. You haven’t run into it yet, but there’s an issue with compiler detection in our Makefile. I just fixed it here. Make sure to pull the latest.

With those two things sorted, I can build fine on Linux:

root@fbo-dev:~/interrupt/example/freertos-example-llvm# COMPILER=clang ARM_GNU_CC=~/gcc-arm-none-eabi-9-2020-q2-update/bin/arm-none-eabi-gcc make clean all
clang
===Clang Compiler Detected===
rm -rf /root/interrupt/example/freertos-example-llvm/build
Compiling src/builtin_scanbuild_examples.c
Compiling src/main.c
Compiling src/memory_leak_examples.c
Compiling src/memory_pool.c
Compiling src/mutex_examples.c
Compiling src/stub_functions.c
Compiling src/freertos_lock_port.c
Compiling src/startup.c
Compiling freertos_kernel/tasks.c
Compiling freertos_kernel/queue.c
Compiling freertos_kernel/list.c
Compiling freertos_kernel/timers.c
Compiling freertos_kernel/portable/GCC/ARM_CM4F/port.c
Compiling freertos_kernel/portable/MemMang/heap_1.c
Linking library
Generated build/nrf52.elf
1 Like

Thank you so much for your help! You’re a lifesaver!
After switching my arm-none-eabi-gcc to the one downloaded from theARM website, I can see the files libm.a and libc.a.

After that I faced an identical issue with @mcrajah (-L issue), but I was able to resolve it thanks to @mcrajah 's previous comments.

I’m just one foot away from succeeding cross-compilation with clang… :slight_smile:
Currently my lld.ld fails due to the symbol COPY in the linker file (nrf52.ld).
I’m not sure what I need to do to fix this one…

$ COMPILER=clang make
error: /home/lonelyjoe/workspace/embedded/interrupt/example/freertos-example-llvm/nrf52.ld:76: symbol not found: COPY
clang: error: ld.lld command failed with exit code 1 (use -v to see invocation)
Makefile:154: recipe for target '/home/lonelyjoe/workspace/embedded/interrupt/example/freertos-example-llvm/build/nrf52.elf' failed
make: *** [/home/lonelyjoe/workspace/embedded/interrupt/example/freertos-example-llvm/build/nrf52.elf] Error 1

Looking at the log you posted, it appears it’s the COPY directive itself that the linker fails to recognize. Could you try updating clang and lld to their latest version? Here’s what I’ve got here:

root@fbo-dev:~# clang --version
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin


root@fbo-dev:~# ld.lld --version
LLD 10.0.0 (compatible with GNU linkers)

Alternatively you should be able to change that section to NOLOAD rather than COPY at line 76 of nrf52.ld (though @chrisc can correct me if I’m wrong).

Edit: By the way, the libgcc issue @mcrajah was talking about is due to the compiler detection bug I fixed at Fix llvm example on Linux · memfault/interrupt@2bd1eb5 · GitHub. If you’re seeing both “GCC compiler detected” and “Clang compiler detected” in the output, there’s a problem!

1 Like

After updating clang & ld.lld to version 10.0.0,
finally my build succeeds! Thank you so much for your help!! :smiley_cat:

I was seeing both “GCC compiler detected” and “Clang compiler detected”, but I fixed it by cloning to the latest version of the repo! Thank you :wink:

1 Like

I tried to implement this all as a CMake config as a cmake skill-builder & to explore the described benefits of transitioning to clang/llvm.
But I encountered a problem that it seems like no one else has mentioned: I was getting a lot of undefined symbols until I included explicit linking against crt0.o, crti.o, crtbegin.o, and crtend.o.

So, I must have an option or flag wrong or missing, given how roundabout my solution is. Doing the build “manually” at the command line needed the same objects added in.
Is this an expected pitfall?
Here’s my minimum working example: https://github.com/apullin/clang_min_fw
with the additions in ${CRT_SUPPORT_ROOT} and ${CRT_SUPPORT_LINK}.

Any insight into what I am missing?

Hi @apullin, one idea would be to try would be adding --ffunction-sections & --fdata-sections to your compiler flags. Without these flags, unused dependencies will get pulled into your build and could be the cause of the undefined symbol errors you were seeing.

I worked on LLVM professionally back when there was just llvm-gcc and no Clang, and for several years after Clang was released. LLVM has been quite capable of lots of things people don’t even attempt for years; llvm IR was originally meant to be cross-processor, and you can generally build a project with processor features disabled to prevent intrinsic generation as IR, then lower to machine code for any supported architecture with the same data sizes (it may have additional / different ones as long as it has the maximum sized integer and float that you built against) given a platform with a compatible C library. This isn’t recommended or necessarily a good idea, but I’ve taken C code compiled to IR built against armv5tej-linux-eabi and lowered it to all of windows-x86_64, darwin-ppc, android-arm, linux-x86, and ios-arm and it remained functional and ran without errors after forcibly lowering to the wrong platform / architecture… Not super useful but kinda neat. Apple requires app store MachO submissions to include bitcode as another multiarch so they can verify code more easily and presumably so they can do new optimized builds for minor arch changes and compiler updates.

A lot of times, due to compiler flags differing in behavior (as seen in previous posts here), people give up or assume LLVM is producing bad code… there are at least 3 bugs I saw on the dev list today complaining about bad optimization compared to GCC where the entire problem could be fixed using -Os or -Oz instead of -O3, because llvm O3 is like telling it, “the target machine has effectively unlimited RAM and icache, spew all the assembly you want if it has any benefit”, which often creates large bizarre looking constructs that execute quickly because of pipelining / processor rules that are non-obvious. This is one of those situations where assembly is kind of all or nothing, and unless you’ve read the thousands of pages of architecture guides and timing like me and similarly pedantic asses who have worked on or currently work on the backends, you’re better off not second guessing the compiler without profiling code at the very least.

One strange example is 3.7.2 in the intel optimization manual where instead of:
mov eax, [ebx +4]
mov ecx, 60
…to set up a loop scanning a list,
mov eax, [ebx +4]
mov eax, [ebx +4]
mov eax, [ebx +4]
mov ecx, 60

Is preferred in most cases on Core architectures because it triggers hardware L1 prefetch on the rest of the data. At first glance this code would look like a compiler error to most sane people, including me if I hadn’t read that manual before, but the 3x duplicated instruction forces insanely fast background prefetch and is safe to do 90% of the time. With constrained hardware (a different processor architecture with wider variance between the high end and embedded procs with a similar optimization, maybe), it might be more important to get rid of the extra instructions with -Oz because you’re working within 128k of flash and the extra speed during your hardware init sequence doesn’t matter. I saw a bug filed today about redundant loads that made me think of this. It was very likely an instance of this optimization or a related one.

Another example was a bug filed about REP MOVSB being selected instead of the wider versions (REP STOSD/Q) with GCC output being given as the example of doing it right… The problem is that GCC is wrong on Ivy Bridge and up; there’s a processor fast path for REP MOVSB and STOSB that makes them universally faster than STOSD and as fast or faster than AVX / AVX2 on copies over 128 bytes. Intel recommends never using rep movsd with movsb to finish mod 4 leftovers for memcpy, and only to use AVX for very short copies now. AVX is faster for those because enhanced rep movsb has startup overhead that isn’t amortized with avx register copying until the 128 byte range. Technically both compilers in the “bug” should have conditionally used AVX based on data size, but it has its own problems on Haswell-E / Broadwell-E / Skylake like dynamic TurboBoost upper speed limit dropping by 200mhz by default on the core or chip when executed that can make it more costly than expected. GCC either defaults to some ancient target processor or doesn’t know about this at all. Now if you didn’t read all that, you’d think copying data as bytes would be the slowest way to do things (and it would using mov reg, [mem]; mov [mem], reg loops for a couple of reasons) but processor architectures can be weird and you’ll have things like that.

There’s another where micro-op fusion occurs with test / jcc but not cmp / jcc, etc.

The whole point there is that even though I liked reading through Intel / ARM / PPC manuals at one point in time and would have contributed to an open source compiler if I had something to contribute, it never would have been to a GPL3 project. Getting paid wasn’t enough to make me submit an instruction encoding fix patch to GAS for ARM, I just flat-out refused (i could get away with a lot as the only person there who could read and write assembly and the compiler backends fluently for every architecture we supported) and then converted our arm-linux-eabi toolchain to clang in a few days instead and got the company to ditch gcc across every supported platform over the next several months after proving it would work in that one.

That was my initiative, not some corporate doesn’t want to release source thing. They’d have gladly submitted patches to gcc/gas forever instead, but I never wanted to have to look at GAS again after doing so once, and already disliked the GPL, so I made absolutely sure I wouldn’t be asked to and neither would anyone else there. We required and integrated with LLVM anyway, so switching wasn’t a hard sell, it’s just that nobody had thought it was possible at that point in time. We still relied on libstdc headers from the toolchain but LGPL doesn’t morally offend me as much and my idea of forcing customers to switch to a more permissively licensed embedded OS wasn’t going to fly (mostly because they may or may not exist).

So, I was happy to see this post because firmware is one of the last holdouts where not-really-free tools must be dealt with now that clang is able to build Linux itself more or less.

Lastly, and probably of more interest here than my uarch / anti-GPL rants, anyone interested in breaking that last part of the reliance on gcc within what you’re building should look at “llvm-libc” C Standard Library — LLVM 12 documentation (source-in-progress at llvm-project/libc at main · llvm/llvm-project · GitHub ) and see if you can contribute. They will accept pull requests from anyone after a well-defined review process. Somewhat ironically it looks as though LLVM-LIBC is being written in C++ (avoiding use of STL, it can be built standalone ), but that’s standard for the project overall aside from language bindings.

1 Like

To be clear did anyone get AddressSanitzer to work using gcc on windows host with ARM Cortex M4 target.
Especially since there is a post on the official ARM site claiming they dont support AddressSanitizer>

This post is about Clang ASan. We haven’t tried GCC’s yet. Would love to hear what people’s experience is like.

Great walkthrough. Just have some probs with c++. figured it out to add -stdlib=libstdc++ to my cxx compile flags but run into issue with not finding <bits/c++config.h>. What am I missing. really appreciate any help

FAILED: Src/CMakeFiles/Application.dir/GuiTask.cpp.obj 
/opt/homebrew/Cellar/llvm/17.0.6_1/bin/clang++ -DLV_CONF_INCLUDE_SIMPLE -DLV_LVGL_H_INCLUDE_SIMPLE -DSTM32G491xx -DUSE_FULL_LL_DRIVER -I/Users/***/git/projectXYZ/Src/Peripherals -I/Users/***/git/projectXYZ/Src/Devices -isystem /Users/***/git/projectXYZ/Src -isystem /Users/***/git/projectXYZ/ThirdParty/CMSIS/Include -isystem /Users/***/git/projectXYZ/ThirdParty/CMSIS/Device/ST/STM32G4xx/Include -isystem /Users/***/git/projectXYZ/ThirdParty/STM32G4xx_HAL_Driver/Inc -isystem /Users/***/git/projectXYZ/ThirdParty/STM32G4xx_HAL_Driver/Inc/Legacy -isystem /Users/***/git/projectXYZ/ThirdParty/lvgl-8.2.0 -isystem /Users/***/git/projectXYZ/ThirdParty/FreeRTOS-Kernel-10.4.6/include -isystem /Users/***/git/projectXYZ/ThirdParty/FreeRTOS-Kernel-10.4.6/portable/GCC/ARM_CM4F -isystem /Users/***/git/projectXYZ/ThirdParty/freertos-addons-1.6.0/c++/Source/include -fno-exceptions -fno-rtti -stdlib=libstdc++ -g -std=gnu++17 --target=arm-none-eabi -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 --sysroot=/Applications/ArmGNUToolchain/13.2.Rel1/arm-none-eabi/arm-none-eabi -MD -MT Src/CMakeFiles/Application.dir/GuiTask.cpp.obj -MF Src/CMakeFiles/Application.dir/GuiTask.cpp.obj.d -o Src/CMakeFiles/Application.dir/GuiTask.cpp.obj -c /Users/***/git/projectXYZ/Src/GuiTask.cpp
In file included from /Users/***/git/projectXYZ/Src/GuiTask.cpp:1:
In file included from /Users/***/git/projectXYZ/Src/GuiTask.hpp:7:
In file included from /Users/***/git/projectXYZ/ThirdParty/freertos-addons-1.6.0/c++/Source/include/thread.hpp:54:
In file included from /Applications/ArmGNUToolchain/13.2.Rel1/arm-none-eabi/arm-none-eabi/include/c++/13.2.1/string:38:
/Applications/ArmGNUToolchain/13.2.Rel1/arm-none-eabi/arm-none-eabi/include/c++/13.2.1/bits/requires_hosted.h:31:10: fatal error: 'bits/c++config.h' file not found
   31 | #include <bits/c++config.h>
      |          ^~~~~~~~~~~~~~~~~~
1 error generated.
ninja: build stopped: subcommand failed.
1 Like