lineage: build: kernel: Rework kernel header logic
The existing kernel header logic has several issues:
* It does not depend on the actual kernel headers, so it does not
detect actual kernel header changes.
* It does depend on the kernel config, which should not be used to
generate (user space) kernel headers.
The end result is that kernel headers aren't properly regenerated when
needed, and spuriously regenerated when not needed. Additionally, the
kernel header rebuild mucks around with the kernel config, which is
unneccesary and fraught with danger.
Rewrite the kernel header dependency and generation logic as follows:
* Use the dependency file $(KERNEL_OUT)/.headers_install_deps to
manage dependencies on the actual kernel header files which are
exported to user space (and the top level kernel Makefile, which
is used to generate version.h). The dependency file is exactly
the same as what GCC would output for a C/C++ dependency with the
M/MM flags.
* Conditionally include the dependency file to detect when headers
should be (re)generated.
* Introduce the phony target INSTALLED_KERNEL_HEADERS for modules to
declare a dependency on kernel headers.
Additionally:
* Get rid of TARGET_KERNEL_HEADER_ARCH and KERNEL_HEADER_DEFCONFIG.
* Get rid of KERNEL_OUT_STAMP and move commands to the appropriate
places in the rules.
* Fail the build when $(KERNEL_OUT)/usr is mentioned in a dependency.
Note a separate commit to build/core/binary.mk will provide a
migration path and a suitable deprecation warning.
* Declare the kernel*config targets phony.
Change-Id: I8b46f4ea1c622d8e73cca5157be96ec09d42ebb3
diff --git a/build/tasks/kernel.mk b/build/tasks/kernel.mk
index bfbafc5..c6d2cb3 100644
--- a/build/tasks/kernel.mk
+++ b/build/tasks/kernel.mk
@@ -28,8 +28,6 @@
# TARGET_KERNEL_SELINUX_CONFIG = SELinux defconfig, optional
# TARGET_KERNEL_ADDITIONAL_CONFIG = Additional defconfig, optional
# TARGET_KERNEL_ARCH = Kernel Arch
-# TARGET_KERNEL_HEADER_ARCH = Optional Arch for kernel headers if
-# different from TARGET_KERNEL_ARCH
# TARGET_KERNEL_CROSS_COMPILE_PREFIX = Compiler prefix (e.g. arm-eabi-)
# defaults to arm-linux-androidkernel- for arm
# aarch64-linux-androidkernel- for arm64
@@ -86,7 +84,6 @@
## Internal variables
KERNEL_OUT := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ
KERNEL_CONFIG := $(KERNEL_OUT)/.config
-KERNEL_OUT_STAMP := $(KERNEL_OUT)/.mkdir_stamp
TARGET_KERNEL_ARCH := $(strip $(TARGET_KERNEL_ARCH))
ifeq ($(TARGET_KERNEL_ARCH),)
@@ -102,18 +99,6 @@
endif
KERNEL_DEFCONFIG_SRC := $(KERNEL_SRC)/arch/$(KERNEL_DEFCONFIG_ARCH)/configs/$(KERNEL_DEFCONFIG)
-TARGET_KERNEL_HEADER_ARCH := $(strip $(TARGET_KERNEL_HEADER_ARCH))
-ifeq ($(TARGET_KERNEL_HEADER_ARCH),)
-KERNEL_HEADER_ARCH := $(KERNEL_ARCH)
-else
-KERNEL_HEADER_ARCH := $(TARGET_KERNEL_HEADER_ARCH)
-endif
-
-KERNEL_HEADER_DEFCONFIG := $(strip $(KERNEL_HEADER_DEFCONFIG))
-ifeq ($(KERNEL_HEADER_DEFCONFIG),)
-KERNEL_HEADER_DEFCONFIG := $(KERNEL_DEFCONFIG)
-endif
-
ifeq ($(BOARD_KERNEL_IMAGE_NAME),)
$(error BOARD_KERNEL_IMAGE_NAME not defined.)
endif
@@ -207,8 +192,8 @@
ifeq ($(FULL_KERNEL_BUILD),true)
-KERNEL_HEADERS_INSTALL := $(KERNEL_OUT)/usr
-KERNEL_HEADERS_INSTALL_STAMP := $(KERNEL_OUT)/.headers_install_stamp
+KERNEL_HEADERS_INSTALL_DIR := $(KERNEL_OUT)/usr
+KERNEL_HEADERS_INSTALL_DEPS := $(KERNEL_OUT)/.headers_install_deps
ifeq ($(NEED_KERNEL_MODULE_ROOT),true)
KERNEL_MODULES_INSTALL := root
@@ -287,21 +272,15 @@
TARGET_KERNEL_MODULES := INSTALLED_KERNEL_MODULES
endif
-$(KERNEL_OUT_STAMP):
- $(hide) mkdir -p $(KERNEL_OUT)
- $(hide) rm -rf $(KERNEL_MODULES_OUT)
- $(hide) mkdir -p $(KERNEL_MODULES_OUT)
- $(hide) rm -rf $(KERNEL_DEPMOD_STAGING_DIR)
- $(hide) touch $@
-
KERNEL_ADDITIONAL_CONFIG_OUT := $(KERNEL_OUT)/.additional_config
.PHONY: force_additional_config
$(KERNEL_ADDITIONAL_CONFIG_OUT): force_additional_config
$(hide) cmp -s $(KERNEL_ADDITIONAL_CONFIG_SRC) $@ || cp $(KERNEL_ADDITIONAL_CONFIG_SRC) $@;
-$(KERNEL_CONFIG): $(KERNEL_OUT_STAMP) $(KERNEL_DEFCONFIG_SRC) $(KERNEL_ADDITIONAL_CONFIG_OUT)
+$(KERNEL_CONFIG): $(KERNEL_DEFCONFIG_SRC) $(KERNEL_ADDITIONAL_CONFIG_OUT)
@echo "Building Kernel Config"
+ $(hide) mkdir -p $(KERNEL_OUT)
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) VARIANT_DEFCONFIG=$(VARIANT_DEFCONFIG) SELINUX_DEFCONFIG=$(SELINUX_DEFCONFIG) $(KERNEL_DEFCONFIG)
$(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
@@ -314,8 +293,12 @@
$(KERNEL_SRC)/scripts/kconfig/merge_config.sh -m -O $(KERNEL_OUT) $(KERNEL_OUT)/.config $(KERNEL_SRC)/arch/$(KERNEL_ARCH)/configs/$(KERNEL_ADDITIONAL_CONFIG); \
$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) KCONFIG_ALLCONFIG=$(KERNEL_OUT)/.config alldefconfig; fi
-TARGET_KERNEL_BINARIES: $(KERNEL_OUT_STAMP) $(KERNEL_CONFIG) $(KERNEL_HEADERS_INSTALL_STAMP)
+.PHONY: TARGET_KERNEL_BINARIES
+TARGET_KERNEL_BINARIES: $(KERNEL_CONFIG)
@echo "Building Kernel"
+ $(hide) rm -rf $(KERNEL_MODULES_OUT)
+ $(hide) mkdir -p $(KERNEL_MODULES_OUT)
+ $(hide) rm -rf $(KERNEL_DEPMOD_STAGING_DIR)
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) $(BOARD_KERNEL_IMAGE_NAME)
$(hide) if grep -q '^CONFIG_OF=y' $(KERNEL_CONFIG); then \
echo "Building DTBs"; \
@@ -348,35 +331,64 @@
$(TARGET_PREBUILT_INT_KERNEL): $(TARGET_KERNEL_MODULES)
-$(KERNEL_HEADERS_INSTALL_STAMP): $(KERNEL_OUT_STAMP) $(KERNEL_CONFIG)
+# Install kernel (uapi) headers.
+#
+# The dependency file serves two purposes:
+# - It is a stamp indicating when the headers were last installed.
+# - It contains a rule to regenerate itself when any kernel header
+# files change. This rule is identical to the rule emitted by
+# GCC using the M/MM flags.
+#
+# Note that the location of installed kernel headers changed when the
+# kernel uapi system was introduced in 3.7. Unfortunately, it is not
+# sufficient to test whether the uapi directories exist because some
+# kernels backport patches that contain uapi headers. So we look for
+# the string "version_h" in the kernel makefile which was introduced
+# as a part of the uapi system (commit d183e6f570f3).
+-include $(KERNEL_HEADERS_INSTALL_DEPS)
+$(KERNEL_HEADERS_INSTALL_DEPS):
@echo "Building Kernel Headers"
- $(hide) if [ ! -z "$(KERNEL_HEADER_DEFCONFIG)" ]; then \
- rm -f ../$(KERNEL_CONFIG); \
- $(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_HEADER_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) VARIANT_DEFCONFIG=$(VARIANT_DEFCONFIG) SELINUX_DEFCONFIG=$(SELINUX_DEFCONFIG) $(KERNEL_HEADER_DEFCONFIG); \
- $(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_HEADER_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) headers_install; fi
- $(hide) if [ "$(KERNEL_HEADER_DEFCONFIG)" != "$(KERNEL_DEFCONFIG)" ]; then \
- echo "Used a different defconfig for header generation"; \
- rm -f ../$(KERNEL_CONFIG); \
- $(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) VARIANT_DEFCONFIG=$(VARIANT_DEFCONFIG) SELINUX_DEFCONFIG=$(SELINUX_DEFCONFIG) $(KERNEL_DEFCONFIG); fi
- $(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
- echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
- echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_OUT)/.config; \
- $(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) oldconfig; fi
- $(hide) if [ ! -z "$(KERNEL_ADDITIONAL_CONFIG)" ]; then \
- echo "Using additional config '$(KERNEL_ADDITIONAL_CONFIG)'"; \
- $(KERNEL_SRC)/scripts/kconfig/merge_config.sh -m -O $(KERNEL_OUT) $(KERNEL_OUT)/.config $(KERNEL_SRC)/arch/$(KERNEL_ARCH)/configs/$(KERNEL_ADDITIONAL_CONFIG); \
- $(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) KCONFIG_ALLCONFIG=$(KERNEL_OUT)/.config alldefconfig; fi
- $(hide) touch $@
+ $(hide) mkdir -p $(KERNEL_OUT)
+ $(hide) rm -f $@
+ $(hide) $(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) headers_install
+ $(hide) echo "$@: \\" > $@
+ $(hide) ( cd $(KERNEL_SRC); \
+ if grep -q '^version_h' 'Makefile'; then \
+ depdirs="arch/$(KERNEL_ARCH)/include/uapi include/uapi"; \
+ else \
+ depdirs="arch/$(KERNEL_ARCH)/include/asm include"; \
+ fi; \
+ deps="Makefile $$(find $$depdirs -type f -name '*.h')"; \
+ for f in $$deps; do \
+ echo " $(KERNEL_SRC)/$$f \\" >> $@; \
+ done ; \
+ echo "" >> $@ ; \
+ for f in $$deps; do \
+ echo "$(KERNEL_SRC)/$$f:" >> $@; \
+ echo "" >> $@; \
+ done \
+ )
-# provide this rule because there are dependencies on this throughout the repo
-$(KERNEL_HEADERS_INSTALL): $(KERNEL_HEADERS_INSTALL_STAMP)
+.PHONY: INSTALLED_KERNEL_HEADERS
+INSTALLED_KERNEL_HEADERS: $(KERNEL_HEADERS_INSTALL_DEPS)
-kerneltags: $(KERNEL_OUT_STAMP) $(KERNEL_CONFIG)
+# Dependencies on $(KERNEL_OUT)/usr are deprecated
+$(KERNEL_HEADERS_INSTALL_DIR): $(KERNEL_HEADERS_INSTALL_DEPS)
+ @echo "Depending on $(KERNEL_HEADERS_INSTALL_DIR) is deprecated." 1>&2
+ @echo "Use INSTALLED_KERNEL_HEADERS instead." 1>&2
+ @exit 1
+
+.PHONY: kerneltags
+kerneltags: $(KERNEL_CONFIG)
+ $(hide) mkdir -p $(KERNEL_OUT)
$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) tags
+.PHONY: kernelconfig kernelxconfig kernelsavedefconfig alldefconfig
+
kernelconfig: KERNELCONFIG_MODE := menuconfig
kernelxconfig: KERNELCONFIG_MODE := xconfig
-kernelxconfig kernelconfig: $(KERNEL_OUT_STAMP)
+kernelxconfig kernelconfig:
+ $(hide) mkdir -p $(KERNEL_OUT)
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) $(KERNEL_DEFCONFIG)
env KCONFIG_NOTIMESTAMP=true \
$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) $(KERNELCONFIG_MODE)
@@ -384,13 +396,15 @@
$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) savedefconfig
cp $(KERNEL_OUT)/defconfig $(KERNEL_DEFCONFIG_SRC)
-kernelsavedefconfig: $(KERNEL_OUT_STAMP)
+kernelsavedefconfig:
+ $(hide) mkdir -p $(KERNEL_OUT)
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) $(KERNEL_DEFCONFIG)
env KCONFIG_NOTIMESTAMP=true \
$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) savedefconfig
cp $(KERNEL_OUT)/defconfig $(KERNEL_DEFCONFIG_SRC)
-alldefconfig: $(KERNEL_OUT_STAMP)
+alldefconfig:
+ $(hide) mkdir -p $(KERNEL_OUT)
env KCONFIG_NOTIMESTAMP=true \
$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) alldefconfig