はじめに
ここまで作ってきたベアメタルのLチカはGCCでビルドしてきたが、それをclangでビルドしてみる。
clang-10のインストール
Ubuntu 20.04環境でClangをインストールする。バージョンは10。
$ sudo apt install -y clang-10 lld-10 make
Makefile
ベースはLチカのFLASH + コンパイル済みBoot Stage2バージョン
まずはMakefile
を下記のように変更する。
LLVM_OPT = --target=armv6-m-unknown-none-eabi -mcpu=cortex-m0plus ASMOPT = $(LLVM_OPT) -c -g COPT = $(LLVM_OPT) -c -mthumb -ffreestanding -g -O0 LOPT = $(LLVM_OPT) -nostdlib all: led.uf2 clean: rm -f *.o rm -f *.elf rm -f *.list rm -f *.uf2 rm -f *~ start.o: start.S clang-10 $(ASMOPT) start.S -o start.o boot2.o: boot2/bs2_default_padded_checksummed.S clang-10 $(ASMOPT) boot2/bs2_default_padded_checksummed.S -o boot2.o main.o: main.c clang-10 $(COPT) -fpic -mthumb -c main.c -o main.o led.elf: start.o boot2.o main.o clang-10 -fuse-ld=lld $(LOPT) start.o boot2.o main.o -T memmap.ld -o led.elf led.uf2: led.elf elf2uf2 led.elf led.uf2
GCC環境とのコマンドは下記のように異なっている。
機能 | GCC | Clang |
---|---|---|
アセンブラ | as | clang |
コンパイラ | gcc | clang |
リンカ | ld | clang |
clangは全ての機能においてclangから呼び出されるようになっている
ポイントはアセンブルとコンパイルの時にリンクまでしたくない場合は-c
をつけること。
clangではクロスコンパイルのためにそれぞれのバイナリがあるのではなくLLVMのバックエンドを切り替えるだけなので、すべてオプションで指定する。
基本的にはRaspberry Pi Pico向けの場合下記のようになる。
LLVM_OPT = --target=armv6-m-unknown-none-eabi -mcpu=cortex-m0plus
それぞれの機能で渡したいオプションが違うので下記のようにする。
ASMOPT = $(LLVM_OPT) -c -g COPT = $(LLVM_OPT) -c -mthumb -ffreestanding -g -O0 LOPT = $(LLVM_OPT) -nostdlib
リンカスクリプト
そのままでは下記のようなエラーになる。
ld.lld: error: no memory region specified for section '.ARM.exidx' clang: error: ld.lld command failed with exit code 1 (use -v to see invocation) make: *** [Makefile:26: led.elf] エラー 1
これは.ARM.exidx
セクションが無いというエラー。
前にリンカスクリプトを眺めた時はnewlibを使用する時に必要になるセクションらしい。
とのことだったが、LLVMでバイナリを吐き出す場合にも必要になるようだ。
MEMORY { FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k } ENTRY(reset) SECTIONS { /* boot2 section is for embed the precompiled boot2. this code from memmap_default.ld in pico-sdk */ .boot2 : { __boot2_start__ = .; KEEP(*(.boot2)) __boot2_end__ = .; } > FLASH ASSERT(__boot2_end__ - __boot2_start__ == 256, "ERROR: Pico second stage bootloader must be 256 bytes in size") .text : { KEEP (*(.vectors)) KEEP(*(.text*)) } > FLASH .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } > FLASH }
これでエラーは回避できるようになった。
$ make clang-10 -fuse-ld=lld --target=armv6-m-unknown-none-eabi -mcpu=cortex-m0plus -nostdlib start.o boot2.o main.o -T memmap.ld -o led.elf elf2uf2 led.elf led.uf2
まとめ
アセンブラ、コンパイラ、リンカの呼び出しが全てclang
だとは思わなかった。
.ARM.exidx
セクションは必要になる。