2012年4月5日木曜日
2012年3月30日金曜日
2012年3月1日木曜日
アセンブラのローカルラベル
GNU ld のローカルラベルについて。
ローカルラベルで
b がつくと前方へ検索、f がつくと後方へ検索の意味になる。例えば、ARMで
1:
b 1b
1:
というコードは前の1: へ分岐する。(つまり無限ループ)
1:
b 1f
1:
は後ろの1:へ分岐する。では、
b も f も付けずに、
1:
b 1
1:
はどうなるかというと、アドレス「1」へ分岐という意味になるみたい。(ですが、pc は4の倍数でないといけないので、アドレス「0」へ分岐になる。)
2012年2月24日金曜日
C言語のswitch文で ...
Linux のコードを見ていると、こんな書き方もできるのかぁ、というものに出くわすことがありますね。
例えば、
arch/arm/mach-rpc/irq.c にある、以下のようなコード。
switch (irq) {
case 0 ... 7:
irq_set_chip_and_handler(irq, &iomd_a_chip,
handle_level_irq);
set_irq_flags(irq, flags);
break;
case 8 ... 15:
irq_set_chip_and_handler(irq, &iomd_b_chip,
handle_level_irq);
set_irq_flags(irq, flags);
break;
case 16 ... 21:
irq_set_chip_and_handler(irq, &iomd_dma_chip,
handle_level_irq);
set_irq_flags(irq, flags);
break;
case 64 ... 71:
irq_set_chip(irq, &iomd_fiq_chip);
set_irq_flags(irq, IRQF_VALID);
break;
}
「...」で範囲指定できるらしい。見た時びっくりしました。
例えば、
arch/arm/mach-rpc/irq.c にある、以下のようなコード。
switch (irq) {
case 0 ... 7:
irq_set_chip_and_handler(irq, &iomd_a_chip,
handle_level_irq);
set_irq_flags(irq, flags);
break;
case 8 ... 15:
irq_set_chip_and_handler(irq, &iomd_b_chip,
handle_level_irq);
set_irq_flags(irq, flags);
break;
case 16 ... 21:
irq_set_chip_and_handler(irq, &iomd_dma_chip,
handle_level_irq);
set_irq_flags(irq, flags);
break;
case 64 ... 71:
irq_set_chip(irq, &iomd_fiq_chip);
set_irq_flags(irq, IRQF_VALID);
break;
}
「...」で範囲指定できるらしい。見た時びっくりしました。
gcc のマニュアルを参照すると
http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/C-Extensions.html#C-Extensions
これはGNU 拡張機能らしいです。
(Case Ranges: `case 1 ... 9' and such. )
gcc に -pedantic をつけると非標準機能を使っていると警告してくれるみたい。
ポータビリティを気にする場合は便利かも。
上のような書き方をすると
警告: range expressions in switch statements are non-standard
という風に warning 出してくれました。
http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/C-Extensions.html#C-Extensions
これはGNU 拡張機能らしいです。
(Case Ranges: `case 1 ... 9' and such. )
gcc に -pedantic をつけると非標準機能を使っていると警告してくれるみたい。
ポータビリティを気にする場合は便利かも。
上のような書き方をすると
警告: range expressions in switch statements are non-standard
という風に warning 出してくれました。
2012年2月23日木曜日
UNK/SBZP
ARM ARM (ARM Architecture Reference Manual) で UNK/SBZP という用語が頻発していて、何の略だろうと思ったら、
UKNOWN on reads, Should-Be-Zero-or-Preserved on writes.
のことらしい。
レジスタのreserved ビットに対する、ソフトでの扱い方を述べているようです。
reserved ビットは、0読み出し、書き込み無視のようにハードではたぶん実装しているはずだが、ソフトはそれを期待するなということだと思います。
UKNOWN on reads, Should-Be-Zero-or-Preserved on writes.
のことらしい。
レジスタのreserved ビットに対する、ソフトでの扱い方を述べているようです。
reserved ビットは、0読み出し、書き込み無視のようにハードではたぶん実装しているはずだが、ソフトはそれを期待するなということだと思います。
2012年2月13日月曜日
LinuxカーネルのMakefileを解析する その6
今回は、Linuxカーネルのmakeシステムの肝とも言える、drivers/, kernel/, fs/ などといったディレクトリを階層的に降りていきながら、各階層に置かれたMakefile(またはKbuild)ファイルをparseする仕組みを解明してみたいと思います。
ちなみに、各ディレクトリ階層に置く Makefileの書き方は
Documentation/kbuild/makefile.txt
に解説がありますが、ここでもちょこっと解説しておきます。
各階層のオブジェクトはMakefile の中で obj-y += hoge.o のようにobj-y変数に追加します。
また、 obj-y += piyo/ のようにディレクトリを追加すると、サブディレクトリに降りるという意味になります。
オブジェクトはディレクトリごとに built-in.o というファイルにまとめられます。
例で示した方がいいかもしれないですね。
以下のようにディレクトリ階層があって、各階層ごとに cのソースと Makefileがあったとする。
hoge
├── Makefile
├── hoge.c
└── piyo
├── Makefile
├── fuga
│ ├── Makefile
│ ├── fuga1.c
│ └── fuga2.c
└── piyo.c
Makefileにはその階層の オブジェクトと一つ下のディレクトリを記載します。
hoge/Makefileの内容:
hoge/piyo/Makefileの内容:
hoge/piyo/fuga/Makefileの内容:
みたいに書いておく。
このとき、 各階層の.o は .c ファイルをコンパイルして作られます。
さらに、
hoge/piyo/fuga/fuga1.o と hoge/piyo/fuga/fuga2.oは ld -r でまとめられて、
hoge/piyo/fuga/build-in.o になります。
さらに、
hoge/piyo/fuga/built-in.o と hoge/piyo/piyo.o がまとめられて hoge/piyo/built-in.oになる。
さらに、
hoge/piyo/built-in.o と hoge/hoge.o がまとめられて、hoge/built-in.o になる。
hoge/built-in.o は他のオブジェクトとトップレベルでリンクされて カーネルイメージになるという具合です。
今回解読するファイルはトップのMakefileとscripts/Makefile.build, scripts/Makefile.lib あたりです。
まず、トップのMakefileの500行目付近にある
に注目します。これが、これから降りていこうとするトップ階層のディレクトリ達です。
さらに700行目付近に以下のように書いてあります。
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
$(net-y) $(net-m) $(libs-y) $(libs-m)))
vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
$(init-n) $(init-) \
$(core-n) $(core-) $(drivers-n) $(drivers-) \
$(net-n) $(net-) $(libs-n) $(libs-))))
init-y := $(patsubst %/, %/built-in.o, $(init-y))
core-y := $(patsubst %/, %/built-in.o, $(core-y))
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
net-y := $(patsubst %/, %/built-in.o, $(net-y))
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)
vmlinux-init := $(head-y) $(init-y)
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux-all := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds := arch/$(SRCARCH)/kernel/vmlinux.lds
これをふまえて、
$ make vmlinux
としたときに何が起きるかを見てみます。
vmlinuxの構築ルールは900行目付近にあります。
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
ifdef CONFIG_HEADERS_CHECK
$(Q)$(MAKE) -f $(srctree)/Makefile headers_check
endif
ifdef CONFIG_SAMPLES
$(Q)$(MAKE) $(build)=samples
endif
ifdef CONFIG_BUILD_DOCSRC
$(Q)$(MAKE) $(build)=Documentation
endif
$(call vmlinux-modpost)
$(call if_changed_rule,vmlinux__)
$(Q)rm -f .old_version
vmlinuxはリンカースクリプト$(vmlinux-lds)の他、$(vmlinux-init) $(vmlinux-main)といったオブジェクトに依存しています。
これらをリンクすることで vmlinuxができます。
$(vmlinux-init) $(vmlinux-main) はほとんどは、トップ階層のディレクトリに /built-in.o をつけたものです。
で、*/built-in.o はどうやって作るかというと、
# The actual objects are generated when descending,
# make sure no implicit rule kicks in
$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
の行です。$(vmlinux-dirs) というディレクトリにだけ依存しています。
$(vmlinux-dirs) の構築ルールは以下です。
PHONY += $(vmlinux-dirs)
$(vmlinux-dirs): prepare scripts
$(Q)$(MAKE) $(build)=$@
前回説明したように、build というのは
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
のことでした。
ここからは、Makefile.build を呼び出して、ディレクトリを降りていく処理です。
例えば、
$ make drivers
とやると、 drivers/ ディレクトリを降りて行ってくれます。
ここからは scripts/Makefile.build の解析です。
例えば、 make -f scripts/Makefile.build obj=drivers
とした場合です。
src := $(obj)
でobjの値(drivers)がsrcにコピーされる。
40行目付近で、
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)
とありまして、$(obj)/Makefile がinclude されます。
ここを抜けてきたときに、obj-y にリンク対象のオブジェクトファイルと、サブディレクトリが入っています。
その下に
include scripts/Makefile.lib
とありまして、Makefile.lib の中で obj-y を加工します。
関係ある部分だけを抜き出すと、、
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y += $(__subdir-y)
...
obj-y := $(patsubst %/, %/built-in.o, $(obj-y))
...
subdir-ym := $(sort $(subdir-y) $(subdir-m))
...
# tell kbuild to descend
subdir-obj-y := $(filter %/built-in.o, $(obj-y))
...
obj-y := $(addprefix $(obj)/,$(obj-y))
obj-m := $(addprefix $(obj)/,$(obj-m))
lib-y := $(addprefix $(obj)/,$(lib-y))
subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y))
最終的に、
obj-y には同階層のオブジェクト群と一つ下の階層のbuilt-in.o
subdir-obj-y は一つ下の階層のbuilt-in.o
subdir-ym は一つ下の階層のディレクトリリスト
が入ります。
で、デフォルトターゲット __build の生成ルールを見ると以下のようになっています。
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
$(subdir-ym) $(always)
@:
ルールは @: なので何もしませんので、依存関係だけを書いています。
重要なのは
__build: $(builtin-target)
の部分です。
$(builtin-target) は $(obj)/built-in.o のことです。
$(builtin-target) を生成するルールは以下です。
$(builtin-target): $(obj-y) FORCE
$(call if_changed,link_o_target)
$(obj-y) を全部集めて、ld -r でまとめて1個のbuilt-in.oにするということです。
一つ下の階層のbuilt-in.o を作るためのルールは以下の部分です。
# To build objects in subdirs, we need to descend into the directories
$(sort $(subdir-obj-y)): $(subdir-ym) ;
...
PHONY += $(subdir-ym)
$(subdir-ym):
$(Q)$(MAKE) $(build)=$@
$(subdir-ym) ディレクトリ以下にさらに降りていくために、再帰的に Makefile.build を呼び出しています。
$@ には、drivers/gpic, drivers/pci のように一つ下の階層のディレクトリ名が入っています。
このように、再帰的make を使うことでディレクトリ階層を降りていきます。
ちなみに、各ディレクトリ階層に置く Makefileの書き方は
Documentation/kbuild/makefile.txt
に解説がありますが、ここでもちょこっと解説しておきます。
各階層のオブジェクトはMakefile の中で obj-y += hoge.o のようにobj-y変数に追加します。
また、 obj-y += piyo/ のようにディレクトリを追加すると、サブディレクトリに降りるという意味になります。
オブジェクトはディレクトリごとに built-in.o というファイルにまとめられます。
例で示した方がいいかもしれないですね。
以下のようにディレクトリ階層があって、各階層ごとに cのソースと Makefileがあったとする。
hoge
├── Makefile
├── hoge.c
└── piyo
├── Makefile
├── fuga
│ ├── Makefile
│ ├── fuga1.c
│ └── fuga2.c
└── piyo.c
Makefileにはその階層の オブジェクトと一つ下のディレクトリを記載します。
hoge/Makefileの内容:
obj-y := hoge.o piyo/
hoge/piyo/Makefileの内容:
obj-y := piyo.o fuga/
hoge/piyo/fuga/Makefileの内容:
obj-y := fuga1.o fuga2.o
みたいに書いておく。
このとき、 各階層の.o は .c ファイルをコンパイルして作られます。
さらに、
hoge/piyo/fuga/fuga1.o と hoge/piyo/fuga/fuga2.oは ld -r でまとめられて、
hoge/piyo/fuga/build-in.o になります。
さらに、
hoge/piyo/fuga/built-in.o と hoge/piyo/piyo.o がまとめられて hoge/piyo/built-in.oになる。
さらに、
hoge/piyo/built-in.o と hoge/hoge.o がまとめられて、hoge/built-in.o になる。
hoge/built-in.o は他のオブジェクトとトップレベルでリンクされて カーネルイメージになるという具合です。
今回解読するファイルはトップのMakefileとscripts/Makefile.build, scripts/Makefile.lib あたりです。
まず、トップのMakefileの500行目付近にある
init-y := init/
drivers-y := drivers/ sound/ firmware/
net-y := net/
libs-y := lib/
core-y := usr/
に注目します。これが、これから降りていこうとするトップ階層のディレクトリ達です。
さらに700行目付近に以下のように書いてあります。
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
$(net-y) $(net-m) $(libs-y) $(libs-m)))
vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
$(init-n) $(init-) \
$(core-n) $(core-) $(drivers-n) $(drivers-) \
$(net-n) $(net-) $(libs-n) $(libs-))))
init-y := $(patsubst %/, %/built-in.o, $(init-y))
core-y := $(patsubst %/, %/built-in.o, $(core-y))
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
net-y := $(patsubst %/, %/built-in.o, $(net-y))
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)
...
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux-all := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds := arch/$(SRCARCH)/kernel/vmlinux.lds
これをふまえて、
$ make vmlinux
としたときに何が起きるかを見てみます。
vmlinuxの構築ルールは900行目付近にあります。
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
ifdef CONFIG_HEADERS_CHECK
$(Q)$(MAKE) -f $(srctree)/Makefile headers_check
endif
ifdef CONFIG_SAMPLES
$(Q)$(MAKE) $(build)=samples
endif
ifdef CONFIG_BUILD_DOCSRC
$(Q)$(MAKE) $(build)=Documentation
endif
$(call vmlinux-modpost)
$(call if_changed_rule,vmlinux__)
$(Q)rm -f .old_version
vmlinuxはリンカースクリプト$(vmlinux-lds)の他、$(vmlinux-init) $(vmlinux-main)といったオブジェクトに依存しています。
これらをリンクすることで vmlinuxができます。
$(vmlinux-init) $(vmlinux-main) はほとんどは、トップ階層のディレクトリに /built-in.o をつけたものです。
で、*/built-in.o はどうやって作るかというと、
# The actual objects are generated when descending,
# make sure no implicit rule kicks in
$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
の行です。$(vmlinux-dirs) というディレクトリにだけ依存しています。
$(vmlinux-dirs) の構築ルールは以下です。
PHONY += $(vmlinux-dirs)
$(vmlinux-dirs): prepare scripts
$(Q)$(MAKE) $(build)=$@
前回説明したように、build というのは
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
のことでした。
ここからは、Makefile.build を呼び出して、ディレクトリを降りていく処理です。
例えば、
$ make drivers
とやると、 drivers/ ディレクトリを降りて行ってくれます。
ここからは scripts/Makefile.build の解析です。
例えば、 make -f scripts/Makefile.build obj=drivers
とした場合です。
src := $(obj)
でobjの値(drivers)がsrcにコピーされる。
40行目付近で、
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)
とありまして、$(obj)/Makefile がinclude されます。
ここを抜けてきたときに、obj-y にリンク対象のオブジェクトファイルと、サブディレクトリが入っています。
その下に
include scripts/Makefile.lib
とありまして、Makefile.lib の中で obj-y を加工します。
関係ある部分だけを抜き出すと、、
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y += $(__subdir-y)
...
obj-y := $(patsubst %/, %/built-in.o, $(obj-y))
...
subdir-ym := $(sort $(subdir-y) $(subdir-m))
...
# tell kbuild to descend
subdir-obj-y := $(filter %/built-in.o, $(obj-y))
...
obj-y := $(addprefix $(obj)/,$(obj-y))
obj-m := $(addprefix $(obj)/,$(obj-m))
lib-y := $(addprefix $(obj)/,$(lib-y))
subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y))
最終的に、
obj-y には同階層のオブジェクト群と一つ下の階層のbuilt-in.o
subdir-obj-y は一つ下の階層のbuilt-in.o
subdir-ym は一つ下の階層のディレクトリリスト
が入ります。
で、デフォルトターゲット __build の生成ルールを見ると以下のようになっています。
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
$(subdir-ym) $(always)
@:
ルールは @: なので何もしませんので、依存関係だけを書いています。
重要なのは
__build: $(builtin-target)
の部分です。
$(builtin-target) は $(obj)/built-in.o のことです。
$(builtin-target) を生成するルールは以下です。
$(builtin-target): $(obj-y) FORCE
$(call if_changed,link_o_target)
$(obj-y) を全部集めて、ld -r でまとめて1個のbuilt-in.oにするということです。
一つ下の階層のbuilt-in.o を作るためのルールは以下の部分です。
# To build objects in subdirs, we need to descend into the directories
$(sort $(subdir-obj-y)): $(subdir-ym) ;
...
PHONY += $(subdir-ym)
$(subdir-ym):
$(Q)$(MAKE) $(build)=$@
$(subdir-ym) ディレクトリ以下にさらに降りていくために、再帰的に Makefile.build を呼び出しています。
$@ には、drivers/gpic, drivers/pci のように一つ下の階層のディレクトリ名が入っています。
このように、再帰的make を使うことでディレクトリ階層を降りていきます。
LinuxカーネルのMakefileを解析する その5
LinuxカーネルのMakefileのファイル構成についてざっくり見てみる。
まずトップにある Makefileですが、いろいろなmake変数をセットアップして、exportしています。
exportされた変数は、再帰的に呼び出したmakeにも引き継がれます。
トップのMakefileが行っているトリッキーな処理については「LinuxカーネルのMakefileを解析する その1」「その2」で説明しました。
他にも、トップレベルの構築ルールも書かれています。
それ以外に、共通で使用するmakefileが scripts/ 以下にあります。
scripts/Kbuild.include には共通で使われる便利な変数や関数が入っています。
Kbuild.include は トップのMakefile や scripts/Makefile.* からincludeされています。
scripts/の下には Makefile.* という名前のファイルがあります。
Makefile.build, Makefile.clean, Makefile.fwinst, Makefile.headersinst, Makefile.help, Makefile.modbuiltin, Makefile.modinst, Makefile.modpost
といったファイルです。
これらは、再帰的にmakeを呼び出すときに使わます。
全部の構築ルールを1つのMakefileに書いてしまうと見づらいので、構築するターゲットの種類ごとにサブのMakefileに分離しているわけですね。
これらの使い方は、ほぼ決まっていて、
hoge:
$(MAKE) -f $(srctree)/scripts/Makefile.build obj=$@
みたいな書き方をします。
hogeを構築するルールは scripts/Makefile.build のようなサブのMakefileに分離されていて、それを再帰的に呼び出します。
その時に、何を作りたいかは obj変数にセットします。
なお、よく使われるものについては、短く書けるように、
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
といった変数が用意されています。これを用いれば、上記のものは、
hoge:
$(MAKE) $(build)=$@
のように非常に短く書くことができます。
この記法はあちこちで多用されています。
同様に、
clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
modbuiltin := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.modbuiltin obj
あたりは短く書くための便利変数が用意されている模様。
名前は似ているんですが、Makefile.host と Makefile.libは他の Makefile.* と違って、単に他のMakefileから includeされているだけです。
まずトップにある Makefileですが、いろいろなmake変数をセットアップして、exportしています。
exportされた変数は、再帰的に呼び出したmakeにも引き継がれます。
トップのMakefileが行っているトリッキーな処理については「LinuxカーネルのMakefileを解析する その1」「その2」で説明しました。
他にも、トップレベルの構築ルールも書かれています。
それ以外に、共通で使用するmakefileが scripts/ 以下にあります。
scripts/Kbuild.include には共通で使われる便利な変数や関数が入っています。
Kbuild.include は トップのMakefile や scripts/Makefile.* からincludeされています。
scripts/の下には Makefile.* という名前のファイルがあります。
Makefile.build, Makefile.clean, Makefile.fwinst, Makefile.headersinst, Makefile.help, Makefile.modbuiltin, Makefile.modinst, Makefile.modpost
といったファイルです。
これらは、再帰的にmakeを呼び出すときに使わます。
全部の構築ルールを1つのMakefileに書いてしまうと見づらいので、構築するターゲットの種類ごとにサブのMakefileに分離しているわけですね。
これらの使い方は、ほぼ決まっていて、
hoge:
$(MAKE) -f $(srctree)/scripts/Makefile.build obj=$@
みたいな書き方をします。
hogeを構築するルールは scripts/Makefile.build のようなサブのMakefileに分離されていて、それを再帰的に呼び出します。
その時に、何を作りたいかは obj変数にセットします。
なお、よく使われるものについては、短く書けるように、
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
といった変数が用意されています。これを用いれば、上記のものは、
hoge:
$(MAKE) $(build)=$@
のように非常に短く書くことができます。
この記法はあちこちで多用されています。
同様に、
clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
modbuiltin := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.modbuiltin obj
あたりは短く書くための便利変数が用意されている模様。
名前は似ているんですが、Makefile.host と Makefile.libは他の Makefile.* と違って、単に他のMakefileから includeされているだけです。
登録:
投稿 (Atom)