2012年6月11日月曜日
LinuxカーネルのMakefileを解析する その7
前回から間があきましたが、今回はLinux Makefile のコンパイルオプションについて解析してみた。
Makefile 中でのコンパイルオプションの与え方は Documentation/kbuild/makefiles.txt の 「3.7 Compilation flags」に記載されている。
ざっと読んでみると、
ccflags-y, asflags-y, ldflags-y
これが記載されている Makefile で有効。
(EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS も過去互換のためにサポートされているが、非推奨)
subdir-ccflags-y, subdir-asflags-y
これが記載されているMakefileとそのサブディレクトリで有効。
CFLAGS_$@, AFLAGS_$@
はファイル単位で追加したいオプションを指定する。
例) CFLAGS_foo.o := -D BAR
CPPFLAGS_$@ はないみたい。
CFLAGS_REMOVE_$@
でファイル単位で削除したいオプションを指定する。
AFLAGS_REMOVE_$@, CPPFLAGS_REMOVE_$@ はないみたい。。
このあたりのオプションがどのように実装されているか、見てみた。
コンパイルオプションはほとんど scripts/Makefile.lib の中で加工されている。
scripts/Makefile.lib は scripts/Makefile.build からインクルードされている。
まず、EXTRA_* の過去互換性のためのルールがある。
# Backward compatibility
asflags-y += $(EXTRA_AFLAGS)
ccflags-y += $(EXTRA_CFLAGS)
cppflags-y += $(EXTRA_CPPFLAGS)
ldflags-y += $(EXTRA_LDFLAGS)
また、サブディレクトリにも伝搬するように、
$(subdir-asflags-y), $(subdir-ccflags-y) は
KBUILD_SUBDIR_ASFLAGS, KBUILD_SUBDIR_CCFLAGS にいれて export している。
# flags that take effect in sub directories
export KBUILD_SUBDIR_ASFLAGS := $(KBUILD_SUBDIR_ASFLAGS) $(subdir-asflags-y)
export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
以下の部分で、_c_flags, _a_flags, _cpp_flags にまとめます。
KBUILD_CPPFLAGS, KBUILD_CFLAGS, KBUILD_AFLAGS は トップのMakefileとarch/*/Makefileで規定されていて、
make 全体に影響を与えます。
orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
$(ccflags-y) $(CFLAGS_$(basetarget).o)
_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \
$(asflags-y) $(AFLAGS_$(basetarget).o)
_cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F))
さらに、KBUILD_SRC が指定されている(つまり O=, M= が指定されている)ならば、インクルードパスの加工を行う。
KBUILD_SRC が指定されてなければ、 _*_flags がそのまま __*_flags になる。
ifeq ($(KBUILD_SRC),)
__c_flags = $(_c_flags)
__a_flags = $(_a_flags)
__cpp_flags = $(_cpp_flags)
else
# -I$(obj) locates generated .h files
# $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files
# and locates generated .h files
# FIXME: Replace both with specific CFLAGS* statements in the makefiles
__c_flags = $(call addtree,-I$(obj)) $(call flags,_c_flags)
__a_flags = $(call flags,_a_flags)
__cpp_flags = $(call flags,_cpp_flags)
endif
これから c_flags, a_flags, cpp_flags, ld_flags が作られる。
c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(__c_flags) $(modkern_cflags) \
-D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(__a_flags) $(modkern_aflags)
cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(__cpp_flags)
ld_flags = $(LDFLAGS) $(ldflags-y)
-Wp,-MD,$(depfile) は依存関係自動生成に使うプリプロセッサ用にオプションですね。
ようやく、これが scripts/Makefile.build のパターンルールの中で使われます。
%.c → %.o には
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
%.S → %.o には
cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
%.c → %.s には
cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
%.c → %.i には
cmd_cc_i_c = $(CPP) $(c_flags) -o $@ $<
%.S → %.s には
cmd_as_s_S = $(CPP) $(a_flags) -o $@ $<
%.lds.S → %.lds には
cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -C -U$(ARCH) \
-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
という風に使われるようです。
ところで、cppflags-y や EXTRA_CPPFLAGS って Makefile.lib には用意されているのですが、ほとんど使われている形跡がないですね。
-Dmacro や -Idir などはプリプロセッサオプションなので、cppflags-y に追加すべきと思うのですが、もっぱら ccflags-y に方に追加されているようです。
もう一つ気になるのは用語の非統一感です。
ccflags-y, EXTRA_CFLAGS, CFLAGS_$@, CFLAGS_REMOVE_$@
→ なんで cflags-y じゃなくて ccflags-y にしたの?
asflags-y, AFLAGS_$@
→ なんで ASFLAGS_$@ じゃなくて AFLAGS_$@ なの?
make でよく使われるのは CFLAGS, CPPFLAGS, ASFLAGS, LDFLAGS だと思うんですが。。(make --print-data-base で確認)
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿