Ответ 1
Kbuild Makefiles не самый легкий для чтения, но здесь высокоуровневый распутывание (с использованием ядра 4.0-rc3):
-
Файл Makefile верхнего уровня делает
include $(srctree)/scripts/Kbuild.include
где
$(srctree)
- это каталог ядра верхнего уровня. -
Kbuild.include
определяет различные общие вещи и помощники. Среди нихbuild
:### # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= # Usage: # $(Q)$(MAKE) $(build)=dir build := -f $(srctree)/scripts/Makefile.build obj
build
используется с командой типа$(MAKE) $(build)=dir
для выполнения сборки для каталогаdir
. Он используетscripts/Makefile.build
. -
Возвращаясь к файлу Makefile верхнего уровня, выполните следующее:
$(vmlinux-dirs): prepare scripts $(Q)$(MAKE) $(build)[email protected]
vmlinux-dirs
содержит список подкаталогов для сборки (init, usr, kernel и т.д.).$(Q)$(MAKE) $(build)=<subdirectory>
будет запущен для каждого подкаталога.Приведенное выше правило компилирует объектные файлы как для образа ядра, так и для модулей. Далее, в Makefile верхнего уровня, есть некоторые дополнительные особенности для модуля:
ifdef CONFIG_MODULES ... modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin # Do additional module-specific stuff using # scripts/Makefile.modpost among other things # (my comment). ... ... endif # CONFIG_MODULES
-
Взяв
scripts/Makefile.build
(Makefile, используемый$(build)
), он начинается с инициализации списковobj-*
и других списков:# Init all relevant variables used in kbuild files so # 1) they have correct type # 2) they do not inherit any value from the environment obj-y := obj-m := lib-y := lib-m :=
Немного дальше, он загружается в файл Kbuild, где установлены
obj-y
,obj-m
и т.д.:include $(kbuild-file)
Далее вниз используется правило по умолчанию, которое содержит списки
$(obj-y)
и$(obj-m)
в качестве предварительных условий:__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \ $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \ $(subdir-ym) $(always) @:
Предпосылки
$(obj-y)
исходят от$(builtin-target)
, который определяется следующим образом:builtin-target := $(obj)/built-in.o ... $(builtin-target): $(obj-y) FORCE $(call if_changed,link_o_target)
Фактическое здание, по-видимому, выполняется по следующему правилу:
# Built-in and composite module parts $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE $(call cmd,force_checksrc) $(call if_changed_rule,cc_o_c)
if_changed_rule
- отKbuild.include
. Правило заканчивается запуском следующих команд вMakefile.build
:define rule_cc_o_c $(call echo-cmd,checksrc) $(cmd_checksrc) \ $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \ ... endef
$(cmd_cc_o_c)
представляется фактической командой компиляции. Обычное определение (есть две возможности вMakefile.build
, AFAICS), похоже, следующее:cmd_cc_o_c = $(CC) $(c_flags) -c -o [email protected] $<
Если явно не использовать, например,
make CC=clang
,CC
по умолчанию используетсяgcc
, как можно видеть здесь в файле Makefile верхнего уровня:ifneq ($(CC),) ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1) COMPILER := clang else COMPILER := gcc endif export COMPILER endif
Я распутал это, выполнив CTRL-C во время сборки ядра и увидев, где make
сообщила об ошибке. Другим удобным способом отладки make
является использование $(warning $(variable))
для печати значения variable
.