[Linux] kernel version string

Linux kernel の version 表記がどのようにして生成されているのかよく分からなかったので調べてみました。

kernel version の文字列

kernel version は major version, patchlevel, sublevel (開発バージョンはさらに extraversion) から成り、それぞれ linux/Makefile に記載されています。"make kernelversion" でそれらを表示します。

$ head -5 Makefile
VERSION = 4
PATCHLEVEL = 13
SUBLEVEL = 0
EXTRAVERSION = -rc7
NAME = Fearless Coyote
$ make kernelversion
4.13.0-rc7

kernel release version の文字列はどうやって決まる?

release version は kernel version に加えてビルド時のリポジトリ情報を追加したもので、 "make releaseversion" で表示します。config 情報を使うので、先に config を実行しておく必要があります。

$ make ARCH=arm64 defconfig
$ make ARCH=arm64 kernelrelease
4.13.0-rc7-01000-gXXXXXXX-dirty

これは linux/scripts/setlocalversion の実行結果で、config の内容とリポジトリの情報を反映しています。影響する config は CONFIG_LOCALVERSION_AUTO と CONFIG_LOCALVERSION です。

CONFIG_LOCALVERSION_AUTO によって大きく動作が異なるため、それぞれについて説明します。"make menuconfig" では以下で設定します。

"General setup   --->
  [*] Automatically append version information to the version string
CONFIG_LOCALVERSION_AUTO=y の場合

次の文字列を連結したものが localversion 文字列になります。

  • linux/localversion* のファイルがあればその文字列
  • CONFIG_LOCALVERSION で定義された文字列
  • 環境変数 LOCALVERSION で定義された文字列
  • リポジトリ情報
  • ローカル変更があった場合の "-dirty"

linux/localversion* ファイルは自分で作成したものです。ファイル名は linux/localversion-hoge でも何でもよいですが、ワイルドカードの評価順に文字列が続きます。

$ cat localversion
-localv1.0
$ cat localversion-foo
-FOO
$ cat localversion-bar
-BAR
$ cat localversion-hoge
-HOGE
$ make ARCH=arm64 kernelrelease
4.13.0-rc7-localv1.0-BAR-FOO-HOGE-01000-gXXXXXXX-dirty

CONFIG_LOCALVERSION は .config で定義される文字列です。"make menuconfig" では以下で設定します。

"General setup   --->
  () Local version - append to kernel release

環境変数 LOCALVERSION は make 実行時に定義されていたものが有効になります。

$ LOCALVERSION=-TMP make ARCH=arm64 kernelrelease
4.13.0-rc7-TMP-01000-gXXXXXXX-dirty

リポジトリ情報は、"git describe --dirty" の結果が適用されます。

annotated tag の付いた commit (通常 kernel version の更新ポイント) から commit の適用数(5桁)と、現在の commit ID が文字列となります。

"-01000-gXXXXXXX" の場合、kernel version から 1000 個の commit が適用され、現在 commit ID が XXXXXXX のリポジトリを使っていることになります。

ソースは変更されているがリポジトリに反映されていない場合、最後に "-dirty" が付きます。

これらを全部適用すると以下のようになります(長い...)。

$ grep LOCALVERSION .config
CONFIG_LOCALVERSION="-TEST"
CONFIG_LOCALVERSION_AUTO=y
$ cat localversion
-localv1.0
$ cat localversion-foo
-FOO
$ cat localversion-bar
-BAR
$ cat localversion-hoge
-HOGE
$ LOCALVERSION=-TMP make ARCH=arm64 kernelrelease
4.13.0-rc7-localv1.0-BAR-FOO-HOGE-TEST-TMP-01000-gXXXXXXX-dirty

linux/scripts/setlocalversion を都度適用する代わりに、予め linux/scripts/setlocalversion  の結果を保存した文字列を適用することもできます。
以下を実行すると linux/.scmversion に保存され、この文字列が常に適用されます。

$ ./script/setlocalversion --save-scmversion .
CONFIG_LOCALVERSION_AUTO is not set の場合

次の文字列を連結したものが localversion 文字列になります。上の3つは "CONFIG_LOCALVERSION=y" と同じです。

  • linux/localversion* のファイルがあればその文字列
  • CONFIG_LOCALVERSION で定義された文字列
  • 環境変数 LOCALVERSION で定義された文字列
  • (LOCALVERSION がない場合) リポジトリ更新を示す "+"

環境変数 LOCALVERSION が定義されていなければ、リポジトリが kernel version から更新されているかを示す "+" が付きます。

環境変数 LOCALVERSION が定義されていればその文字列だけが付きます。LOCALVERSION を空定義すると何も付かないことになります。

$ make ARCH=arm64 kernelrelease
4.13.0-rc7+
$ LOCALVERSION=-TMP make ARCH=arm64 kernelrelease
4.13.0-rc7-TMP
$ LOCALVERSION= make ARCH=arm64 kernelrelease
4.13.0-rc7

release version と kernel module

kernel module は install directory に release version が付く(/lib/modules/<release-version>) ため、気づかないうちに version 文字列が変わっててトラブルの原因になることがあります。そのため、module 開発者はどの文字列が kernel の何の設定で付与されているのかを正しく理解しておく必要があります。


コメント

タイトルとURLをコピーしました