Cross compiling for ARMv7-m

Hi,
I am trying to use LLVM/clang to build a binary for ARM Cortex M platforms.
When I build my binary the linker fails to find these libraries.

./bin/clang++ -target arm-none-eabi -mcpu=cortex-m4 ./temp.cpp -L
./lib/ -L ./libexec/ -L ../build3_v7m/lib/
ld.lld: error: unable to find library -lunwind
ld.lld: error: unable to find library -lc
ld.lld: error: unable to find library -lm
ld.lld: error: unable to find library -lclang_rt.builtins-arm.a

I am guessing I can borrow libraries such as lc and lm from GCC
arm-none-eabi*, but for clang_rt.builtins-arm.a (which I thought
should've been built with LLVM build but I couldn't find that library
in my build directory) I tried building it from LLVM source.

To generate the library, I tried generating builtins by following the guide at:
https://llvm.org/docs/HowToCrossCompileBuiltinsOnArm.html
I tried with different configurations, but each one ends up in some
error which left me wondering that this document might be obsolete.

Anyhow googling things led me to this thread.

http://llvm.1065342.n5.nabble.com/llvm-dev-Compiling-for-baremetal-ARMv4-on-Ubuntu-Linux-td124226.html

After going through this I figured my best bet would be using GCC
sysroot. After which my cmake command looks like this.

cmake -G "Unix Makefiles"
-DBAREMETAL_ARMV6M_SYSROOT=../../gcc-arm-none-eabi-9-2019-q4-major/arm-none-eabi/
-DBAREMETAL_ARMV7M_SYSROOT=../../gcc-arm-none-eabi-9-2019-q4-major/arm-none-eabi/
-DBAREMETAL_ARMV7EM_SYSROOT=../../gcc-arm-none-eabi-9-2019-q4-major/arm-none-eabi/
-DCMAKE_BUILD_TYPE=Release -C ../clang/cmake/caches/BaremetalARM.cmake
../llvm

But with this, I am getting this error attached to the email. Is there
something I am missing here? Is there any update to the
cross-compilation guide? My end goal is cross-compiling C++ programs
for ARM on x86. Any pointers for this would be helpful.

Thanks,
Arslan

error_console.txt (6.33 KB)

Hello Arslan,

I am guessing I can borrow libraries such as lc and lm from GCC
arm-none-eabi*, but for clang_rt.builtins-arm.a (which I thought
should've been built with LLVM build but I couldn't find that library
in my build directory) I tried building it from LLVM source.

You can take these from an arm-none-eabi toolchain. The GCC equivalent of clang_rt.builtins-arm.a is libgcc.a, one way to use these with clang is use one of the options that suppress -lc -lm and -lclang_rt.builtins-arm.a I think either --nostdlib or --nodefaultlibs will do that. You'll need to tell clang where to find these in your arm-none-eabi toolchain.

To generate the library, I tried generating builtins by following the guide at:
How to Cross Compile Compiler-rt Builtins For Arm — LLVM 18.0.0git documentation
I tried with different configurations, but each one ends up in some
error which left me wondering that this document might be obsolete.

I'd hope the information in there isn't completely obsolete, but I haven't tried the build for over a year so it may well need an update. I'll try to reproduce my steps and send a patch to update the guide if there is anything broken. I can't promise when I'll get that done by though.

cmake -G "Unix Makefiles"
-DBAREMETAL_ARMV6M_SYSROOT=../../gcc-arm-none-eabi-9-2019-q4-major/arm-none-eabi/
-DBAREMETAL_ARMV7M_SYSROOT=../../gcc-arm-none-eabi-9-2019-q4-major/arm-none-eabi/
-DBAREMETAL_ARMV7EM_SYSROOT=../../gcc-arm-none-eabi-9-2019-q4-major/arm-none-eabi/
-DCMAKE_BUILD_TYPE=Release -C ../clang/cmake/caches/BaremetalARM.cmake
../llvm

That particular recipe predates the monorepo, and relied upon compiler-rt being checked out in the runtimes subdirectory. I suspect that this will likely not work with the monorepo.

Peter

Hi Peter,

Hello Arslan,

> I am guessing I can borrow libraries such as lc and lm from GCC
> arm-none-eabi*, but for clang_rt.builtins-arm.a (which I thought
> should've been built with LLVM build but I couldn't find that library
> in my build directory) I tried building it from LLVM source.

You can take these from an arm-none-eabi toolchain. The GCC equivalent of clang_rt.builtins-arm.a is libgcc.a, one way to use these with clang is use one of the options that suppress -lc -lm and -lclang_rt.builtins-arm.a I think either --nostdlib or --nodefaultlibs will do that. You'll need to tell clang where to find these in your arm-none-eabi toolchain.

> To generate the library, I tried generating builtins by following the guide at:
> How to Cross Compile Compiler-rt Builtins For Arm — LLVM 18.0.0git documentation
> I tried with different configurations, but each one ends up in some
> error which left me wondering that this document might be obsolete.

I'd hope the information in there isn't completely obsolete, but I haven't tried the build for over a year so it may well need an update. I'll try to reproduce my steps and send a patch to update the guide if there is anything broken. I can't promise when I'll get that done by though.

I recently tried again to build compiler-rt for cortex-m using the
info from the guide mentioned above, but it still fails for me.

Something that I don't understand is that when I call
clang --target=armv7m-none-eabi
--gcc-toolchain=/XX/gcc-linaro-7.3.1-2018.05-x86_64_arm-eabi
--sysroot=/XX/gcc-linaro-7.3.1-2018.05-x86_64_arm-eabi/arm-eabi/
-L$PWD/llvm-project/cross-install/lib hello.o -o hello.exe.arm.clang

I get:
clang-12: warning: argument unused during compilation:
'--gcc-toolchain=/XX/gcc-linaro-7.3.1-2018.05-x86_64_arm-eabi'
[-Wunused-command-line-argument]
ld.lld: error: unable to find library -lc
ld.lld: error: unable to find library -lm
clang-12: error: ld.lld command failed with exit code 1 (use -v to see
invocation)

Not sure why --gcc-toolchain isn't used, anyway libc.a and libm.a are
under $SYSROOT/libc/usr/lib
(and I did try --sysroot=...../libc --sysroot=.../libc/usr and
--sysroot=../libc/usr/lib, none of which worked)

Any idea?

Thanks,

Christophe

________________________________________
From: Christophe Lyon <christophe.lyon@linaro.org>
Sent: 14 September 2020 15:42
To: Peter Smith
Cc: llvm-dev@lists.llvm.org; Arslan Khan; nd
Subject: Re: [llvm-dev] Cross compiling for ARMv7-m

Hi Peter,

>
> Hello Arslan,
>
> > I am guessing I can borrow libraries such as lc and lm from GCC
> > arm-none-eabi*, but for clang_rt.builtins-arm.a (which I thought
> > should've been built with LLVM build but I couldn't find that library
> > in my build directory) I tried building it from LLVM source.
>
> You can take these from an arm-none-eabi toolchain. The GCC equivalent of clang_rt.builtins-arm.a is libgcc.a,
> one way to use these with clang is use one of the options that suppress -lc -lm and -lclang_rt.builtins-arm.a
> I think either --nostdlib or --nodefaultlibs will do that. You'll need to tell clang where to find these in your arm-none-eabi toolchain.
>
> > To generate the library, I tried generating builtins by following the guide at:
> > How to Cross Compile Compiler-rt Builtins For Arm — LLVM 18.0.0git documentation
> > I tried with different configurations, but each one ends up in some
> > error which left me wondering that this document might be obsolete.
>
> I'd hope the information in there isn't completely obsolete, but I haven't tried the build for over a year so it may well need an update.
> I'll try to reproduce my steps and send a patch to update the guide if there is anything broken. I can't promise when I'll get that done by though.
>

I recently tried again to build compiler-rt for cortex-m using the
info from the guide mentioned above, but it still fails for me.

Something that I don't understand is that when I call
clang --target=armv7m-none-eabi
--gcc-toolchain=/XX/gcc-linaro-7.3.1-2018.05-x86_64_arm-eabi
--sysroot=/XX/gcc-linaro-7.3.1-2018.05-x86_64_arm-eabi/arm-eabi/
-L$PWD/llvm-project/cross-install/lib hello.o -o hello.exe.arm.clang

I get:
clang-12: warning: argument unused during compilation:
'--gcc-toolchain=/XX/gcc-linaro-7.3.1-2018.05-x86_64_arm-eabi'
[-Wunused-command-line-argument]
ld.lld: error: unable to find library -lc
ld.lld: error: unable to find library -lm
clang-12: error: ld.lld command failed with exit code 1 (use -v to see
invocation)

Not sure why --gcc-toolchain isn't used, anyway libc.a and libm.a are
under $SYSROOT/libc/usr/lib
(and I did try --sysroot=...../libc --sysroot=.../libc/usr and
--sysroot=../libc/usr/lib, none of which worked)

Any idea?

Thanks,

Christophe

Hello Christophe,

When the bare metal driver is selected with --target=arm-none-eabi the --gcc-toolchain option is not checked.

From the code in clang/lib/Driver/ToolChains/BareMetal.cpp it looks like sysroot is used in the include paths but not for the library paths.

If libc.a and libm.a are under $SYSROOT/libc/usr/lib then with the bare-metal driver I think you would need to use -L $SYSROOT/libc/usr/lib

If it helps, this is what a colleague had been using recently to compile compiler-rt for bare-metal. I've not tested it myself though. The interesting parts that may be
new are -DCOMPILER_RT_BAREMETAL_BUILD=ON and -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY I expect that a lot of that can be trimmed as well.

cmake -G Ninja ../llvm-project/compiler-rt/
        -DCMAKE_BUILD_TYPE=Release \
        -DCOMPILER_RT_BUILD_SANITIZERS=OFF \
        -DCOMPILER_RT_BUILD_XRAY=OFF \
        -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
        -DCOMPILER_RT_BUILD_PROFILE=OFF \
        -DCOMPILER_RT_BAREMETAL_BUILD=ON \
        -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
        -DCMAKE_C_COMPILER_TARGET="$TARGET" \
        -DCMAKE_ASM_COMPILER_TARGET="$TARGET" \
        -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
        -DLLVM_CONFIG_PATH="$BUILDTOOLS/llvm-config" \
        -DCMAKE_C_COMPILER="$TOOLS/clang" \
        -DCMAKE_C_FLAGS="--sysroot $INSTALL/targets/$TARGET" \
        -DCMAKE_AR="$TOOLS/llvm-ar" \
        -DCMAKE_NM="$TOOLS/llvm-nm" \
        -DCMAKE_RANLIB="$TOOLS/llvm-ranlib" \
        -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" \
        -DCMAKE_INSTALL_PREFIX="$INSTALL/targets/$TARGET"

Hope this gets you a bit further. Apologies if the webmail client has mangled the reply. Let me know if you are still having problems and I'll try and take a look.

Peter

> ________________________________________
> From: Christophe Lyon <christophe.lyon@linaro.org>
> Sent: 14 September 2020 15:42
> To: Peter Smith
> Cc: llvm-dev@lists.llvm.org; Arslan Khan; nd
> Subject: Re: [llvm-dev] Cross compiling for ARMv7-m
>
> Hi Peter,
>
>
> >
> > Hello Arslan,
> >
> > > I am guessing I can borrow libraries such as lc and lm from GCC
> > > arm-none-eabi*, but for clang_rt.builtins-arm.a (which I thought
> > > should've been built with LLVM build but I couldn't find that library
> > > in my build directory) I tried building it from LLVM source.
> >
> > You can take these from an arm-none-eabi toolchain. The GCC equivalent of clang_rt.builtins-arm.a is libgcc.a,
> > one way to use these with clang is use one of the options that suppress -lc -lm and -lclang_rt.builtins-arm.a
> > I think either --nostdlib or --nodefaultlibs will do that. You'll need to tell clang where to find these in your arm-none-eabi toolchain.
> >
> > > To generate the library, I tried generating builtins by following the guide at:
> > > How to Cross Compile Compiler-rt Builtins For Arm — LLVM 18.0.0git documentation
> > > I tried with different configurations, but each one ends up in some
> > > error which left me wondering that this document might be obsolete.
> >
> > I'd hope the information in there isn't completely obsolete, but I haven't tried the build for over a year so it may well need an update.
> > I'll try to reproduce my steps and send a patch to update the guide if there is anything broken. I can't promise when I'll get that done by though.
> >
>
> I recently tried again to build compiler-rt for cortex-m using the
> info from the guide mentioned above, but it still fails for me.
>
> Something that I don't understand is that when I call
> clang --target=armv7m-none-eabi
> --gcc-toolchain=/XX/gcc-linaro-7.3.1-2018.05-x86_64_arm-eabi
> --sysroot=/XX/gcc-linaro-7.3.1-2018.05-x86_64_arm-eabi/arm-eabi/
> -L$PWD/llvm-project/cross-install/lib hello.o -o hello.exe.arm.clang
>
> I get:
> clang-12: warning: argument unused during compilation:
> '--gcc-toolchain=/XX/gcc-linaro-7.3.1-2018.05-x86_64_arm-eabi'
> [-Wunused-command-line-argument]
> ld.lld: error: unable to find library -lc
> ld.lld: error: unable to find library -lm
> clang-12: error: ld.lld command failed with exit code 1 (use -v to see
> invocation)
>
> Not sure why --gcc-toolchain isn't used, anyway libc.a and libm.a are
> under $SYSROOT/libc/usr/lib
> (and I did try --sysroot=...../libc --sysroot=.../libc/usr and
> --sysroot=../libc/usr/lib, none of which worked)
>
> Any idea?
>
> Thanks,
>
> Christophe

Hello Christophe,

When the bare metal driver is selected with --target=arm-none-eabi the --gcc-toolchain option is not checked.
From the code in clang/lib/Driver/ToolChains/BareMetal.cpp it looks like sysroot is used in the include paths but not for the library paths.

If libc.a and libm.a are under $SYSROOT/libc/usr/lib then with the bare-metal driver I think you would need to use -L $SYSROOT/libc/usr/lib

If it helps, this is what a colleague had been using recently to compile compiler-rt for bare-metal. I've not tested it myself though. The interesting parts that may be
new are -DCOMPILER_RT_BAREMETAL_BUILD=ON and -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY I expect that a lot of that can be trimmed as well.

cmake -G Ninja ../llvm-project/compiler-rt/
        -DCMAKE_BUILD_TYPE=Release \
        -DCOMPILER_RT_BUILD_SANITIZERS=OFF \
        -DCOMPILER_RT_BUILD_XRAY=OFF \
        -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
        -DCOMPILER_RT_BUILD_PROFILE=OFF \
        -DCOMPILER_RT_BAREMETAL_BUILD=ON \
        -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
        -DCMAKE_C_COMPILER_TARGET="$TARGET" \
        -DCMAKE_ASM_COMPILER_TARGET="$TARGET" \
        -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
        -DLLVM_CONFIG_PATH="$BUILDTOOLS/llvm-config" \
        -DCMAKE_C_COMPILER="$TOOLS/clang" \
        -DCMAKE_C_FLAGS="--sysroot $INSTALL/targets/$TARGET" \
        -DCMAKE_AR="$TOOLS/llvm-ar" \
        -DCMAKE_NM="$TOOLS/llvm-nm" \
        -DCMAKE_RANLIB="$TOOLS/llvm-ranlib" \
        -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" \
        -DCMAKE_INSTALL_PREFIX="$INSTALL/targets/$TARGET"

Hope this gets you a bit further. Apologies if the webmail client has mangled the reply. Let me know if you are still having problems and I'll try and take a look.

Hi Peter,

Thanks, it did help. Looks like I was missing
-DCMAKE_C_FLAGS="--sysroot XXX"
so now build_and_install_compilerrt() completes.

I guess my next step is now to understand how to build a toolchain for
eg. rtems to see what I need to update to build the sanitizers for a
new "OS" (baremetal for me).

Thanks,

Christophe