はじめに
この記事の目的
Linux のカーネルモジュールを Linux のカーネルツリー内に追加してビルドする際の Makefile の書き方と
カーネルツリーの外からビルドする際の Makefile の書き方は微妙に違っています。
Makefile をカーネルツリー内用とカーネルツリー外用と個別に用意するのもなんだか面倒です。
そこでこの記事では Linux カーネルモジュールの Makefile をカーネルツリー内外兼用にする方法について説明します。
既存の Makefile の説明
まず、この節で、カーネルツリー内に追加してビルドする際の Makefile と カーネルツリーの外からビルドする際の Makefile の特徴について簡単に説明します。
カーネルツリー内に追加してビルドする際の Makefile と Kconfig
Linux のカーネルツリーにすでに組み込まれているカーネルモジュールの Makefile はだいたい次のようになっています。
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_SAMPLE) += sample.o
上の Makefile で参照されている CONFIG_SAMPLE は Makefile と同じディレクトリにある Kconfig で次のように定義されているとします。
# SPDX-License-Identifier: GPL-2.0-only
menuconfig SAMPLE
tristate "This is Sample Kernel Module"
help
Enable this to allow the sample kernel module to be built.
If you don't know what to do here, say N.
上記の Makefile と Kconfig を次のようにして上位のディレクトリ(この例では drivers/staging/
) にある Makefile と Kconfig に追加しておきます。
# :
# (前略)
# :
obj-$(CONFIG_SAMPLE) += sample/
# :
# (前略)
# :
source "drivers/staging/sample/Kconfig"
こうしておけば、Linux Kernel のビルド時に make menuconfig でメニューの Staging drivers に SAMPLE の項目が追加されるので m
や y
を指定することができるようになります。
また、直接 defconfig ファイルに CONFIG_SAMPLE=m
や CONFIG_SAMPLE=m
を書いておいてもいいでしょう。
カーネルツリー外でビルドする際の Makefile
Linux のカーネルモジュールをカーネルのソースの外でビルドする際、たいてい次のような Makefile を使います。
#
# For in kernel tree variables
#
obj-m := sample.o
#
# For out of kernel tree variables
#
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
#
# For out of kernel tree rules
#
all:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD)
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
この Makefile の説明は、前回の記事『Linux カーネルモジュールの Makefile は二度呼ばれる』@Qiita を参照してください。
余段ですが、もともと前回の記事は今回の記事の一部だったのですが、ちょっと記事の量が多かったので別々にした経緯があります。
Makefile をカーネルツリー内外兼用にする
まず、カーネルツリー外でビルドする際の Makefile の 変数 obj-m
の名前を obj-$(CONFIG_SAMPLE)
に変更します。(さらに 代入演算子を :=
から +=
に変更します。)
こうすることで、この Makefile をカーネルツリー内に直接置いて、Kconfig と連動することができるようになります。
ただし、変数 obj-m
の名前を obj-$(CONFIG_SAMPLE)
に変更しただけでは、今度はカーネルツリー外でビルドすることが出来ません。
何故なら、前回の記事『Linux カーネルモジュールの Makefile は二度呼ばれる』@Qiitaで説明したようにこの Makefile は二度読まれるのですが、CONFIG_SAMPLE
が定義されていないので、二度目に Makefile の読み込まれた際に obj- += sample.o
と解釈されてしまい、ビルド対象から外れるからです。
そこで make -C $(KERNEL_SRC) M=$(PWD)
を実行する際の文に CONFIG_SAMPLE=m
を追加しておきます。
こうすることで、二度目に Makefile の読み込まれた際に obj-m += sample.o
と解釈され、カーネルモジュールとしてビルドされます。
#
# For in kernel tree variables
#
obj-$(CONFIG_SAMPLE) += sample.o
#
# For out of kernel tree variables
#
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
#
# For out of kernel tree rules
#
all:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) CONFIG_SAMPLE=m
modules_install:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) CONFIG_SAMPLE=m modules_install
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) CONFIG_SAMPLE=m clean
さらに Makefile を Yocto に対応する?
あと、これは未確認ですが、Yocto (Petalinux) でカーネルモジュールをビルドする際には、カーネルソースのディレクトリが変数
KERNEL_SRC
に設定されているようです。
したがって、make -C
で指定するカーネルソースのパスに $(KERNEL_SRC)
を参照するようにしておけば Yocto (Petalinux) でも、この Makefile が使えるようです。
私は Yocto (Petalinux) を使っていないので分からないですが、udmabuf の issue によると、どうやらいけるようです。
余談ですが、もともとこの記事を書こうと思ったのは、上の issue に触発されて、udmabuf の Makefile を見直したためでした。おかげさまで Linux カーネルモジュールの Makefile について少し理解が深まりました。issue をくれた方には感謝です。