linux kernelのmakeターゲットについてのあれこれ

はじめに

本記事は、Linux Advent Calendar 2014 7日目の記事を2016/2/2に編集したものです。linux kernelをビルドする際に使用するmakeのターゲット(以下"makeターゲット"と記載)について、よく使われる便利なもの、面白いもの、小咄などの紹介を目的とします。本記事の執筆時点で、makeターゲットの数はゆうに50を超えますが、全部を網羅的に紹介するのではなく、適当にかいつまんで数個だけを紹介します。全てのターゲットについて知りたい方は、make helpコマンドの実行結果を参照してください。

本記事の調査に使用したkernelのバージョンは3.18-rc7です。本書の想定読者は、linux kernelをビルドしたことはあるけれども、makeターゲットの細かい話は知らないかたがたです。以下、それぞれのネタは個々に独立しているため、前から順番に読む必要はなく、興味のあるところだけ読んでくだされば問題ありません。

kernelビルド時間を短くしたい

linux kernelの設定項目は数千個も存在するため、どれを有効化/無効化すれば自分の環境でブートするkernelが出来上がるのかがわかりにくいです。様々な用途、環境向けに作成されたdistribution kernelの設定ファイルを流用すると、確かにブートはするものの、あなたが今後一生使うことがないような大量の機能、ドライバが組み込まれた巨大なkernelが出来上がってしまいます。そのビルド時間も長時間に及ぶため、そこから更に無効化可能な設定を逐一確かめていくのは、非常に面倒かつ困難です。

まず、distribution kernel の設定ファイルを流用した場合に、どれだけの設定項目が有効化されるかを見てみましょう。

 $ cd src/linux
 $ make kernelrelease
 scripts/kconfig/conf --silentoldconfig Kconfig
 3.18.0-rc7 # kernel source は v3.18-rc7 のもの
 $ uname -a
 Linux www2455ue 3.13-1-amd64 #1 SMP Debian 3.13.10-1 (2014-04-15) x86_64 GNU/Linux               # 現在動いているカーネル。これは debian/testing の distribution kernel
 $ cp /boot/config-$(uname -r) .config
 $ make olddefconfig                                     # 古い.conigをもとに、新しい項目はデフォルト値を設定
 scripts/kconfig/conf --olddefconfig Kconfig
 #
 # configuration written to .config
 #
  
 $ grep -c '^CONFIG_.*=[my]$' .config
 4168                                                    # 有効化されている設定項目は 4,000 個以上

そこで登場するのがlocalmodconigターゲットです。これは、既存の.configのうち、モジュールとしてビルドする設定になっているもの(CONFIG_*=m)について、make localmodconfig発行時にloadされていないmoduleをビルド対象から外してくれるという優れものです。これによって、あなたの環境でブートし、かつ、余計なモジュールが含まれないkernelを作成することができます。

以下、上記の実行例の続きです

 $ make localmodconfig
 ...                                                     # 新しい config について設定。気にしなければ適当にENTER連打でいい
 $ grep -c '^CONFIG_.*=[my]$' .config
 1028                                                    # 有効な設定項目数が 4,168 から 1,028 に、約 1/4 に減少。ビルド時間もそれに応じて大幅短縮可能。

以下、いくつか注意点と補足情報を紹介します。

  • kernelをビルドするシステム(以下「ビルドシステム」と記載)と、ビルドしたカーネルを動作させたいシステム(以下「ターゲットシステム」と記載)が異なる場合は、ターゲットシステムにおいてlsmodを採取した結果をファイル(ここでは lsmod.txt"とする)に保存しておき、ビルドシステムのkernelソースディレクトリにおいて"LSMOD=lsmod.txt make localmodconfig"コマンドを発行すればよい。わざわざターゲットシステムにkernelソースを持って行ってmake localmodconfigを発行する必要は無い。
  • "CONFIG_*=y"となっている設定項目については、localmodconigは残念ながら自動的に無効化しない。その理由は、これら設定項目に関する機能はkernelのバイナリに組み込まれてしまっているので、使用有無を自動的に判別する方法が無いため。必要ならば手動で設定する必要がある。参考までに、ktest("tools/testing/ktest")のminconfig機能によってを用いれば最小の.configを作れるようだが、筆者は未確認。
  • 本ターゲットの実行は、.configは、今現在動作中のkernel、あるいはそれより若干高いバージョンのものをベースにするのが無難。そうでないと、動作中のシステムのkernelとビルド対象kernelで名前が異なっているモジュールが存在する場合に、期待通りの動作をしないことがある。
  • "make localmodconig"実行時は、システムが普段使用している機能をすべて実行しておくほうがよい。たとえば、普段はNFSファイルシステムをmountしているが、"make localmodconfig"実行時は偶然それをmountしていなかったとする。この場合、コマンド発行時にはNFSのkernelモジュールがロードされていないため、.configのビルド対象からNFSが外されてしまうことがある。

kernelを全部ビルドするのではなく、自分が変更したソースのみ、コンパイルが通るかどうかを確認をしたい

自分で書いたkernel patchを適用したkernelのビルドが通らないことがよくあります。kernelビルドのために数十分待たされたあげく、「自分の追加した行の末尾にセミコロンが無かった」などという下らないバグによってビルドエラーが出ると、泣きたい気分になります。そのような事態を避けるために、linux kernelは特定ファイルのみをコンパイル可能です。たとえば"kernel/sched/core.c"というソースファイル(タスクスケジューラの中心部のソースファイル)のみを編集した場合は、"make kernel/sched/core.o"コマンドを発行すると、当該ファイルと、それが依存するファイルだけをコンパイルしてくれるため、ビルドエラーの有無を短時間で確認可能です。

特定の設定項目についての情報を得たい

make menuconfig.configの実行開始後に"/"(スラッシュ)を入力することによって、設定項目の検索機能を使用できます。そこで特定の設定項目を示す文字列を打ち込むと、当該項目に関する説明文、依存する設定項目、現在の設定値、menuconfigのメニューをどのように辿れば当該項目の設定画面に辿り着けるかがわかります。入力した文字列が複数の設定項目にマッチした場合は、マッチしたすべての項目についての情報が出力されます。

では、CONFIG_BTRFS_FS についての情報を参照したい場合の実行例を見てみましょう。

 $ make menuconfig

最初の画面

 .config - Linux/x86 3.18.0-rc7 Kernel Configuration                            
 qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq 
  lqqqqqqqqqqqqqqq Linux/x86 3.18.0-rc7 Kernel Configuration qqqqqqqqqqqqqqqk   
  x  Arrow keys navigate the menu.  <Enter> selects submenus ---> (or empty x   
  x  submenus ----).  Highlighted letters are hotkeys.  Pressing <Y>        x   
  x  includes, <N> excludes, <M> modularizes features.  Press <Esc><Esc> to x   
  x  exit, <?> for Help, </> for Search.  Legend: [*] built-in  [ ]         x   
  x lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk x   
  x x    [*] 64-bit kernel                                                x x   
  x x        General setup  --->                                          x x   
  x x    [*] Enable loadable module support  --->                         x x   
  x x    [*] Enable the block layer  --->                                 x x   
  x x        Processor type and features  --->                            x x   
  x mqqqqv(+)qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj x   
  tqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqu   
  x        <Select>    < Exit >    < Help >    < Save >    < Load >         x   
  mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj   

ここで "/"(スラッシュキー) を入力

 .config - Linux/x86 3.18.0-rc7 Kernel Configuration                            
 qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq 
                                                                                
                                                                                
  lqqqqqqqqqqqqqqqqqqqq Search Configuration Parameter qqqqqqqqqqqqqqqqqqqqqk   
  x  Enter (sub)string or regexp to search for (with or without "CONFIG_")  x   
  x lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk x   
  x x                                                                     x x   
  x mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj x   
  x                                                                         x   
  x                                                                         x   
  tqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqu   
  x                         <  Ok  >      < Help >                          x   
  mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj   

知りたい設定項目の名前、"CONFIG_BTRFS_FS" を入力

 .config - Linux/x86 3.18.0-rc7 Kernel Configuration                            
 qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq 
                                                                                
                                                                                
  lqqqqqqqqqqqqqqqqqqqq Search Configuration Parameter qqqqqqqqqqqqqqqqqqqqqk   
  x  Enter (sub)string or regexp to search for (with or without "CONFIG_")  x   
  x lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk x   
  x xCONFIG_BTRFS_FS                                                      x x   
  x mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj x   
  x                                                                         x   
  x                                                                         x   
  tqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqu   
  x                         <  Ok  >      < Help >                          x   
  mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj   

続けて画面上の "< OK >" を選択すると、CONFIG_BTRFS_FS についての情報が出力される。同じく検索文字列にマッチした "CONFIG_BTRFS_FS_CHECK_INTEGRITY" などについての情報も表示される。

 .config - Linux/x86 3.18.0-rc7 Kernel Configuration                            
 > Search (CONFIG_BTRFS_FS) qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq 
  lqqqqqqqqqqqqqqqqqqqqqqqqqqqq Search Results qqqqqqqqqqqqqqqqqqqqqqqqqqqqqk   
  x Symbol: BTRFS_FS [=m]                                                   x   
  x Type  : tristate                                                        x   
  x Prompt: Btrfs filesystem support                                        x   
  x   Location:                                                             x   
  x (1) -> File systems                                                     x   
  x   Defined at fs/btrfs/Kconfig:1                                         x   
  x   Depends on: BLOCK [=y]                                                x   
  x   Selects: CRYPTO [=y] && CRYPTO_CRC32C [=m] && ZLIB_INFLATE [=y] && ZL x   
  x                                                                         x   
  x                                                                         x   
  x Symbol: BTRFS_FS_CHECK_INTEGRITY [=n]                                   x   
  tqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq( 32%)qqu   
  x                                < Exit >                                 x   
  mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj   
                                                                                

いつも、このような情報を確認する際に Kconfig ファイルを grep していたようなかたは、大きく時間が節約できるはずです。

ビルドしたkernelをrpmdebなどのパッケージ管理システムで管理したい

普通にkernelをビルドした場合、つまり、ターゲット指定なしでmakeコマンドを実行した場合、開発者は、distributionが提供するパッケージ管理システムを使うことなく、手動、ないし"make install"を用いてkernelをインストール/アンインストールする必要があります。管理が面倒などという理由でこれが不満なかたは、"make deb-pkg"、あるいは"make rpm-pkg"コマンドを発行すると、それぞれ.deb形式、.rpm形式のkernelパッケージを作成することができます。

linux kernelの新しいテスト用フレームワーク

自分でkernelを作った場合(とくにソースに変更を加えた場合)、そのカーネルを実際に動作させる前にテストをする必要があります(ビルドすら通らないkernel patchをLKMLに投げてくる人も稀にいますが…)。これまでkernelのテストには、バグ報告者や開発者が自作したテスト、LTP,およびxfstestsなどの様々なものが使われてきました。

kernel-3.17からは、カーネル自身がテスト用のフレームワークを持つようになりました。"make kselftests"コマンドを発行すると、tools/testing/selftests以下のテストが流れます。このフレームワークは、まだ出来たばかりなこともあり、どれだけ普及するかは現在のところまだ未知数ですが、いずれは多くの/すべての開発者が使うようになるかもしれません。他のテスト用ツールに比べて、変化の早いkernelそのものに同梱されているというのは大きな強みといえるでしょう。

変な名前のターゲット

"make mrproper" は、kernelソースのソース変更やビルドに伴い様々なファイルが新規に作成された状態において、kernelソースにもともと含まれていたファイル以外ほとんど全て(たとえば.config, .o, .ko, やkernelのバイナリ)を消去するmake ターゲットです。その機能自身はいいとして、この変な名前はどういう意味があるのでしょうか。

これは、P&Gのクリーニング製品のマスコットキャラクター、Mr. Properが由来だそうです。こういう特定の文化に依存した"うまいこと言ってる"系のネタは、その文化の外の人から見ると、なかなかわかりにくいところです。

余談ですが、日本ではこの手のマスコットには可愛いキャラ、萌えキャラ、ゆるキャラなどが採用されそうなものですが、Mr. Properは上記リンク先のイラストにあるように、ムキムキマッチョなスキンヘッドの親父です。文化の違いをひしひしと感じます。

最後に

本記事で紹介したもの以外にも、makeターゲットには便利なもの、面白いものがたくさんあります。また、makeターゲットは、比較的頻繁に更新されるため、しばらく確認を怠っていると、いつのまにか見慣れないものが追加されていることがよくあります。たまにはmake helpを眺めてみて、面白そうなものがあれば試してみるのもよいかもしれません。

おわり。最後まで見て頂いて、ありがとうございました