Compile rt-thread using LLVM

LLVM17 has been released, and arm officials have also released the corresponding compiled version 17.01. See the link https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/tags. I have always wanted to use LLVM to replace GCC. , so let’s try it. Note that 17.01 does not come with compiled cfg files for common architectures. I copied them from the 16.0 compressed package to the bin directory of 17.0.1.

I have seen someone try LLVM compilation on rtt before (https://blog.csdn.net/rtthreadiotos/article/details/122465863?depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~ OPENSEARCH~Rate-3-122465863-blog-133980411.235^v38^pc_relevant_sort_base1), there is no need to write the makefile from scratch. rt-thread has also released version 5.0.2 recently, so I downloaded version 5.0.2. After searching the entire project, I found that there are already STM32 chips that support LLVM compilation, and the board path is rt-thread-5.0.2\bsp\stm32\stm32l475-atk-pandora. You can see that rtconfig.py in the board directory already has configured LLVM compiler options and parameters, but GCC is used by default. After modifying CROSS_TOOL='gcc' to CROSS_TOOL='llvm-arm', open the ENV tool and enter rt-thread-5.0.2\bsp\stm32\stm32l475 -atk-pandora directory, enter scons -j4 to start compilation.

I originally thought that LLVM would be called directly to start compilation smoothly, but the ENV toolbar showed that GCC was called. I looked at rtconfig.py again and found this sentence:

if os.getenv('RTT_CC'):
    CROSS_TOOL = os.getenv('RTT_CC')

The ENV tool sets the RTT_CC environment variable, so the cross toolbar is still GCC, so I comment out these two sentences with # and continue compiling. There is an error in the daily error compilation flag, please modify it as follows:

elif PLATFORM == 'llvm-arm':
    #toolchains
    PREFIX = 'llvm-'
    CC = 'clang'
    AS = 'clang'
    AR = PREFIX + 'ar'
    CXX = 'clang + + '
    LINK = 'clang'
    TARGET_EXT = 'elf'
    SIZE = PREFIX + 'size'
    OBJDUMP = PREFIX + 'objdump'
    OBJCPY = PREFIX + 'objcopy'
    DEVICE = ' --config armv7em_hard_fpv4_sp_d16.cfg'
    DEVICE + = ' -ffunction-sections -fdata-sections'
    CFLAGS = DEVICE
    CFLAGS + = ' -mfloat-abi=hard -march=armv7em -mfpu=fpv4-sp-d16'
    AFLAGS = ' -c' + DEVICE + ' -Wa,-mimplicit-it=thumb ' ## -x assembler-with-cpp
    LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rt-thread.map,-u,Reset_Handler -T board/linker_scripts/link.lds'

    CPATH = ''
    LPATH = ''

    if BUILD == 'debug':
        CFLAGS + = ' -O0 -gdwarf-2 -g'
        AFLAGS + = '-gdwarf-2'
    else:
        CFLAGS + = '-O2'

    CXXFLAGS = CFLAGS

    POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\
' + SIZE + ' $TARGET \
'

As a result, the compilation still reported an error, saying that there was a problem with the definition in picolibc.h. After searching online for a long time, I couldn’t find a solution, so I commented out that sentence. It still doesn’t work after compilation, and an error is reported during the syscall compilation. If you look closely, the path compiled by syscall.c is still the newlib path E:\Download\rt-thread-5.0.2\components\libc\compilers\
ewlib\syscall.c
, it means that some LLVM configurations have not taken effect. After checking for a long time, I found that the LLVM picolib version was not printed during the scons scan (GCC prints it), so I looked at the python script to obtain the picolib version E:\Download\rt-thread-5.0.2\tools\llvm_arm .py, print out all the key paths in the script, and find that there is a problem with this exec_path. It actually points to the GCC path that comes with the ENV tool. It is really inexplicable. So I went to rtconfig.py and looked through it again, and wrote the following sentence:

if os.getenv('RTT_EXEC_PATH'):
    EXEC_PATH = os.getenv('RTT_EXEC_PATH')

This configuration is really baffling. Comment out these two sentences with # and compile again. Finally the picolib version is printed and compilation starts.

 >scons -j2
scons: Reading SConscript files ...
PicoLibc version: 1.8.5
scons: done reading SConscript files.
scons: Building targets ...
scons: building associated VariantDir targets: build
CC build\applications\main.o
CC build\board\board.o
CC build\board\CubeMX_Config\Src\stm32l4xx_hal_msp.o
CC build\kernel\components\drivers\core\device.o
CC build\kernel\components\drivers\ipc\completion.o
CC build\kernel\components\drivers\ipc\dataqueue.o
CC build\kernel\components\drivers\ipc\pipe.o
CC build\kernel\components\drivers\ipc\ringblk_buf.o
CC build\kernel\components\drivers\ipc\ringbuffer.o

When linking finally, another error was reported, saying that the memory was insufficient and the eh_frame segment took up too much space. I searched on g and found that it was in the ld file E:\Download\rt-thread-5.0.2\bsp\stm32 \stm32l475-atk-pandora\board\linker_scripts\link.ldsAdd this sentence:

/DISCARD/ : { *(.eh_frame) <sections to discard>}

After adding it, the link was indeed successful.

AS E:\Download\rt-thread-5.0.2\bsp\stm32\libraries\STM32L4xx_HAL\CMSIS\Device\ST\STM32L4xx\Source\Templates\gcc\startup_stm32l475xx.o
clang: warning: argument unused during compilation: '-ffunction-sections' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-fdata-sections' [-Wunused-command-line-argument]
E:\Download\rt-thread-5.0.2\bsp\stm32\libraries\STM32L4xx_HAL\CMSIS\Device\ST\STM32L4xx\Source\Templates\gcc\startup_stm32l475xx.s:59:5: warning: DWARF2 only supports one section per compilation unit
    .section .text.Reset_Handler
    ^
E:\Download\rt-thread-5.0.2\bsp\stm32\libraries\STM32L4xx_HAL\CMSIS\Device\ST\STM32L4xx\Source\Templates\gcc\startup_stm32l475xx.s:114:5: warning: DWARF2 only supports one section per compilation unit
    .section .text.Default_Handler,"ax",%progbits
    ^
LINKrt-thread.elf
llvm-objcopy -O binary rt-thread.elf rtthread.bin
llvm-size rt-thread.elf
   text data bss dec hex filename
  73056 1788 2264 77108 12d34 rt-thread.elf
scons: done building targets.

Compared with the bin file compiled by GCC, it is about 3% smaller, the performance improvement is unknown, and it cannot be tested without a physical board.

scons: warning: you do not seem to have the pywin32 extensions installed;
        parallel (-j) builds may not work reliably with open Python files.
File "D:\autotest\code\env\tools\Python27\Scripts\scons.py", line 204, in <module>
scons: Building targets ...
scons: building associated VariantDir targets: build
LINKrt-thread.elf
arm-none-eabi-objcopy -O binary rt-thread.elf rtthread.bin
arm-none-eabi-size rt-thread.elf
   text data bss dec hex filename
  75192 2200 3280 80672 13b20 rt-thread.elf
scons: done building targets.

Try it on the stm32f407, beaglebone black and RK3568 development boards next time.