はじめに
Yoctoのセルフコンパイル環境でout-of-treeのカーネルモジュールをビルドする。
普通にビルドしようとエラーが発生するのでその回避方法をメモしておく。
hello-mod
今回はrecipe-skeleton/recipes-kernelにあるhello-mod
をラズベリーパイ3上でビルドする。
Yoctoのイメージ
今回使用するセルフコンパイル環境を作成するには、local.conf
に次の内容を追加する。
# for raspberrypi3 MACHINE = "raspberrypi3" DL_DIR ?= "${TOPDIR}/../downloads" # enable uart ENABLE_UART = "1" # enable self-compile EXTRA_IMAGE_FEATURES_append = " dev-pkgs tools-debug tools-sdk" # add kernel soruce IMAGE_INSTALL_append = "kernel-devsrc"
カーネルソースを含むパッケージkernel-devsrc
を追加する。
作成するモジュール
~/hello
にソースとMakefileを作成する。
$ mkdir ~/hello $ cd hello
~/hello/hello.c
を次の内容で作成する。
#include <linux/module.h> int init_module(void) { printk("Hello World!\n"); return 0; } void cleanup_module(void) { printk("Goodbye Cruel World!\n"); } MODULE_LICENSE("GPL");
~/hello/Makefile
を次の内容で作成する。
obj-m := hello.o SRC := $(shell pwd) all: $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install: $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install clean: rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c rm -f Module.markers Module.symvers modules.order rm -rf .tmp_versions Modules.symvers
このMakefileではKERNEL_SRC
を変数にしているので、make実行に次のようにするか
# cd ~/hello # make KERNEL_SRC=/lib/modules/`uname -r`/build
予め環境変数に登録しておく。
# export KERNEL_SRC=/lib/modules/`uname -r`/build # make
発生するエラーの内容
初期状態でモジュールをビルドすると次のようなエラーが発生する。
# make KERNEL_SRC=/lib/modules/`uname -r`/build make -C /lib/modules/4.14.79/build M=/home/root/hello make[1]: Entering directory '/lib/modules/4.14.79/build' make[1]: Warning: File 'scripts/Makefile.ubsan' has modification time 601 s in the future make[2]: Warning: File 'scripts/Makefile.lib' has modification time 601 s in the future AR /home/root/hello/built-in.o CC [M] /home/root/hello/hello.o In file included from ./include/asm-generic/int-ll64.h:11, from ./arch/arm/include/uapi/asm/types.h:5, from ./include/uapi/linux/types.h:5, from ./include/linux/types.h:6, from ./include/linux/list.h:5, from ./include/linux/module.h:9, from /home/root/hello/hello.c:1: ./include/uapi/asm-generic/int-ll64.h:12:10: fatal error: asm/bitsperlong.h: No such file or directory #include <asm/bitsperlong.h> ^~~~~~~~~~~~~~~~~~~ compilation terminated. make[2]: *** [scripts/Makefile.build:335: /home/root/hello/hello.o] Error 1 make[1]: *** [Makefile:1527: _module_/home/root/hello] Error 2 make[1]: Leaving directory '/lib/modules/4.14.79/build' make: *** [Makefile:6: all] Error 2
fatal error: asm/bitsperlong.h: No such file or directory
。bitsperlong.h
が見つからないというエラーが出る。
エラー回避の方法
まずは、ラズベリーパイの時刻が狂っているので現在時刻に設定する。
$ date -s "MM/DD hh:mm YYYY"
日付を合わせておかないとwarning: Clock skew detected. Your build may be incomplete.
という警告が出る。
実害はなさそうだが気持ち悪いので対策しておく。
次にカーネルソースのscripts
をビルドする。
$ cd /lib/modules/`uname -r`/build $ make scripts
bitsperlong.h
のエラーはこちらで対策できる。
再びビルド
再度モジュールをビルドしてみる。
# cd ~/hello # make KERNEL_SRC=/lib/modules/`uname -r`/build make -C /lib/modules/4.14.79/build M=/home/root/hello make[1]: Entering directory '/lib/modules/4.14.79/build' AR /home/root/hello/built-in.o CC [M] /home/root/hello/hello.o Building modules, stage 2. MODPOST 1 modules CC /home/root/hello/hello.mod.o LD [M] /home/root/hello/hello.ko make[1]: Leaving directory '/lib/modules/4.14.79/build'
hello.koが生成される。
ほかのヘッダファイルでエラー
たとえば、hello.cの先頭の方にに次の行を追加する。
#include <linux/module.h> #include <linux/unistd.h> ...(snip)...
すると、makeで次のエラーが発生する。
# make KERNEL_SRC=/lib/modules/`uname -r`/build make -C /lib/modules/4.14.79/build M=/home/root/hello make[1]: Entering directory '/lib/modules/4.14.79/build' CC [M] /home/root/hello/hello.o In file included from ./arch/arm/include/asm/unistd.h:16, from ./include/uapi/linux/unistd.h:8, from /home/root/hello/hello.c:2: ./arch/arm/include/uapi/asm/unistd.h:21:10: fatal error: asm/unistd-eabi.h: No such file or directory #include <asm/unistd-eabi.h> ^~~~~~~~~~~~~~~~~~~ compilation terminated. make[2]: *** [scripts/Makefile.build:335: /home/root/hello/hello.o] Error 1 make[1]: *** [Makefile:1527: _module_/home/root/hello] Error 2 make[1]: Leaving directory '/lib/modules/4.14.79/build' make: *** [Makefile:6: all] Error 2
これは次のコマンドで回避できる。
# cd /lib/modules/`uname -r`/build # make prepare
最終的な回避策
Yoctoで作成したセルフコンパイル環境でout-of-treeのカーネルモジュールをビルドするためには、
カーネルソースで予めscripts
とprepare
をmakeしておく必要がある。
# cd /lib/modules/`uname -r`/build # make scripts # make prepare
hello.c
に次のようなincludeを追加したが、とりあえずのところエラーは発生していない。
#include <linux/module.h> #include <linux/unistd.h> #include <linux/init.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/sched.h> #include <linux/device.h> #include <linux/slab.h> #include <asm/current.h> #include <asm/uaccess.h> #include <asm/io.h> ...(snip)...