Linux2.6カーネルMakefileの分析

1。概要

Makefileは5つの部分で構成されています。

  • Makefile:ルートディレクトリMakefile。.configファイルを読み取り、vmlinux(カーネルイメージ)とモジュール(モジュールファイル)の作成を担当します。
  • .config:カーネル構成ファイル(通常はmake menuconfigによって生成されます)。
  • arch/$(ARCH)/Makefile:ターゲットプロセッサのMakefile。
  • scripts/Makefile.*:すべてのkbuild Makefileルール、定義/ルールなどが含まれます。
  • kbuild Makefiles:各サブディレクトリには、組み込みまたはモジュラーターゲットの生成を担当するkbuildMakefileがあります。(注:kbuild Makefileは、kbuild構造を使用するMakefileを指し、カーネル内のほとんどのMakefileはkbuild Makefileです。)

2.kbuildファイル

2.1。obj-y和obj-m

最も単純なkbuildMakefileには、次のもののみを含めることができます。

obj-$(CONFIG_FOO) += foo.o

これ$(CONFIG_FOO)はyまたはmと等しくなる可能性があり、その値は.configファイルによって指定されます。$(CONFIG_FOO)yでもmでもない場合、ファイルはコンパイルおよびリンクされません

$(CONFIG_FOO)yに等しい場合、上記のステートメントはobj-y + = foo.oと同等であり、現在のディレクトリにfoo.oというオブジェクトファイルがあり、foo.cまたはfoo.Sからコンパイルされることをkbuildに通知します。 。

それは場合$(CONFIG_FOO)Mに等しく、それはfoo.oのニーズをモジュールにコンパイルすることを意味します。

2.1.1。obj-y生成組み込み.o

Kbuildはすべての$(obj-y)ファイルをコンパイル"$(LD) -r"し、これらすべてのファイルをbuilt-in.oファイルにマージするために呼び出します。このbuilt-in.oは、上位ディレクトリのMakefileによって使用され、最終的にvmlinuxにリンクされます。

2.1.2。ターゲットは複数のソースファイルからコンパイルされます

ターゲットが複数のソースファイルからコンパイルされている場合は、$(<module_name>-objs)または$(<module_name> -y)を使用しこれらのソースファイルkbuildに指示できます。Kbuildは、サフィックス-objsおよび-yを認識できます。次に例を示します。

#drivers/isdn/i4l/Makefile
obj-$(CONFIG_ISDN) += isdn.o
isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o

Kbuildは、その中のすべて$(isdn-objs)のオブジェクトをコンパイルし"$(LD) -r"それらを呼び出してisdn.oファイルにリンクします。

以下は、接尾辞-yの使用例です。接尾辞-yの利点は、CONFIG_XXXシンボルを使用して、いくつかのソースファイルを追加するかどうかを決定できることです(.oは対応する.cまたは.Sからコンパイルされます)。

#fs/ext2/Makefile
obj-$(CONFIG_EXT2_FS)        += ext2.o
ext2-y                       := balloc.o bitmap.o
ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o

2.1.3。サブディレクトリMakefileを呼び出す

Makefileは、現在のディレクトリ内のオブジェクトのコンパイルのみを担当します。サブディレクトリ内のオブジェクトは、サブディレクトリ内のMakefileを担当します。サブディレクトリのMakefileをmake呼び出しさせる方法は?答えは、obj-yまたはobj-mにサブディレクトリを含めることです。例えば:

#fs/Makefile
obj-$(CONFIG_EXT2_FS) += ext2/

CONFIG_EXT2_FSがyまたはmの場合、kbuildシステムはext2ディレクトリでmakeコマンドを呼び出します(つまり、ext2ディレクトリでMakefileを呼び出します)。

2.2。lib-y和lib-m

ディレクトリには、obj-yリストされたファイルをにコンパイルされbuilt-in.oたファイル、およびlib-y或lib-mリストされたファイルは、カレントディレクトリに生成されますlib.a

注意:一般lib-y或lib-m只用在lib/和arch/*/lib这两个目录中。

2.3。コンパイラオプション変数

2.3.1。ccflags-y、asflags-y、ldflags-y

これらの3つの変数は、現在のMakefileでのみ有効です。補足:これ$(KBUILD_CFLAGS)はルートディレクトリMakefileで定義された変数であり、コアの総数に適用されます。

2.3.2。subdir-ccflags-y、subdir-asflags-y

これらの2つの変数は、現在のMakefileとそのすべてのサブディレクトリに作用します。

2.3.3。CFLAGS _ $ @、AFLAGS _ $ @

これらの2つの変数は、現在のMakefileでのみ有効です。$ @を使用してファイル名を指定できるため、ファイルごとに異なるコンパイルオプションを使用できます。例えば:

# drivers/scsi/Makefile
CFLAGS_aha152x.o =   -DAHA152X_STAT -DAUTOCONF
CFLAGS_gdth.o    = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ /
                     -DGDTH_STATISTICS
CFLAGS_seagate.o =   -DARBITRATE -DPARITY -DSEAGATE_USE_ASM

2.4。$(src)、$(obj)、$(kecho)

$(src)現在のMakefieディレクトリの相対パスをポイントします。$(obj)ターゲットファイルの保存に使用される相対ディレクトリをポイントします。例は次のとおりです。

#drivers/scsi/Makefile
$(obj)/53c8xx_d.h: $(src)/53c7,8xx.scr $(src)/script_asm.pl
       $(CPP) -DCHIP=810 - < $< | ... $(src)/script_asm.pl

ここで$(src)は、drivers / scsi /に等しく、drivers / scsi /に$(obj)も等しくなります。

“make -s”コマンドを使用すると、警告メッセージとエラーメッセージのみが出力されます。$(kecho)「make-s」を使用しない場合は、次のコンテンツを標準出力ストリーム(通常はディスプレイ)に出力できます。例は次のとおりです。

#arch/blackfin/boot/Makefile
$(obj)/vmImage: $(obj)/vmlinux.gz
       $(call if_changed,uimage)
       @$(kecho) 'Kernel: $@ is ready'

2.5。$(CC)関連の関数

2.5.1。as-option、ld-option、cc-option

ファイルをコンパイルおよびリンクするときに、xx-opitonを使用して$(CC)現在使用されているコンパイルオプションがサポートされいるかどうかを確認できます前者がサポートされていない場合は、後者を使用できます。例えば:

#arch/sh/Makefile
cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),)

現在のものが$(CC)サポートされていない場合は-Wa$(comma)-isa=$(isa-y)、2番目のコンパイルオプション(ここでは空)を使用できます。

2.5.2。cc-option-in

cc-option-ynは$(CC)、指定されたコンパイラオプションがサポートされているかどうかを確認するために使用されます。サポートされている場合はyを返し、サポートされていない場合はnを返します。例えば:

#arch/ppc/Makefile
biarch := $(call cc-option-yn, -m32)
aflags-$(biarch) += -a32
cflags-$(biarch) += -m32

2.5.3。cc-option-align

3.0以降、gccは、指定された関数やループなどの配置オプションのタイプを変更しました。gcc <3.00の場合、cc-option-align = -malign; gcc> = 3.00の場合、cc-option-align = -falign。$(cc-option-align)を使用して、正しいプレフィックスを選択します。例えば:

KBUILD_CFLAGS += $(cc-option-align)-functions=4

2.5.4。cc-version、cc-ifversion、cc-fullversion

cc-versionはバージョンを返します$(CC)それは場合$(CC)はgcc 3.41で、その後、CC-バージョンは0341を返します。例えば:

#arch/i386/Makefile
cflags-y += $(shell /
if [ $(call cc-version) -ge 0300 ] ; then /
        echo "-mregparm=3"; fi ;)

cc-ifversionは、バージョンが条件を満たしている場合、最後のパラメーターを返します。例は次のとおりです。

#fs/reiserfs/Makefile
ccflags-y := $(call cc-ifversion, -lt, 0402, -O1)

$(CC)バージョンが4.2未満の場合、ccflags-yは-O1に等しくなります。

cc-fullversionは、より詳細なバージョン情報を提供します。次に例を示します。

#arch/powerpc/Makefile
$(Q)if test "$(call cc-fullversion)" = "040200" ; then /
       echo -n '*** GCC-4.2.0 cannot compile the 64-bit powerpc ' ; /
       false ; /
fi

2.5.5。cc-クロスプレフィックス

cc-cross-prefix指定されたプレフィックス$(CC)が存在するかどうかを確認するために使用されます。存在する場合は、最初に一致するプレフィックスを返します。存在しない場合は、空を返します。複数のプレフィックスを一致させる必要がある場合は、単一のスペースを使用して各プレフィックスを区切ります。例えば:

#arch/m68k/Makefile
ifneq ($(SUBARCH),$(ARCH))
      ifeq ($(CROSS_COMPILE),)
           CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu-)
      endif
endif

(注:本文所述内容来自kernel-2.6.30/Documentation/kbuild/makefiles.txt,适用于Linux 2.6内核)

3.Linuxカーネルコンパイルシステム

Linuxカーネル2.6以降、Kbuildシステムを使用してLinuxカーネルをコンパイルします。これは、特にLinuxカーネルモジュールのコンパイルでは、以前のコンパイルシステムとは大きく異なります。新しいシステムでは、LinuxビルドシステムはLinux Makefileを2回スキャンします。最初に、ビルドシステムはLinuxカーネルの先頭にあるMakefileを読み取り、次にKbuild Makefileをもう一度読み取って、何に基づいてLinuxカーネルをコンパイルします。読みます。

3.1.LinuxカーネルのMakefile分類

  • カーネルMakefile
    カーネルMakefileは、Linuxカーネルソースコードのトップディレクトリにあり、トップメイクファイルとも呼ばれます。これは主に、Linuxカーネルオブジェクトファイル(vmlinux)およびモジュール(モジュール)を指定およびコンパイルするために使用されます。カーネルまたはモジュールをコンパイルするとき、このファイルが最初に読み取られ、コンパイル環境変数は読み取られた内容に従って構成されます。カーネルまたはドライバーの開発者にとって、このファイルはほとんど変更する必要がありません。

  • Kbuild Makefile
    Kbuildシステムは、KbuildMakefileを使用してカーネルまたはモジュールをコンパイルします。カーネルMakefileが解析されると、Kbuildは関連するKbuild Makefileを読み取って、1つまたは複数のカーネルをコンパイルします。Kbuild Makefileには、カーネルにコンパイルされるもの、モジュールにコンパイルされるもの、および対応するソースファイルを指定するための特定の構文があります。カーネルとドライバーの開発者は、このKbuildMakefileを作成する必要があります。

  • ARCH Makefile
    ARCH Makefileは、プラットフォームに対応するシステムのMakefileであるARCH / $(ARCH)/ Makefileにあります。Kernel Top Makefileには、プラットフォーム関連の情報を指定するためにこのファイルが含まれます。プラットフォーム開発者だけがこのファイルを気にします。

3.2。Kbuild Makefile

Kbuild Makefileのファイル名は必ずしもMakefileである必要はありませんが、Makefileという名前をお勧めします。ほとんどのKbuildファイルの名前はMakefileです。他のMakefileファイルと区別するために、KbuildMakefileの名前をKbuildとして指定することもできます。また、「Makefile」ファイルと「Kbuild」ファイルが同時に存在する場合、Kbuildシステムは「Kbuild」ファイルを使用します。

  • ターゲット定義
    KbuildMakefileの主な関数の1つは、何をコンパイルするかを指定することです。この関数は、次の2つのオブジェクトによって指定されるobj-?およびxxx-objsです。

    • obj-?
      obj-?何をコンパイルし、どのようにコンパイルするかを指定しますか?「?」は「y」または「m」の場合があり、「y」はオブジェクトがカーネルにコンパイルされることを指定し、「m」はオブジェクトがモジュールにコンパイルされることを指定します。構文は次のとおりです
      obj-? = $(target).o
      。targetはコンパイルされたオブジェクトの名前です。指定しない場合xxx-objs、このオブジェクトのコンパイルに必要なソースファイルは$(target).c或$(target).sです。指定されている場合$(target)-objs、このオブジェクトをコンパイルするために必要なソースファイルはファイルによって$(target)-objs指定さ不能有$(target).c 或$(target).sます。

    • xxx-objs
      xxx-objsは、コンパイルされたオブジェクトに必要なファイルを指定します。通常、複数のソースファイルがある場合にのみ必要です。

    これらの2行が含まれている限り、KbuildMakefileは機能するはずです。

  • ネストされたコンパイル
    オブジェクトが別のオブジェクトのディレクトリに埋め込まれている場合があるので、サブディレクトリ内のオブジェクトをコンパイルするにはどうすればよいですか?実際、指定されたobj_?オブジェクトがサブディレクトリの名前である限り、これは非常に単純
    obj-? = $(sub_target)/
    ですここで、「?」は「y」または「m」($(sub_target)サブディレクトリの名前)にすることができます

  • コンパイラオプション
    ほとんどの場合、コンパイラオプションを指定する必要はありませんが、一部のコンパイラオプションを指定する必要がある場合もあります。

    • ccflags-y、asflags-y、およびldflags-y
      これらのコンパイルオプションは、cc、as、およびldのコンパイルオプションを指定するために使用されます。

3.3。外部モジュールをコンパイルする

カーネルソースツリーの外部でカーネルモジュールをコンパイルする必要がある場合があります。コンパイルの基本的なコマンドは次のとおりです。

make -C $(KERNEL_DIR) M=`pwd` modules

このコマンドをMakefileに統合して、「make」コマンドを入力するだけで済みます。前の章のMakefileを思い出してください。これは、NormalMakefileとKbuildMakefileを1つのファイルに統合します。KbuildMakefileと通常のMakefileを区別するために、Makefileを次の形式に書き換え、KbuildMakefile-「Kbuild」を追加します。

##Makefile
ifneq ($(KERNELRELEASE),)
include "Kbuild"
else
KERNEL_DIR = /lib/modules/`uname -r`/build
MODULEDIR := $(shell pwd)
.PHONY: modules
default: modules
modules:
        make -C $(KERNEL_DIR)  M=$(MODULEDIR) modules
clean distclean:
        rm -f *.o *.mod.c .*.*.cmd *.ko
        rm -rf .tmp_versions
endif

## Kbuild Makefile

## Kbuild
MODULE_NAME = helloworld
$(MODULE_NAME)-objs := hello.o
obj-m   := $(MODULE_NAME).o

通常、古いバージョンのKbuildシステムと互換性を持たせるために記述されたMakefileに次のコードを含める必要はありません。KERNELRELEASE変数はカーネルMakefileで定義されているため、KbuildのコンテンツはMakefileがKbuildによって2回目に読み取られたときにのみ解析されます。

ifneq ($(KERNELRELEASE),)
include "Kbuild"
else
...
endif

外部ヘッダーファイル
カーネルソースコードの外部でシステムヘッダーファイルを接続する必要がある場合がありますが、Kbuildシステムのデフォルトのシステムヘッダーファイルはカーネルソースコードの内部にあります。外部ヘッダーファイルの使用方法は?これは、Kbuildシステムの特別なルールを使用して実行できます。

  • EXTRA_CFLAGS
    EXTRA_CFLAGSは、外部システムヘッダーファイルをKbuildシステムに追加できます。
    EXTRA_CFLAGS += $(ext_include_path)
    通常、外部ヘッダーファイルは外部モジュールソースファイルのディレクトリにあります。どのように指定しますか?これは、$(src)またはの助けを借りて行うことができます$(obj)
  • $(src)/ $(obj)
    $(src)は相対パスであり、Makefile / Kbuildファイルが配置されているパスです。同じこと$(obj)がコンパイルターゲットが保存されるパスであり、デフォルトはソースコードが配置されているパスです。

おすすめ

転載: blog.csdn.net/houxiaoni01/article/details/103561563