Help us understand the problem. What is going on with this article?

クロスコンパイルした Debian GNU/Linux でデバイスドライバをセルフコンパイルする際の注意点

はじめに

https://github.com/ikwzm/FPGA-SoC-Linux では Zynq(ARMv7+FPGA)用の Debian GNU/Linux を用意しています。このリポジトリで用意している Linux Kernel や Debian Package は、Ubuntu(x86-64)上でクロスコンパイルしたものです。この記事では、デバイスドライバをセルフコンパイル(ターゲットシステムの上でコンパイル)しようとしたときに遭遇した問題点と(暫定的な)解決方法について説明します。

2019年10月17日 追記

ここで説明しているのは Linux Kernel 4.x の場合です。Linux Kernel 5.x ではもう一工夫必要でした。詳細は以下の記事を参照してください。

ヘッダーパッケージのインストール

ターゲット上でデバイスドライバをセルフコンパイルするためには、ターゲットにヘッダーパッケージがインストールされている必要があります。https://github.com/ikwzm/FPGA-SoC-Linux では linux-headers-4.14.21-armv7-fpga_4.14.21-armv7-fpga-1_armhf.deb 等のように linux-headers-*_*_?_armhf.deb のようなファイル名で用意しています(* には Linux Kernel のバージョン番号を含んだタグ、? にはパッケージのバージョン番号が入ります)。

まずはこのヘッダーパッケージをインストールします(すでにインストールされている場合もあります)。

dpkg -i linux-headers-4.14.21-armv7-fpga_4.14.21-armv7-fpga-1_armhf.deb のログ
fpga@debian-fpga:~/debian$ sudo dpkg -i linux-headers-4.14.21-armv7-fpga_4.14.21-armv7-fpga-1_armhf.deb
Selecting previously unselected package linux-headers-4.14.21-armv7-fpga.
(Reading database ... 62256 files and directories currently installed.)
Preparing to unpack linux-headers-4.14.21-armv7-fpga_4.14.21-armv7-fpga-1_armhf.deb ...
Unpacking linux-headers-4.14.21-armv7-fpga (4.14.21-armv7-fpga-1) ...
Setting up linux-headers-4.14.21-armv7-fpga (4.14.21-armv7-fpga-1) ...

セルフコンパイルの失敗例

ダウンロード

ここで udmabuf (カーネル空間に確保したバッファをユーザー空間から使えるようにするデバイスドライバ)を例としてコンパイルしてみます。

git clone https://github.com/ikwzm/udmabuf.git のログ
root@debian-fpga:~/work# git clone https://github.com/ikwzm/udmabuf.git
Cloning into 'udmabuf'...
remote: Counting objects: 212, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 212 (delta 0), reused 3 (delta 0), pack-reused 206
Receiving objects: 100% (212/212), 160.13 KiB | 0 bytes/s, done.
Resolving deltas: 100% (115/115), done.
root@debian-fpga:~/work# cd udmabuf

失敗時のログ

udmabuf を make コマンドでビルドすると、次のように失敗します。

root@debian-fpga:~/work/udmabuf# make
make -C /lib/modules/4.14.21-armv7-fpga/build ARCH=arm CROSS_COMPILE= M=/root/work/udmabuf modules
make[1]: Entering directory '/usr/src/linux-headers-4.14.21-armv7-fpga'
  CC [M]  /root/work/udmabuf/udmabuf.o
/bin/sh: 1: scripts/basic/fixdep: Exec format error
scripts/Makefile.build:326: recipe for target '/root/work/udmabuf/udmabuf.o' failed
make[2]: *** [/root/work/udmabuf/udmabuf.o] Error 2
Makefile:1508: recipe for target '_module_/root/work/udmabuf' failed
make[1]: *** [_module_/root/work/udmabuf] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-4.14.21-armv7-fpga'
Makefile:19: recipe for target 'all' failed
make: *** [all] Error 2

失敗の理由

ログを見ると、どうやら scripts/basic/fixdep の実行フォーマットが違うと言っているようです。scripts/basic/fixdep/usr/src/linux-headers-*/scripts/basic/fixdep にあります。ファイルの型を確認すると、ホストコンピュータのアーキテクチャ(ここでは x86-64)のバイナリファイルになっています。

file /usr/src/linux-headers-4.14.21-armv7-fpga/scripts/basic/fixdep のログ
root@debian-fpga:~/work/udmabuf# file /usr/src/linux-headers-4.14.21-armv7-fpga/scripts/basic/fixdep
/usr/src/linux-headers-4.14.21-armv7-fpga/scripts/basic/fixdep: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, not stripped

暫定的な対処方法

そこで、次のように /usr/src/linux-headers-*/ にインストールした各種スクリプトをターゲットのアーキテクチャ用に再ビルドします。

make scripts 実行時のログ
root@debian-fpga:~/work/udmabuf# cd /usr/src/linux-headers-4.14.21-armv7-fpga/
root@debian-fpga:/usr/src/linux-headers-4.14.21-armv7-fpga# make scripts
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/basic/bin2c
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf  --silentoldconfig Kconfig
  HOSTCC  scripts/dtc/dtc.o
  HOSTCC  scripts/dtc/flattree.o
  HOSTCC  scripts/dtc/fstree.o
  HOSTCC  scripts/dtc/data.o
  HOSTCC  scripts/dtc/livetree.o
  HOSTCC  scripts/dtc/treesource.o
  HOSTCC  scripts/dtc/srcpos.o
  HOSTCC  scripts/dtc/checks.o
  HOSTCC  scripts/dtc/util.o
  HOSTCC  scripts/dtc/dtc-lexer.lex.o
  HOSTCC  scripts/dtc/dtc-parser.tab.o
  HOSTLD  scripts/dtc/dtc
  HOSTCC  scripts/genksyms/genksyms.o
  HOSTCC  scripts/genksyms/parse.tab.o
  HOSTCC  scripts/genksyms/lex.lex.o
  HOSTLD  scripts/genksyms/genksyms
  CC      scripts/mod/empty.o
  HOSTCC  scripts/mod/mk_elfconfig
  MKELF   scripts/mod/elfconfig.h
  HOSTCC  scripts/mod/modpost.o
  CC      scripts/mod/devicetable-offsets.s
  CHK     scripts/mod/devicetable-offsets.h
  HOSTCC  scripts/mod/file2alias.o
  HOSTCC  scripts/mod/sumversion.o
  HOSTLD  scripts/mod/modpost
  HOSTCC  scripts/kallsyms
  HOSTCC  scripts/conmakehash
  HOSTCC  scripts/sortextable
scripts/sortextable.c:31:32: fatal error: tools/be_byteshift.h: No such file or directory
 #include <tools/be_byteshift.h>
                                ^
compilation terminated.
scripts/Makefile.host:102: recipe for target 'scripts/sortextable' failed
make[1]: *** [scripts/sortextable] Error 1
Makefile:558: recipe for target 'scripts' failed
make: *** [scripts] Error 2

scripts/sortextable でコンパイルエラーが出ます。どうやら <tools/be_byteshift.h> が見つからないと言っているようです。ですが、とにかく、scripts/basic/fixdep のビルドは出来ているようです。再度、デバイスドライバをビルドしてみます。

root@debian-fpga:/usr/src/linux-headers-4.14.21-armv7-fpga# cd ~/work/udmabuf
root@debian-fpga:~/work/udmabuf# make
make -C /lib/modules/4.14.21-armv7-fpga/build ARCH=arm CROSS_COMPILE= M=/root/work/udmabuf modules
make[1]: Entering directory '/usr/src/linux-headers-4.14.21-armv7-fpga'
  CC [M]  /root/work/udmabuf/udmabuf.o
  Building modules, stage 2.
  MODPOST 1 modules
WARNING: modpost: Found 1 section mismatch(es).
To see full details build your kernel with:
'make CONFIG_DEBUG_SECTION_MISMATCH=y'
  CC      /root/work/udmabuf/udmabuf.mod.o
  LD [M]  /root/work/udmabuf/udmabuf.ko
make[1]: Leaving directory '/usr/src/linux-headers-4.14.21-armv7-fpga'

今度は正常にビルド出来ました。

ヘッダーパッケージの修正

本来ならばターゲットアーキテクチャ用にコンパイルした実行ファイルをヘッダーパッケージに含めるようにするのが正しい方法だと思います。しかし、私の調べた範囲では、このようにヘッダーパッケージをビルドする方法が判りませんでした。どなたか詳しい方がいらっしゃれば、教えてくださると有難いです。

次善の策として、ターゲットにヘッダーパッケージをインストールした際に自動的に各種スクリプトを再ビルドするように、ヘッダーパッケージを作り直します。具体的には、ヘッダーパッケージを生成するスクリプトに次のようなパッチを当てます。

linux-4.14.21-armv7-fpga-patch-builddeb.diff
linux-4.14.21-armv7-fpga-patch-builddeb.diff
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 0bc8747..515963f 100755
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -313,7 +313,7 @@ fi

 # Build kernel header package
 (cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$objtree/debian/hdrsrcfiles"
-(cd $srctree; find arch/*/include include scripts -type f) >> "$objtree/debian/hdrsrcfiles"
+(cd $srctree; find arch/*/include include tools/include scripts -type f) >> "$objtree/debian/hdrsrcfiles"
 (cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles"
 (cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles"
 if grep -q '^CONFIG_STACK_VALIDATION=y' $KCONFIG_CONFIG ; then
@@ -330,6 +330,15 @@ mkdir -p "$destdir"
 (cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be
 ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build"
 rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
+mkdir -m 755 -p "$kernel_headers_dir/DEBIAN"
+cat <<EOF >> $kernel_headers_dir/DEBIAN/postinst
+#!/bin/sh -e
+
+make -C /usr/src/linux-headers-$version scripts
+
+EOF
+
+chmod 755 $kernel_headers_dir/DEBIAN/postinst

 cat <<EOF >> debian/control






このパッチファイルは builddeb に対して、tools/include 以下のファイルを含めるようにしています。これにより scripts/sortextable のビルドが正常に終了します。

そして、スクリプトをターゲット用に再ビルドするための postinst スクリプトをヘッダーパッケージに追加しています。これにより、ヘッダーパッケージをインストールした際、自動的にスクリプトを再ビルドします。

ヘッダーパッケージを昔のバージョンからアップグレードする際は、そのまま新しいヘッダーパッケージをインストールします。

dpkg -i linux-headers-4.14.21-armv7-fpga_4.14.21-armv7-fpga-2_armhf.deb のログ
root@debian-fpga:/home/fpga/debian# dpkg -i linux-headers-4.14.21-armv7-fpga_4.14.21-armv7-fpga-2_armhf.deb
(Reading database ... 81503 files and directories currently installed.)
Preparing to unpack linux-headers-4.14.21-armv7-fpga_4.14.21-armv7-fpga-2_armhf.deb ...
Unpacking linux-headers-4.14.21-armv7-fpga (4.14.21-armv7-fpga-2) over (4.14.21-armv7-fpga-1) ...
Setting up linux-headers-4.14.21-armv7-fpga (4.14.21-armv7-fpga-2) ...
make: Entering directory '/usr/src/linux-headers-4.14.21-armv7-fpga'
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/basic/bin2c
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf  --silentoldconfig Kconfig
  HOSTCC  scripts/dtc/dtc.o
  HOSTCC  scripts/dtc/flattree.o
  HOSTCC  scripts/dtc/fstree.o
  HOSTCC  scripts/dtc/data.o
  HOSTCC  scripts/dtc/livetree.o
  HOSTCC  scripts/dtc/treesource.o
  HOSTCC  scripts/dtc/srcpos.o
  HOSTCC  scripts/dtc/checks.o
  HOSTCC  scripts/dtc/util.o
  HOSTCC  scripts/dtc/dtc-lexer.lex.o
  HOSTCC  scripts/dtc/dtc-parser.tab.o
  HOSTLD  scripts/dtc/dtc
  HOSTCC  scripts/genksyms/genksyms.o
  HOSTCC  scripts/genksyms/parse.tab.o
  HOSTCC  scripts/genksyms/lex.lex.o
  HOSTLD  scripts/genksyms/genksyms
  CC      scripts/mod/empty.o
  HOSTCC  scripts/mod/mk_elfconfig
  MKELF   scripts/mod/elfconfig.h
  HOSTCC  scripts/mod/modpost.o
  CC      scripts/mod/devicetable-offsets.s
  CHK     scripts/mod/devicetable-offsets.h
  HOSTCC  scripts/mod/file2alias.o
  HOSTCC  scripts/mod/sumversion.o
  HOSTLD  scripts/mod/modpost
  HOSTCC  scripts/kallsyms
  HOSTCC  scripts/conmakehash
  HOSTCC  scripts/sortextable
make: Leaving directory '/usr/src/linux-headers-4.14.21-armv7-fpga'

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away