Categories Books | Hard | Hardware | Linux | MCU | Misc | Publish | Radio | Repository | Thoughts | Time | UNIX | Writing | プロフィール
Brainstorm-ML上で、高原さんから「Linux kernel 2.6 での make がうまく行かない」という報告を頂く。特に、「サブディレクトリ内部での make がおかしい」とのこと。
このメッセージを拝見して、一瞬「シマッタ!」と思う。実は、記事執筆の際に使った私のホスト環境では、/usr/include/asm が Linux-2.4.24 内部の include/asm へのシンボリックリンクになっていた。当初は、Linux 2.6 ソースツリー内部の asm-i386 へ、張り直すつもりでいたのだが、仕事を急ぐ余りそのまま放置し、今回の問題点を見逃してしまった・・。滝汗;
全国、いや世界中で、この問題で眠れぬ日々を送っておられる方々のために、応急的な対処方法をご紹介しておこう。
Linux カーネルやモジュール、システムツールのビルド時に、インクルードファイルが「鬼門」となることは、これまでの連載を通じて何回か紹介してきたが、この問題は汎用ライブラリーである glibc 用のヘッダーファイルと、アーキテクチャに強く依存する Linux カーネル用のヘッダーファイルが共存しているために発生している。
なぜ、このような問題が生じるかについては、「インクルードとは何なのか?」という、素朴な疑問を丁寧に紐解いていく必要がある。例によって、世の中にはこのあたりの技術背景を解説した文書は、存在しないようなので、近いうちに GCC プログラミング工房上で徹底解説できればと思う。
ともあれ、時間は限られているので、即席の解決手段をご紹介しよう。まず、あなたは glibc と Linux kernel、おふたりさんのうち、どちらかを選択する必要がある。glibc を選んだ人には、マニュアルでカーネルをビルドするよりも、パッケージで入手することをお勧めする。
暴れ馬である Linux kernel を選んだ方は、落馬を覚悟で次のステップにお進みあれ。
Red Hat や Debian などのディストリビューターは、/usr/include ディレクトリ中に、アーキテクチャに依存するヘッダーファイル群を asm, linux サブディレクトリに格納している。当然のことながら、カーネルの成長と共に、asm, linux ディレクトリ中のヘッダーファイルは日々変遷を遂げている。具体的には、データ構造や、システムコール番号、エラーコード番号、各種インデックス番号などが挙げられる。
カーネルがこれらのファイルに依存しているのはもちろんのこと、実は glibc も一部で依存している。例えば、<errno.h> はその好例だ(実際に、内部の芋づる式 include 命令を追ってみると良い)。
よって、カーネルをアップデートした際には、厳密にはライブラリーも再構築する必要がある。しかし、そのような律儀な人(暇人?)は、まず存在しないだろう。そこで、各ディストリビューターは、カーネルヘッダーファイルと glibc の乖離を防ぐために、自分たちがライブラリーをビルドした際に使用したアーキテクチャ依存性のヘッダーファイルをあらかじめ /usr/include/asm, /usr/include/linux サブディレクトリ内部に用意しているのである。
一般的なアプリケーションをビルドする際には、これでも良いのだが、問題はカーネルに強く依存するモジュールや、システムツールをビルドする場合。詳細は割愛するが、ビルドエラー、もしくはカーネルとモジュール間でデータ構造の整合性が取れない事態に発展する。
以上より、カーネルハッキング大好き人間は、ディストリビューターが用意してくれている asm, linux サブディレクトリをさっさとポイしてきた。本当に rm -r してしまうと、ちと心配なので、通常は asm.orig, linux.orig などに改名すると良いだろう。その上で、/usr/src/linux 内部へのシンボリックリンクを張る。私の場合は、次の通り。
/usr/include # file asm asm-generic asm: symbolic link to ../src/linux/include/asm-i386 asm-generic: symbolic link to ../src/linux/include/asm-generic /usr/include # file ../src/linux ../src/linux: symbolic link to linux-2.6.3
最終的には、/usr/include/asm は、/usr/src/linux-2.6.3/include/asm-i386、/usr/include/asm-generic は、/usr/src/linux-2.6.3/include/asm-generic、/usr/include/linux は、/usr/src/linux-2.6.3/include/linux への参照となる。asm-generic は、カーネル 2.6 から <asm/errno.h> 内部で <asm-generic/errno.h> を孫インクルードするようになったために、必要になったものである。
ここで、Embedded UNIX Vol.6 および GCC プログラミング工房で紹介した、サブディレクトリ内部でのビルドに挑戦してみると・・
残念ながら、エラーにより異常終了してしまう(従来通り、トップディレクトリ上でビルドすれば、問題は発生しない)。この原因は、トップディレクトリに用意されている Makefile 中の prepare1 ターゲットにある。
571 # prepare1 is used to check if we are building in a separate output directory, 572 # and if so do: 573 # 1) Check that make has not been executed in the kernel src $(srctree) 574 # 2) Create the include2 directory, used for the second asm symlink 575 576 prepare1: 577 ifneq ($(KBUILD_SRC),) 578 @echo ' Using $(srctree) as source for kernel' 579 # $(Q)if [ -h $(srctree)/include/asm -o -f $(srctree)/.config ]; then ? 580 # echo " $(srctree) is not clean, please run 'make mrproper'";? 581 # echo " in the '$(srctree)' directory.";? 582 # /bin/false; ? 583 # fi; 584 $(Q)if [ ! -d include2 ]; then mkdir -p include2; fi; 585 $(Q)ln -fsn $(srctree)/include/asm-$(ARCH) include2/asm 586 endif
結論から言えば、579行目がエラーの発生箇所である。本行が意味するところはなかなか深いのだが、取り急ぎ今は何も考えず 579〜583行をコメントアウトしてしまおう。以上で、カーネルハッキングに最適のビルド環境が出来上がる。
後はひたすらビルドするのみ。Have fun!
以上のように、Linux 2.6 では 2.4 に比較してカーネルヘッダーファイルの取り扱いが激変している。にもかかわらず、ソースツリー内部の解説文書には、この変化に関する記述が見当たらないのである。
ソースコードと優れた技術文書が融合し、初めて美しい肉体が出来上がるとすれば、現状の Linux はさしずめ「骸骨」と言ったところだろうか・・。