Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiling with clang, possible? Too much work for it? #194

Open
andyinno opened this issue May 1, 2021 · 5 comments
Open

Compiling with clang, possible? Too much work for it? #194

andyinno opened this issue May 1, 2021 · 5 comments

Comments

@andyinno
Copy link

andyinno commented May 1, 2021

I would just know if anybody here has already tried to compile using this project and clang.

If some modification is needed, could it be possible to share?

thank you in advance
Andrea

@atsju
Copy link
Collaborator

atsju commented May 2, 2021

I had a quick (1h) look.
It seems CMSIS itself doesn't support Clang
I have seen some reports of using Clang bare metal so I suppose it should work but maybe this would also require HAL+CMSIS changes. But maybe it's possible to build whole end user projects with Clang even if I suppose this would require some porting in end user project source code.
Maybe if you only require to build the files for Clang static analysis purpose but not for real binary generation it could be possible and not too complicated.

This is current state of my research and I definitely approve the idea of having a Clang build for static analysis. Do you used Clang on embedded projects before (without STM32-cmake) ? If yes maybe you could share and example project or past experience ?

@andyinno
Copy link
Author

andyinno commented May 2, 2021

I had spent some hours yesterday on the topic.

Just out of curiosity I made some small changes to the blinky example to check if it could compile.
I think that the result at the moment is not really bad.

The changes to the blinky example are here: https://github.com/andyinno/stm32-cmake/tree/clang_test

Basically I can compile the project. The problem is on the linking.

I read online that a lot of people are using the gnu linker for linking the final executable. I did not understand how yet.

Using the clang linker I can link the c and math libraries passing to the linker the path to the GNU libraries.

One change that is needed is to remove the hardcoded toolchain file present in the cmake example. I do not think that they are really "modern cmake" style.
Modern cmake is all about disable hardcoded paths and commands. Having the toolchain file hardcoded in the main cmakelists.txt in my opinion is in contraddiction with it.

Second change is just the toolchain file. In the toolchain file I hardcoded the paths present on my system.

The resulting error that linker outputs is:

ld.lld: error: unable to find library -lclang_rt.builtins-arm

I read online that the library is not shipped with clang but everybody needs to compile it on its own.

Regarding your last questions:

Do you used Clang on embedded projects before (without STM32-cmake) ?

I followed a different approach on it in my own projects. For static analysis I isolated the arm only code in files that are only built when the target is arm. Otherwise I link mocked functions and I perform ctests on the host computer using cmocka.
With this setup I have also the benefits of compiling with gcc, clang, and have results for ctests and lcov/gcov graphs.

If yes maybe you could share and example project or past experience ?

Never used clang on embedded. I just understand that the ARM toolchain is a patched version of CLANG. What I see compiling parts of my embedded programs for X64 is that clang analyzer is a bit more picky than the gnu gcc one. Therefore I would like to see also the rest of the code (the one that I cannot compile for X64) how behave with CLANG. The binary file, I am not sure if I could use it in production yet.

@atsju
Copy link
Collaborator

atsju commented May 2, 2021

Cool :) Thank you for your feedback.
You got further than me. I'm on windows and haven't recompiled clang yet. Which from my understanding is needed to be able to build for arm.

I notice that CMAKE_SYSTEM_NAME and CMAKE_SYSTEM_PROCESSOR is already defined in common.cmake

Also I know that setting CMAKE_C_COMPILER is not the recommended way to select the compiler but it's in cmake documentation for toolchains

I agree that hardcoded toolchain path is not modern cmake but I'm not comfortable enough with cmake to propose a fix. I fell like this toolchain file thing always becomes a bit tricky when coming to embedded cross-compilation and many of the old information is masking the modern cmake approach on the web.

@andyinno
Copy link
Author

andyinno commented May 2, 2021

It was just an apt install clang, everything went on my pc automagically. Except the clang_rt.builtins-arm file.

The fix on the hardcoded toolchain is just to explicit it with the cmake invocation. Nothing more than that. :)

@andyinno
Copy link
Author

andyinno commented May 2, 2021

Ok, I compiled the clang_rt.builtins-arm file for arm cortex 4.

for reference and credits I followed the instruction that are present in this blog post: https://interrupt.memfault.com/blog/arm-cortexm-with-llvm-clang#cross-compiling-with-clang

export NONE_EABI_TARGET=armv7em-none-eabi
export LLVM_BIN_PATH=$(dirname $(which clang))
export NONE_EABI_TARGET_FLAGS="-mthumb -mfloat-abi=soft -mfpu=none"
export ARM_SYSROOT=/usr/lib/arm-none-eabi/

cloned the LLVM project

git clone https://github.com/llvm/llvm-project.git llvm-project
cd llvm-project/compiler-rt
mkdir build
cd build

cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Release -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY -DCOMPILER_RT_OS_DIR="baremetal" -DCOMPILER_RT_BUILD_BUILTINS=ON -DCOMPILER_RT_BUILD_SANITIZERS=OFF -DCOMPILER_RT_BUILD_XRAY=OFF -DCOMPILER_RT_BUILD_LIBFUZZER=OFF -DCOMPILER_RT_BUILD_PROFILE=OFF -DCMAKE_C_COMPILER=${LLVM_BIN_PATH}/clang -DCMAKE_C_COMPILER_TARGET=${NONE_EABI_TARGET} -DCMAKE_ASM_COMPILER_TARGET=${NONE_EABI_TARGET} -DCMAKE_AR=${LLVM_BIN_PATH}/llvm-ar -DCMAKE_NM=${LLVM_BIN_PATH}/llvm-nm -DCMAKE_LINKER=${LLVM_BIN_PATH}/ld.lld -DCMAKE_RANLIB=${LLVM_BIN_PATH}/llvm-ranlib -DCOMPILER_RT_BAREMETAL_BUILD=ON -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON -DLLVM_CONFIG_PATH=${LLVM_BIN_PATH}/llvm-config -DCMAKE_C_FLAGS= ${NONE_EABI_TARGET_FLAGS} -DCMAKE_ASM_FLAGS=${NONE_EABI_TARGET_FLAGS} -DCOMPILER_RT_INCLUDE_TESTS=OFF -DCMAKE_SYSROOT=${ARM_SYSROOT} ..

ninja
ninja install

then the compilation completes correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants