Cross compilation of libcxx for baremetal ARMv7m with hard floating point support

Hello All,
I am trying to use the libcxx library on a bare-metal ARMv7m microcontroller with hardware floating point support. I am using llvm release 14.x.

First I tried just to build the libcxx, but I received a warning that a standalone build is deprecated in this release. So I tried to follow the guide for building the libcxx Building libc++ — libc++ documentation. Following the clang cross compilation guide (Cross-compilation using Clang — Clang 16.0.0git documentation) I have used the following CMake parameters:

cmake\
	-G Ninja \
	-B build \
	-DCMAKE_BUILD_TYPE=Release \
	-DCMAKE_INSTALL_PREFIX=/usr/local/llvm-arm-none-eabi \
	-DCMAKE_C_FLAGS="--target=armv7m-none-eabi -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb --sysroot=/usr/lib/gcc/arm-none-eabi/10.3.1/" \
	-DCMAKE_CXX_FLAGS="--target=armv7m-none-eabi -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb --sysroot=/usr/lib/gcc/arm-none-eabi/10.3.1/" \
    -DLLVM_ENABLE_RUNTIMES="compiler-rt;libcxx;libcxxabi;libunwind" \
	-DLLVM_TARGETS_TO_BUILD=ARM \
	-DLLVM_DEFAULT_TARGET_TRIPL="arm-none-eabi" \
	-DCMAKE_C_COMPILER=/usr/bin/clang \
	-DCMAKE_CXX_COMPILER=/usr/bin/clang++ \
	llvm

, but the compilation failed due to a lack of c,m, stdc++, subc++, gcc and unwind libraries. So I have provided paths to directories where those libraries can be found (updated CMAKE_C_FLAGS and CMAKE_CXX_FLAGS):

-L/usr/lib/gcc/arm-none-eabi/10.3.1/ -L/usr/lib/arm-none-eabi/newlib/

So now I am just missing unwind library. Why the build system requires this library if I have specified that I want this library to be built?

I don’t think that building the runtimes means you also get to use the runtimes on the same build, as they’re build at the same time, not one before the other.

So, to build LLVM with those runtimes, you’d need to build them first, then point the library path / sysroot to the installed libraries on the second stage.

I’m not sure why you’re not getting an unwind library, as I expect the GCC sysroot to have it’s own unwind library in there… I can’t remember if arm-none-eabi GCC has Thumb libraries, but I’d guess it does.

Cross-compiling with LLVM is always a puzzle, with mismatched pieces, unfortunately. GCC gets away with building a complete toolchain out-of-the-box, which is something we never did (because we never had all libraries, including libc and libm) to have a proper sysroot.

We now have a project to build an LLVM libc, and we already have compiler-rt, libunwind and libc++, so I’m hoping this will allow us to build a complete sysroot, including for cross-compilation.

Slightly off topic but spotted a typo LLVM_DEFAULT_TARGET_TRIPL should be LLVM_DEFAULT_TARGET_TRIPLE.

1 Like

I followed the guide (Building libc++ — libc++ documentation) which says:

It is possible to build Clang and then build the runtimes using that just-built compiler in a single CMake invocation. This is usually the correct way to build the runtimes when putting together a toolchain, or when the system compiler is not adequate to build them (too old, unsupported, etc.).

But I will try to build them one by one as you suggested.

As for the unwind library being a part of gcc arm none eabi.
I have only found unwind headers and no compiled library:

tree -f | grep arm-none-eabi.*unwind

│   │   │       │   ├── ./lib/gcc/arm-none-eabi/10.3.1/include/unwind-arm-common.h

│   │   │       │   ├── ./lib/gcc/arm-none-eabi/10.3.1/include/unwind.h

Maybe I should try to reinstall the arm-none-eabi toolchain.

Thank you for spotting that!
I fixed the typo. The result is the same unfortunately.

IIUC, you want the other way around: build the libraries and then build clang with them. That option is for building Clang first, then those libraries with the just-built clang.

Look for gcc_eh and gcc_s, IIRC, those ate the unwind runtimes.

Thank you for your answers @rengolin !

My true goal is to use the LLVM version of the C++ standard library on the ARMv7m project. I would like to compare it with the gnu C++ standard library.
As for compiling clang, do I need to compile clang if I have it already installed and clang is a cross compiler?

I found those libraries only for x86 and for arm-linux-gnueabihf. I cannot install them for arm-none-eabi using sudo apt-get install nor get any information about those libraries for arm-none-eabi while looking for it on the internet.

As you suggested, I have tried to build the libcxx library without anything else. I linked the unwind library from llvm-embedded-toolchain-for-arm (unfortunately in the soft floating point version), and I used the following CMake parameters::

cmake\
	-G Ninja \
	-B build\
	-DCMAKE_BUILD_TYPE=Release \
	-DCMAKE_INSTALL_PREFIX=/usr/local/llvm-arm-none-eabi \
	-DCMAKE_C_FLAGS="--target=armv7m-none-eabi -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb --sysroot=/usr/lib/gcc/arm-none-eabi/10.3.1/ -L/usr/lib/arm-none-eabi/newlib/ -L/usr/lib/gcc/arm-none-eabi/10.3.1 -L/usr/lib/llvm-embedded-toolchain-for-arm/lib/clang-runtimes/armv7m_soft_nofp/lib/" \
	-DCMAKE_CXX_FLAGS="--target=armv7m-none-eabi -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb --sysroot=/usr/lib/gcc/arm-none-eabi/10.3.1/ -L/usr/lib/arm-none-eabi/newlib/ -L/usr/lib/gcc/arm-none-eabi/10.3.1 -L/usr/lib/llvm-embedded-toolchain-for-arm/lib/clang-runtimes/armv7m_soft_nofp/lib/" \
	-DLLVM_ENABLE_RUNTIMES="libcxx" \
	-DLLVM_TARGETS_TO_BUILD=ARM \
	-DLLVM_DEFAULT_TARGET_TRIPLE="arm-none-eabi" \
	-DCMAKE_C_COMPILER=/usr/bin/clang \
	-DCMAKE_CXX_COMPILER=/usr/bin/clang++ \
	llvm

This time CMake complains about too old version of libstdc++ :tired_face:

CMake Error at cmake/modules/CheckCompilerVersion.cmake:98 (message):

  libstdc++ version must be at least 5.1.

Call Stack (most recent call first):

  cmake/config-ix.cmake:14 (include)

  CMakeLists.txt:732 (include)

I have installed libstdc++ for arm-none-eabi using sudo apt-get install libstdc++-arm-none-eabi it seems that this library is too old. Anyway, I wonder why gnu implementation of the C++ standard library is needed to build LLVM implementation of the standard library.

I am sorry for my noob questions. It feels like, the longer I tried to compile this library, the less I understand. What are the necessary steps and components needed to have this library compiled for ARMv7m? Has anyone ever tried to do that?

You may find multi-arch library packages in some distros, but you can also just cross-compile the libraries alone, and use those with the system clang.

You don’t need to compile your own clang, the distros provide a cross-compiler by default. You may need to compile libc++ et al and build a sysroot. Because different distros use different ways to build a sysroot, you may have to ask around other forums. @compnerd and @kraj may have some ideas.

This is just because the minimum for building LLVM has gone up over the years, with increasing support for more modern C++ features. Your host system seems too old to have the appropriate packages. Can you upgrade your system? Or get a container with a more recent Debian/Ubuntu?

Surprisingly, these are not noob questions. Because each combination of micro-arch / OS / toolchain does it slightly different (and LLVM wants to cater to them all), it’s always a mess. I don’t know in Arm who’s working with M-class nowadays, but @kbeyls or @smithp35 may be able to redirect you to the right people.

1 Like

We do have an open source project GitHub - ARM-software/LLVM-embedded-toolchain-for-Arm: A project dedicated to build LLVM toolchain for 32-bit Arm embedded targets. that will build clang, libc++abi, libunwind and libc++ in various configurations including v7-m including a hard float variant.

It uses picolibc (a derivative of newlib) although earlier versions of the scripts do use newlib.

I’m hoping you’ll be able to find out the magic runes from the project. As Renato says, this is not easy and is full of small details that are very difficult to work out unless you know about them in advance.

Peter

1 Like

@rengolin @smithp35 thank you for your help.
ARM LLVM embedded toolchain libc++ works fine for me. I was able to compile and run a simple program that uses C++ features for my CortexM7 target.

Thank you once again!

1 Like