はじめに
meta-clangの使い方を調べた。
meta-clangはbitbakeでのパッケージのビルドやSDKでgccの代わりにclangを使えるようにするためのレイヤ。
meta-clangを使う
既存のビルド環境にmeta-clangを組み込むには下記のようにする。
$ git clone https://github.com/kraj/meta-clang -b dunfell
ビルド対象に組み込むにはbitbake-layers
を実行する。
$ bitbake-layers add-layers ../layers/meta-clang
デフォルトのツールチェインを切り替える
bitbakeで使用するデフォルトのツールチェインをgccからclangに変更するにはlocal.conf
で下記を設定する。
TOOLCHAIN = "clang"
一部、gccじゃないとうまくビルドできないようなパッケージは、meta-clang/conf/nonclangable.conf
で次のように設定されている(抜粋)。
# __ai uint8x16_t vabdq_u8(uint8x16_t __p0, uint8x16_t __p1) { TOOLCHAIN_pn-firefox = "gcc" TOOLCHAIN_pn-gcc = "gcc" TOOLCHAIN_pn-gcc-runtime = "gcc" TOOLCHAIN_pn-gcc-sanitizers = "gcc" TOOLCHAIN_pn-glibc = "gcc" TOOLCHAIN_pn-glibc-initial = "gcc" TOOLCHAIN_pn-glibc-locale = "gcc" TOOLCHAIN_pn-glibc-mtrace = "gcc" TOOLCHAIN_pn-glibc-scripts = "gcc" TOOLCHAIN_pn-glibc-testsuite = "gcc" TOOLCHAIN_pn-grub = "gcc" TOOLCHAIN_pn-grub-efi = "gcc"
追加で設定したい場合はこの書式に則ってlocal.conf
に設定を追加する。
レシピ毎のツールチェインを切り替える
デフォルトのツールチェインは変更せずにレシピ毎に使用するツールチェインをclangに設定したい場合は、それぞれのレシピで下記の内容を設定する。
TOOLCHAIN = "clang"
SDKにclangを含める
SDKにclangを含めるにはlocal.conf
に下記を設定する。
CLANGSDK = "1"
# Adding clang in generated SDK toolchain clang based cross compiler is not included into the generated SDK using `bitbake meta-toolchain` or `bitbake -cpopulate_sdk <image>` if clang is expected to be part of SDK, add `CLANGSDK = "1"` in `local.conf`
CLANGSDKに関するREADME.mdの説明は下記のようになっている。
# Removing clang from generated SDK toolchain
clang based cross compiler is automatically included into the generated SDK using `bitbake meta-toolchain` or
`bitbake -cpopulate_sdk <image>` in circumstanced where clang is not expected to be part of SDK, then reset `CLANGSDK`
variable in `local.conf`
```shell
CLANGSDK = ""
```
clangをSDKに含めないようにするにはCLANGSDK = ""
として値をリセットするようにという説明しか無いため、
最初読んだ時今いち理解ができなかった。
これはもともとCLANGSDKのデフォルトが1になっていて、SDKに含まれることが前提だったためこのような書き方になっている。
デフォルトは826feacfeb64e2b4fe3ff50153a8ba4fa4bfff76
のコミットで0に修正されている。
commit 826feacfeb64e2b4fe3ff50153a8ba4fa4bfff76 Author: Khem Raj <raj.khem@gmail.com> Date: Thu Apr 2 14:21:57 2020 -0700 layer.conf: Mark CLANGSDK 0 by default This ensures that clangsdk does not inserts itself unless user asks for Fixes #234 Signed-off-by: Khem Raj <raj.khem@gmail.com> diff --git a/.drone.yml b/.drone.yml index 548873f..7f14e38 100644 --- a/.drone.yml +++ b/.drone.yml @@ -40,6 +40,7 @@ steps: - echo IMAGE_CLASSES += \"testimage testsdk\" >> conf/local.conf - echo INHERIT += \"report-error rm_work blacklist\" >> conf/local.conf - echo TOOLCHAIN = \"clang\" >> conf/local.conf + - echo CLANGSDK = \"1\" >> conf/local.conf - echo IMAGE_INSTALL_append = \" clang \" >> conf/local.conf - echo XZ_DEFAULTS = \"--threads=8\" >> conf/local.conf - echo LICENSE_FLAGS_WHITELIST_append = \" commercial non-commercial\" >> conf/local.conf diff --git a/conf/layer.conf b/conf/layer.conf index f3e3fcc..792ba40 100644 --- a/conf/layer.conf +++ b/conf/layer.conf @@ -26,8 +26,8 @@ PREFERRED_PROVIDER_llvm-native = "clang-native" PREFERRED_PROVIDER_nativesdk-llvm = "nativesdk-clang" INHERIT += "clang" -# include clang in SDK -CLANGSDK ??= "1" +# Do not include clang in SDK unless user wants to +CLANGSDK ??= "0" LLVMVERSION = "10.0.0"
この時、ドキュメントは更新されなかったためこのような状態になっている。
masterを見ると修正されていたのでblameしてみると、下記のコミットで修正されたらしい。
commit 2730fe62d5d0af59d49bc2d8fe703753331aacf2 Author: Khem Raj <raj.khem@gmail.com> Commit: Khem Raj <raj.khem@gmail.com> README: Update documentation Few knobs have changed and has not been yet reflected in README Signed-off-by: Khem Raj <raj.khem@gmail.com>
SDKにクロスコンパイラが含まれない場合
既にSDKをビルドしてしまった状態で、local.confにCLANGSDK = "1"
を設定した場合、SDKにclangのクロスコンパイラが含まれない場合がある。
実際にSDKにclangのクロスコンパイラを入れる処理はpackagegroup-cross-canadian
というレシピが行っているが、
CLANGSDKの値の変更はbitbake時に検出しないため、このパッケージをcleanする必要があるようだ。
確実にCLANGSDKの変更を反映するには下記のようにコマンドを実行する。
$ bitbake packagegroup-cross-canadian -c cleanall $ bitbake core-image-base -c populate_sdk -f
SDKをインストールする際の注意点
build/tmp/deploy/sdk
以下に生成されるインストーラではインストール先のディレクトリ変更することができるが、2020/12/13時点でWhen setting up sdk relocating error #119の問題が解決されてないため、デフォルトのままインストールするほうが無難。
インストールしたSDKのclangを使う
インストールしたSDKを使用するには最初に環境変数を設定する必要がある。
$ source /opt/poky/3.1.4/environment-setup-aarch64-poky-linux
Cソースのビルド
今回は適当にHello worldを用意する。下記の内容でhello.c
を作成する。
#include <stdio.h> int main(void) { printf("hello world from C\n"); return 0; }
ターゲット向けにCのソースファイルをビルドするには下記のようにする。
$ ${CLANGCC} hello.c -ohello -O2
ターゲット用のビルドを行うためのコマンドラインはCLANGCC
環境変数に設定されている。
C++ソースのビルド
こちらもC++でHello world。下記の内容でhello.cpp
を作成する。
#include <iostream> int main(void) { std::cout << "hello world" << std::endl; return 0; }
ターゲット向けにC++のソースファイルをビルドするには下記のようにする。
$ ${CLANGCXX} hello.cpp -ohello -O2
autotoolsベースのビルド
Makefile.amを以下の内容で作成する。
bin_PROGRAMS=hello hello_SOURCES=hello.cpp
configure.acを以下の内容で作成する。
AC_INIT(hello.cpp) AM_INIT_AUTOMAKE(hello,0.1) AC_PROG_CC AC_PROG_CXX AC_PROG_INSTALL AC_OUTPUT(Makefile)
次のような配置にする。
. ├── Makefile.am ├── configure.ac └── hello.cpp
下記のように環境変数を設定する。
$ export CC=${CLANGCC} $ export CXX=${CLANGCXX} $ export CPP=${CLANGCPP}
次のコマンドを実行してビルドする。
$ touch NEWS README AUTHORS ChangeLog $ autoreconf -i $ ./configure --host=${CROSS_COMPILE} $ make
Makefileを確認するとclangでビルドされていることが分かる。
...(snip)... CC = aarch64-poky-linux-clang -march=armv8-a+crc -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -mlittle-endian --sysroot=/opt/poky/3.1.4/sysroots/aarch64-poky-linux CCDEPMODE = depmode=gcc3 CFLAGS = -O2 -pipe -g -feliminate-unused-debug-types CPPFLAGS = CXX = aarch64-poky-linux-clang++ -march=armv8-a+crc -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -mlittle-endian --sysroot=/opt/poky/3.1.4/sysroots/aarch64-poky-linux ...(snip)...
CMakeベースのビルド
CMakeLists.txtを下記の内容で作成する。
cmake_minimum_required(VERSION 3.10) project("hello") add_executable(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}/hello.cpp )
次のような配置にする。
. ├── CMakeLists.txt └── hello.cpp
下記のように環境変数を設定する。
$ export CC=${CLANGCC} $ export CXX=${CLANGCXX} $ export CPP=${CLANGCPP}
次のコマンドを実行してビルドする。
$ mkdir build && cd build $ cmake .. $ make
ccmakeなどで確認するとclangでビルドされていることが分かる。
CMAKE_CXX_COMPILER /opt/poky/3.1.4/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-clang++ CMAKE_CXX_COMPILER_AR /opt/poky/3.1.4/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-llvm-ar CMAKE_CXX_COMPILER_ARG1 -march=armv8-a+crc -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -mlittle-endian --sysroot=/opt/poky/3.1.4/sysroots/aarch64-poky-linux
まとめ
meta-clangの使い方をまとめた。
もともと存在は知っていたが、実際に動作を確認したのは初めてだった。
Yoctoでのアプリケーション開発でclangが使用できると新し目のC++の機能を使ったりもできるので便利かもしれない。