diff --git a/build/soong/Android.bp b/build/soong/Android.bp index 36f0427..6021975 100644 --- a/build/soong/Android.bp +++ b/build/soong/Android.bp @@ -21,7 +21,7 @@ twrp_generator { name: "generated_kernel_includes", // The headers make command - cmd: "$(PATH_OVERRIDE_SOONG) $(KERNEL_MAKE_CMD) $(KERNEL_MAKE_FLAGS) -C $(TARGET_KERNEL_HEADERS_SOURCE) O=$(KERNEL_BUILD_OUT_PREFIX)$(genDir) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) headers_install", + cmd: "$(PATH_OVERRIDE_SOONG) $(KERNEL_MAKE_CMD) $(KERNEL_MAKE_FLAGS) -C $(TARGET_KERNEL_SOURCE) O=$(KERNEL_BUILD_OUT_PREFIX)$(genDir) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) headers_install && vendor/twrp/tools/clean_headers.sh $(KERNEL_BUILD_OUT_PREFIX)$(genDir)", // Directories that can be imported by a cc_* module generated_headers property export_include_dirs: [ diff --git a/build/tasks/kernel.mk b/build/tasks/kernel.mk index 779df53..9d0ea05 100644 --- a/build/tasks/kernel.mk +++ b/build/tasks/kernel.mk @@ -1,5 +1,5 @@ # Copyright (C) 2012 The CyanogenMod Project -# (C) 2017-2021 The LineageOS Project +# (C) 2017-2023 The LineageOS Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -21,17 +21,16 @@ # # These config vars are usually set in BoardConfig.mk: # -# TARGET_KERNEL_CONFIG = Kernel defconfig +# TARGET_KERNEL_ADDITIONAL_FLAGS = Additional make flags, optional +# TARGET_KERNEL_CONFIG = List of kernel defconfigs, first one being the base one, +# while all the others are fragments that will be merged +# to main one in .config. +# TARGET_KERNEL_RECOVERY_CONFIG = Same as above, but applicable to recovery kernel instead. # TARGET_KERNEL_VARIANT_CONFIG = Variant defconfig, optional # TARGET_KERNEL_SELINUX_CONFIG = SELinux defconfig, optional -# TARGET_KERNEL_ADDITIONAL_CONFIG = Additional defconfig, optional # # TARGET_KERNEL_CLANG_COMPILE = Compile kernel with clang, defaults to true # -# TARGET_KERNEL_CLANG_VERSION = Clang prebuilts version, optional, defaults to clang-stable -# -# TARGET_KERNEL_CLANG_PATH = Clang prebuilts path, optional -# # BOARD_KERNEL_IMAGE_NAME = Built image name # for ARM use: zImage # for ARM64 use: Image.gz @@ -41,14 +40,16 @@ # For example, for ARM devices, # use zImage-dtb instead of zImage. # -# BOARD_DTBO_CFG = Path to a mkdtboimg.py config file +# BOARD_DTB_CFG = Path to a mkdtboimg config file for dtb.img +# +# BOARD_DTBO_CFG = Path to a mkdtboimg config file +# +# BOARD_CUSTOM_DTBIMG_MK = Path to a custom dtbimage makefile # # BOARD_CUSTOM_DTBOIMG_MK = Path to a custom dtboimage makefile # # KERNEL_CC = The C Compiler used. This is automatically set based # on whether the clang version is set, optional. -# KERNEL_LD = The Linker used. This is automatically set based -# on whether the clang/gcc version is set, optional. # # KERNEL_CLANG_TRIPLE = Target triple for clang (e.g. aarch64-linux-gnu-) # defaults to arm-linux-gnu- for arm @@ -62,8 +63,8 @@ # NEED_KERNEL_MODULE_VENDOR_OVERLAY = Optional, if true, install kernel # modules in vendor_overlay instead of vendor # -# TARGET_FORCE_PREBUILT_KERNEL = Optional, use TARGET_PREBUILT_KERNEL even if -# kernel sources are present +# TARGET_MERGE_DTBS_WILDCARD = Optional, limits the .dtb files used to generate the +# final DTB image when using QCOM's merge_dtbs script. ifneq ($(TARGET_NO_KERNEL),true) ifneq ($(TARGET_NO_KERNEL_OVERRIDE),true) @@ -72,16 +73,27 @@ ifneq ($(TARGET_NO_KERNEL_OVERRIDE),true) KERNEL_SRC := $(TARGET_KERNEL_SOURCE) # kernel configuration - mandatory KERNEL_DEFCONFIG := $(TARGET_KERNEL_CONFIG) +RECOVERY_DEFCONFIG := $(TARGET_KERNEL_RECOVERY_CONFIG) VARIANT_DEFCONFIG := $(TARGET_KERNEL_VARIANT_CONFIG) SELINUX_DEFCONFIG := $(TARGET_KERNEL_SELINUX_CONFIG) +# dtb generation - optional +TARGET_MERGE_DTBS_WILDCARD ?= * ## Internal variables DTC := $(HOST_OUT_EXECUTABLES)/dtc KERNEL_OUT := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ +RECOVERY_KERNEL_OUT := $(TARGET_OUT_INTERMEDIATES)/RECOVERY_KERNEL_OBJ DTBO_OUT := $(TARGET_OUT_INTERMEDIATES)/DTBO_OBJ DTB_OUT := $(TARGET_OUT_INTERMEDIATES)/DTB_OBJ +ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) +DTBS_BASE := $(DTB_OUT)/base +DTBS_OUT := $(DTB_OUT)/out +endif KERNEL_CONFIG := $(KERNEL_OUT)/.config KERNEL_RELEASE := $(KERNEL_OUT)/include/config/kernel.release +RECOVERY_KERNEL_CONFIG := $(RECOVERY_KERNEL_OUT)/.config +RECOVERY_KERNEL_RELEASE := $(RECOVERY_KERNEL_OUT)/include/config/kernel.release +GKI_SUFFIX := $(shell echo android$(PLATFORM_VERSION)-$(TARGET_KERNEL_VERSION)) ifeq ($(KERNEL_ARCH),x86_64) @@ -90,18 +102,13 @@ else KERNEL_DEFCONFIG_ARCH := $(KERNEL_ARCH) endif KERNEL_DEFCONFIG_DIR := $(KERNEL_SRC)/arch/$(KERNEL_DEFCONFIG_ARCH)/configs -KERNEL_DEFCONFIG_SRC := $(KERNEL_DEFCONFIG_DIR)/$(KERNEL_DEFCONFIG) +ALL_KERNEL_DEFCONFIG_SRCS := $(foreach config,$(KERNEL_DEFCONFIG),$(KERNEL_DEFCONFIG_DIR)/$(config)) +ALL_RECOVERY_KERNEL_DEFCONFIG_SRCS := $(foreach config,$(RECOVERY_DEFCONFIG),$(KERNEL_DEFCONFIG_DIR)/$(config)) -ifneq ($(TARGET_KERNEL_ADDITIONAL_CONFIG),) -KERNEL_ADDITIONAL_CONFIG := $(TARGET_KERNEL_ADDITIONAL_CONFIG) -KERNEL_ADDITIONAL_CONFIG_SRC := $(KERNEL_DEFCONFIG_DIR)/$(KERNEL_ADDITIONAL_CONFIG) - ifeq ("$(wildcard $(KERNEL_ADDITIONAL_CONFIG_SRC))","") - $(warning TARGET_KERNEL_ADDITIONAL_CONFIG '$(TARGET_KERNEL_ADDITIONAL_CONFIG)' doesn't exist) - KERNEL_ADDITIONAL_CONFIG_SRC := /dev/null - endif -else - KERNEL_ADDITIONAL_CONFIG_SRC := /dev/null -endif +BASE_KERNEL_DEFCONFIG := $(word 1, $(KERNEL_DEFCONFIG)) +BASE_KERNEL_DEFCONFIG_SRC := $(word 1, $(ALL_KERNEL_DEFCONFIG_SRCS)) +BASE_RECOVERY_KERNEL_DEFCONFIG := $(word 1, $(RECOVERY_DEFCONFIG)) +BASE_RECOVERY_KERNEL_DEFCONFIG_SRC := $(word 1, $(ALL_RECOVERY_KERNEL_DEFCONFIG_SRCS)) ifeq ($(TARGET_PREBUILT_KERNEL),) ifeq ($(BOARD_KERNEL_IMAGE_NAME),) @@ -110,6 +117,8 @@ ifeq ($(TARGET_PREBUILT_KERNEL),) endif TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/$(BOARD_KERNEL_IMAGE_NAME) +TARGET_PREBUILT_INT_RECOVERY_KERNEL := $(RECOVERY_KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/$(BOARD_KERNEL_IMAGE_NAME) + ifeq "$(wildcard $(KERNEL_SRC) )" "" ifneq ($(TARGET_PREBUILT_KERNEL),) HAS_PREBUILT_KERNEL := true @@ -150,104 +159,121 @@ else $(warning **********************************************************) $(error "NO KERNEL CONFIG") else - ifneq ($(TARGET_FORCE_PREBUILT_KERNEL),) - ifneq ($(filter RELEASE NIGHTLY SNAPSHOT EXPERIMENTAL,$(LINEAGE_BUILDTYPE)),) - $(error "PREBUILT KERNEL IS NOT ALLOWED ON OFFICIAL BUILDS!") - else - $(warning **********************************************************) - $(warning * Kernel source found and configuration was defined, *) - $(warning * but prebuilt kernel is being forced. *) - $(warning * While this is likely intentional, *) - $(warning * it is NOT SUPPORTED WHATSOEVER. *) - $(warning * Generated kernel headers may not align with *) - $(warning * the ABI of kernel you're including. *) - $(warning * Please unset TARGET_FORCE_PREBUILT_KERNEL *) - $(warning * to build the kernel from source. *) - $(warning **********************************************************) - FULL_KERNEL_BUILD := false - KERNEL_BIN := $(TARGET_PREBUILT_KERNEL) - endif - else - FULL_KERNEL_BUILD := true - KERNEL_BIN := $(TARGET_PREBUILT_INT_KERNEL) - endif + FULL_KERNEL_BUILD := true + KERNEL_BIN := $(TARGET_PREBUILT_INT_KERNEL) endif endif -ifeq ($(FULL_KERNEL_BUILD),true) - -ifeq ($(NEED_KERNEL_MODULE_ROOT),true) -KERNEL_MODULES_OUT := $(TARGET_ROOT_OUT) -KERNEL_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_recovery) -KERNEL_MODULE_MOUNTPOINT := -else ifeq ($(NEED_KERNEL_MODULE_SYSTEM),true) -KERNEL_MODULES_OUT := $(TARGET_OUT) -KERNEL_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_system) -KERNEL_MODULE_MOUNTPOINT := system -$(INSTALLED_SYSTEMIMAGE_TARGET): $(TARGET_PREBUILT_INT_KERNEL) -else ifeq ($(NEED_KERNEL_MODULE_RECOVERY),true) -KERNEL_MODULES_OUT := $(TARGET_RECOVERY_ROOT_OUT)/vendor -KERNEL_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_recovery) -KERNEL_MODULE_MOUNTPOINT := -$(INSTALLED_RAMDISK_TARGET): $(TARGET_PREBUILT_INT_KERNEL) -else ifeq ($(NEED_KERNEL_MODULE_VENDOR_OVERLAY),true) -KERNEL_MODULES_OUT := $(TARGET_OUT_PRODUCT)/vendor_overlay/$(PRODUCT_TARGET_VNDK_VERSION) -KERNEL_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_product) -KERNEL_MODULE_MOUNTPOINT := vendor -$(INSTALLED_PRODUCTIMAGE_TARGET): $(TARGET_PREBUILT_INT_KERNEL) +ifneq ($(TARGET_KERNEL_RECOVERY_CONFIG),) + ifeq "$(wildcard $(KERNEL_SRC) )" "" + ifeq ($(TARGET_PREBUILT_RECOVERY_KERNEL),) + $(warning ***************************************************************) + $(warning * *) + $(warning * No recovery kernel source found, and no fallback prebuilt *) + $(warning * defined. Please make sure your device is properly *) + $(warning * configured to download the kernel repository to $(KERNEL_SRC)) + $(warning * or remove TARGET_KERNEL_RECOVERY_CONFIG from BoardConfig.mk *) + $(warning * *) + $(warning * Or, define the TARGET_PREBUILT_RECOVERY_KERNEL *) + $(warning * variable with the path to the prebuilt recovery kernel image*) + $(warning * in your BoardConfig.mk file *) + $(warning * *) + $(warning ***************************************************************) + $(error "NO RECOVERY KERNEL SOURCE") + endif + endif + ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),) + $(warning ********************************************************) + $(warning * TARGET_KERNEL_RECOVERY_CONFIG set but device uses *) + $(warning * RECOVERY_AS_BOOT, which uses boot kernel as recovery *) + $(warning * kernel, as such it's not possible to use different *) + $(warning * configs *) + $(warning ********************************************************) + $(error "INVALID CONFIGURATION") + else + FULL_RECOVERY_KERNEL_BUILD := true + RECOVERY_KERNEL_COPY := true + RECOVERY_BIN := $(TARGET_PREBUILT_INT_RECOVERY_KERNEL) + endif else -KERNEL_MODULES_OUT := $(TARGET_OUT_VENDOR) -KERNEL_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_vendor) -KERNEL_MODULE_MOUNTPOINT := vendor -$(INSTALLED_VENDORIMAGE_TARGET): $(TARGET_PREBUILT_INT_KERNEL) + ifneq ($(TARGET_PREBUILT_RECOVERY_KERNEL),) + RECOVERY_BIN := $(TARGET_PREBUILT_RECOVERY_KERNEL) + RECOVERY_KERNEL_COPY := true + endif endif -MODULES_INTERMEDIATES := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,kernel_modules) - -KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_vendor_ramdisk) -$(INTERNAL_VENDOR_RAMDISK_TARGET): $(TARGET_PREBUILT_INT_KERNEL) +ifeq ($(or $(FULL_RECOVERY_KERNEL_BUILD), $(FULL_KERNEL_BUILD)),true) # Add host bin out dir to path PATH_OVERRIDE := PATH=$(KERNEL_BUILD_OUT_PREFIX)$(HOST_OUT_EXECUTABLES):$$PATH ifneq ($(TARGET_KERNEL_CLANG_COMPILE),false) - ifneq ($(TARGET_KERNEL_CLANG_VERSION),) - KERNEL_CLANG_VERSION := clang-$(TARGET_KERNEL_CLANG_VERSION) - else - # Use the default version of clang if TARGET_KERNEL_CLANG_VERSION hasn't been set by the device config - KERNEL_CLANG_VERSION := $(LLVM_PREBUILTS_VERSION) + ifneq ($(KERNEL_NO_GCC), true) + ifeq ($(KERNEL_ARCH),arm64) + KERNEL_CLANG_TRIPLE ?= CLANG_TRIPLE=aarch64-linux-gnu- + else ifeq ($(KERNEL_ARCH),arm) + KERNEL_CLANG_TRIPLE ?= CLANG_TRIPLE=arm-linux-gnu- + else ifeq ($(KERNEL_ARCH),x86) + KERNEL_CLANG_TRIPLE ?= CLANG_TRIPLE=x86_64-linux-gnu- + endif + PATH_OVERRIDE += LD_LIBRARY_PATH=$(TARGET_KERNEL_CLANG_PATH)/lib64:$$LD_LIBRARY_PATH endif - TARGET_KERNEL_CLANG_PATH ?= $(BUILD_TOP)/prebuilts/clang/host/$(HOST_PREBUILT_TAG)/$(KERNEL_CLANG_VERSION) - ifeq ($(KERNEL_ARCH),arm64) - KERNEL_CLANG_TRIPLE ?= CLANG_TRIPLE=aarch64-linux-gnu- - else ifeq ($(KERNEL_ARCH),arm) - KERNEL_CLANG_TRIPLE ?= CLANG_TRIPLE=arm-linux-gnu- - else ifeq ($(KERNEL_ARCH),x86) - KERNEL_CLANG_TRIPLE ?= CLANG_TRIPLE=x86_64-linux-gnu- - endif - PATH_OVERRIDE += PATH=$(TARGET_KERNEL_CLANG_PATH)/bin:$$PATH LD_LIBRARY_PATH=$(TARGET_KERNEL_CLANG_PATH)/lib64:$$LD_LIBRARY_PATH + PATH_OVERRIDE += PATH=$(TARGET_KERNEL_CLANG_PATH)/bin:$$PATH ifeq ($(KERNEL_CC),) - KERNEL_CC := CC="$(CCACHE_BIN) clang" - endif - ifeq ($(KERNEL_LD),) - KERNEL_LD := + CLANG_EXTRA_FLAGS := --cuda-path=/dev/null + ifeq ($(shell $(TARGET_KERNEL_CLANG_PATH)/bin/clang -v --hip-path=/dev/null >/dev/null 2>&1; echo $$?),0) + CLANG_EXTRA_FLAGS += --hip-path=/dev/null + endif + KERNEL_CC := CC="$(CCACHE_BIN) clang $(CLANG_EXTRA_FLAGS)" endif endif -ifneq ($(TARGET_KERNEL_MODULES),) - $(error TARGET_KERNEL_MODULES is no longer supported!) +ifneq ($(KERNEL_NO_GCC), true) + PATH_OVERRIDE += PATH=$(KERNEL_TOOLCHAIN_PATH_gcc):$$PATH endif -PATH_OVERRIDE += PATH=$(KERNEL_TOOLCHAIN_PATH_gcc):$$PATH - # System tools are no longer allowed on 10+ PATH_OVERRIDE += $(TOOLS_PATH_OVERRIDE) -KERNEL_ADDITIONAL_CONFIG_OUT := $(KERNEL_OUT)/.additional_config +ifeq (true,$(filter true, $(TARGET_NEEDS_DTBOIMAGE) $(BOARD_KERNEL_SEPARATED_DTBO))) + KERNEL_MAKE_FLAGS += DTC_EXT=$(KERNEL_BUILD_OUT_PREFIX)$(DTC) +endif + +ifneq ($(TARGET_KERNEL_ADDITIONAL_FLAGS),) + KERNEL_MAKE_FLAGS += $(TARGET_KERNEL_ADDITIONAL_FLAGS) +endif # Internal implementation of make-kernel-target # $(1): output path (The value passed to O=) # $(2): target to build (eg. defconfig, modules, dtbo.img) define internal-make-kernel-target -$(PATH_OVERRIDE) $(KERNEL_MAKE_CMD) $(KERNEL_MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_BUILD_OUT_PREFIX)$(1) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) $(KERNEL_LD) $(2) +$(PATH_OVERRIDE) $(KERNEL_MAKE_CMD) $(KERNEL_MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_BUILD_OUT_PREFIX)$(1) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) $(2) +endef + +# Make an external module target +# $(1): module name +# $(2): module root path +# $(3): target to build (eg. modules_install) +define make-external-module-target +$(PATH_OVERRIDE) $(KERNEL_MAKE_CMD) $(KERNEL_MAKE_FLAGS) -C $(TARGET_KERNEL_EXT_MODULE_ROOT)/$(1) M=$(2)/$(1) KERNEL_SRC=$(BUILD_TOP)/$(KERNEL_SRC) OUT_DIR=$(KERNEL_BUILD_OUT_PREFIX)$(KERNEL_OUT) O=$(KERNEL_BUILD_OUT_PREFIX)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) $(3) +endef + +# Make an external module target using kbuild +# $(1): module name +# $(2): module root path relative to kernel source +# $(2): target to build (eg. modules_install) +define make-kbuild-module-target +$(PATH_OVERRIDE) $(KERNEL_MAKE_CMD) $(KERNEL_MAKE_FLAGS) -C $(BUILD_TOP)/$(KERNEL_SRC) M=$(2)/$(1) O=$(KERNEL_BUILD_OUT_PREFIX)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_CLANG_TRIPLE) $(KERNEL_CC) $(3) +endef + +# Generate kernel .config from a given defconfig +# $(1): Output path (The value passed to O=) +# $(2): The defconfig to process (just the filename, no need for full path to file) +define make-kernel-config + $(call internal-make-kernel-target,$(1),VARIANT_DEFCONFIG=$(VARIANT_DEFCONFIG) SELINUX_DEFCONFIG=$(SELINUX_DEFCONFIG) $(2)) + $(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \ + echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \ + echo $(KERNEL_CONFIG_OVERRIDE) >> $(1)/.config; \ + $(call make-kernel-target,oldconfig); \ + fi endef # Make a kernel target @@ -256,6 +282,12 @@ define make-kernel-target $(call internal-make-kernel-target,$(KERNEL_OUT),$(1)) endef +# Make a recovery kernel target +# $(1): The kernel target to build (eg. defconfig, modules, modules_install) +define make-recovery-kernel-target +$(call internal-make-kernel-target,$(RECOVERY_KERNEL_OUT),$(1)) +endef + # Make a DTBO target # $(1): The DTBO target to build (eg. dtbo.img, defconfig) define make-dtbo-target @@ -273,44 +305,97 @@ endef # $(3): mount point # $(4): staging dir # $(5): module load list +# $(6): suffix for output dir, needed for GKI modules usecase, empty otherwise # Depmod requires a well-formed kernel version so 0.0 is used as a placeholder. define build-image-kernel-modules-twrp - mkdir -p $(2)/lib/modules - cp $(1) $(2)/lib/modules/ + mkdir -p $(2)/lib/modules$(6) + cp $(1) $(2)/lib/modules$(6) rm -rf $(4) - mkdir -p $(4)/lib/modules/0.0/$(3)lib/modules - cp $(1) $(4)/lib/modules/0.0/$(3)lib/modules + mkdir -p $(4)/lib/modules/0.0/$(3)lib/modules$(6) + cp $(1) $(4)/lib/modules/0.0/$(3)lib/modules$(6) $(DEPMOD) -b $(4) 0.0 - sed -e 's/\(.*modules.*\):/\/\1:/g' -e 's/ \([^ ]*modules[^ ]*\)/ \/\1/g' $(4)/lib/modules/0.0/modules.dep > $(2)/lib/modules/modules.dep - cp $(4)/lib/modules/0.0/modules.softdep $(2)/lib/modules - cp $(4)/lib/modules/0.0/modules.alias $(2)/lib/modules - rm -f $(2)/lib/modules/modules.load + sed -e 's/\(.*modules.*\):/\/\1:/g' -e 's/ \([^ ]*modules[^ ]*\)/ \/\1/g' $(4)/lib/modules/0.0/modules.dep > $(2)/lib/modules$(6)/modules.dep + cp $(4)/lib/modules/0.0/modules.softdep $(2)/lib/modules$(6) + cp $(4)/lib/modules/0.0/modules.alias $(2)/lib/modules$(6) + rm -f $(2)/lib/modules$(6)/modules.load for MODULE in $(5); do \ - basename $$MODULE >> $(2)/lib/modules/modules.load; \ + NAME=$$(basename $$MODULE .ko); \ + if [ -n "$$(find $(2)/lib/modules$(6) -type f -name $$NAME'.ko')" ]; then \ + echo "$$NAME" >> $(2)/lib/modules$(6)/modules.load; \ + else \ + echo "ERROR: $$NAME.ko was not found in the kernel modules intermediates dir, module load list must be corrected" 1>&2 && exit 1; \ + fi; \ done endef +endif # FULL_RECOVERY_KERNEL_BUILD or FULL_KERNEL_BUILD + +ifeq ($(FULL_KERNEL_BUILD),true) + +ifeq ($(NEED_KERNEL_MODULE_ROOT),true) +KERNEL_MODULES_OUT := $(TARGET_ROOT_OUT) +KERNEL_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_recovery) +KERNEL_MODULE_MOUNTPOINT := +else ifeq ($(NEED_KERNEL_MODULE_SYSTEM),true) +KERNEL_MODULES_OUT := $(TARGET_OUT) +KERNEL_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_system) +KERNEL_MODULE_MOUNTPOINT := system +$(INSTALLED_SYSTEMIMAGE_TARGET): $(TARGET_PREBUILT_INT_KERNEL) +else ifeq ($(NEED_KERNEL_MODULE_VENDOR_OVERLAY),true) +KERNEL_MODULES_OUT := $(TARGET_OUT_PRODUCT)/vendor_overlay/$(PRODUCT_TARGET_VNDK_VERSION) +KERNEL_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_product) +KERNEL_MODULE_MOUNTPOINT := vendor +$(INSTALLED_PRODUCTIMAGE_TARGET): $(TARGET_PREBUILT_INT_KERNEL) +else +KERNEL_MODULES_OUT := $(TARGET_OUT_VENDOR) +KERNEL_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_vendor) +KERNEL_MODULE_MOUNTPOINT := vendor +$(INSTALLED_VENDORIMAGE_TARGET): $(TARGET_PREBUILT_INT_KERNEL) +endif +ifeq ($(BOARD_USES_SYSTEM_DLKMIMAGE),true) +SYSTEM_KERNEL_MODULES_OUT := $(TARGET_OUT_SYSTEM_DLKM) +SYSTEM_KERNEL_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_system_dlkm) +SYSTEM_KERNEL_MODULE_MOUNTPOINT := system_dlkm +$(INSTALLED_SYSTEM_DLKMIMAGE_TARGET): $(TARGET_PREBUILT_INT_KERNEL) +endif +MODULES_INTERMEDIATES := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,kernel_modules) + +ifneq (,$(filter dlkm,$(BOARD_VENDOR_RAMDISK_FRAGMENTS))) +KERNEL_VENDOR_RAMDISK_KERNEL_MODULES_LOAD := $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD) +KERNEL_VENDOR_RAMDISK_MODULES_OUT := $(VENDOR_RAMDISK_FRAGMENT.dlkm.STAGING_DIR) +KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_vendor_ramdisk_fragment-stage-dlkm) +$(INTERNAL_VENDOR_RAMDISK_FRAGMENT_TARGETS): $(TARGET_PREBUILT_INT_KERNEL) +$(INTERNAL_VENDOR_RAMDISK_TARGET): $(TARGET_PREBUILT_INT_KERNEL) +else ifeq ($(PRODUCT_BUILD_VENDOR_KERNEL_BOOT_IMAGE),true) +KERNEL_VENDOR_RAMDISK_KERNEL_MODULES_LOAD := $(BOARD_VENDOR_KERNEL_RAMDISK_KERNEL_MODULES_LOAD) +KERNEL_VENDOR_RAMDISK_MODULES_OUT := $(TARGET_VENDOR_KERNEL_RAMDISK_OUT) +KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_vendor_kernel_ramdisk) +$(INTERNAL_VENDOR_KERNEL_RAMDISK_TARGET): $(TARGET_PREBUILT_INT_KERNEL) +$(INTERNAL_VENDOR_RAMDISK_TARGET): $(TARGET_PREBUILT_INT_KERNEL) +else ifeq ($(BUILDING_VENDOR_BOOT_IMAGE),true) +KERNEL_VENDOR_RAMDISK_KERNEL_MODULES_LOAD := $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD) +KERNEL_VENDOR_RAMDISK_MODULES_OUT := $(TARGET_VENDOR_RAMDISK_OUT) +KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_vendor_ramdisk) +$(INTERNAL_VENDOR_RAMDISK_TARGET): $(TARGET_PREBUILT_INT_KERNEL) +else +KERNEL_VENDOR_RAMDISK_KERNEL_MODULES_LOAD := $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD) +KERNEL_VENDOR_RAMDISK_MODULES_OUT := $(TARGET_RAMDISK_OUT) +KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_ramdisk) +$(INSTALLED_RAMDISK_TARGET): $(TARGET_PREBUILT_INT_KERNEL) +endif + +ifneq ($(RECOVERY_KERNEL_MODULES),) +KERNEL_RECOVERY_DEPMOD_STAGING_DIR := $(KERNEL_BUILD_OUT_PREFIX)$(call intermediates-dir-for,PACKAGING,depmod_recovery) +KERNEL_RECOVERY_MODULES_OUT := $(TARGET_RECOVERY_ROOT_OUT) +$(recovery_uncompressed_ramdisk): $(TARGET_PREBUILT_INT_KERNEL) +endif + $(KERNEL_OUT): mkdir -p $(KERNEL_OUT) -$(KERNEL_ADDITIONAL_CONFIG_OUT): $(KERNEL_OUT) - $(hide) cmp -s $(KERNEL_ADDITIONAL_CONFIG_SRC) $@ || cp $(KERNEL_ADDITIONAL_CONFIG_SRC) $@; - -$(KERNEL_CONFIG): $(KERNEL_DEFCONFIG_SRC) $(KERNEL_ADDITIONAL_CONFIG_OUT) +$(KERNEL_CONFIG): $(KERNEL_OUT) $(ALL_KERNEL_DEFCONFIG_SRCS) @echo "Building Kernel Config" - $(call make-kernel-target,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)'"; \ - echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_OUT)/.config; \ - $(call make-kernel-target,oldconfig); \ - fi - # Create defconfig build artifact - $(call make-kernel-target,savedefconfig) - $(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); \ - $(call make-kernel-target,KCONFIG_ALLCONFIG=$(KERNEL_OUT)/.config alldefconfig); \ - fi + $(call make-kernel-config,$(KERNEL_OUT),$(KERNEL_DEFCONFIG)) $(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_CONFIG) $(DEPMOD) $(DTC) @echo "Building Kernel Image ($(BOARD_KERNEL_IMAGE_NAME))" @@ -324,20 +409,51 @@ $(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_CONFIG) $(DEPMOD) $(DTC) $(call make-kernel-target,modules) || exit "$$?"; \ echo "Installing Kernel Modules"; \ $(call make-kernel-target,INSTALL_MOD_PATH=$(MODULES_INTERMEDIATES) INSTALL_MOD_STRIP=1 modules_install); \ + $(if $(TARGET_KERNEL_EXT_MODULES),\ + echo "Building and Installing External Kernel Modules"; \ + rpath=$$(python3 -c 'import os,sys;print(os.path.relpath(*(sys.argv[1:])))' $(TARGET_KERNEL_EXT_MODULE_ROOT) $(KERNEL_SRC)); \ + $(foreach p, $(TARGET_KERNEL_EXT_MODULES),\ + $$pwd; \ + $(call $(if $(filter $(word 2,$(subst :, ,$(p))),kbuild),make-kbuild-module-target,make-external-module-target),$(word 1,$(subst :, ,$(p))),$$rpath,) || exit "$$?"; \ + $(call $(if $(filter $(word 2,$(subst :, ,$(p))),kbuild),make-kbuild-module-target,make-external-module-target),$(word 1,$(subst :, ,$(p))),$$rpath,INSTALL_MOD_PATH=$(MODULES_INTERMEDIATES) INSTALL_MOD_STRIP=1 KERNEL_UAPI_HEADERS_DIR=$(KERNEL_OUT) modules_install)) || exit "$$?"; \ + ) \ kernel_release=$$(cat $(KERNEL_RELEASE)) \ kernel_modules_dir=$(MODULES_INTERMEDIATES)/lib/modules/$$kernel_release \ $(foreach s, $(TARGET_MODULE_ALIASES),\ $(eval p := $(subst :,$(space),$(s))) \ ; mv $$(find $$kernel_modules_dir -name $(word 1,$(p))) $$kernel_modules_dir/$(word 2,$(p))); \ - modules=$$(find $$kernel_modules_dir -type f -name '*.ko'); \ - ($(call build-image-kernel-modules-twrp,$$modules,$(KERNEL_MODULES_OUT),$(KERNEL_MODULE_MOUNTPOINT)/,$(KERNEL_DEPMOD_STAGING_DIR),$(BOARD_VENDOR_KERNEL_MODULES_LOAD))); \ + all_modules=$$(find $$kernel_modules_dir -type f -name '*.ko'); \ + filtered_modules=""; \ + $(if $(SYSTEM_KERNEL_MODULES),\ + gki_modules=$$(for m in $(SYSTEM_KERNEL_MODULES); do \ + p=$$(find $$kernel_modules_dir -type f -name $$m); \ + if [ -n "$$p" ]; then echo $$p; else echo "ERROR: $$m from SYSTEM_KERNEL_MODULES was not found" 1>&2 && exit 1; fi; \ + done); \ + [ $$? -ne 0 ] && exit 1; \ + ($(call build-image-kernel-modules-twrp,$$gki_modules,$(SYSTEM_KERNEL_MODULES_OUT),$(SYSTEM_KERNEL_MODULE_MOUNTPOINT)/,$(SYSTEM_KERNEL_DEPMOD_STAGING_DIR),$(BOARD_SYSTEM_KERNEL_MODULES_LOAD),/$(GKI_SUFFIX))) || exit "$$?"; \ + filtered_modules=$$(for n in $$all_modules; do \ + module_name=$$(basename $$n); \ + if [[ ! "$(SYSTEM_KERNEL_MODULES)" =~ "$$module_name" ]]; then echo $$n; fi; \ + done); \ + ($(call build-image-kernel-modules-twrp,$$filtered_modules,$(KERNEL_MODULES_OUT),$(KERNEL_MODULE_MOUNTPOINT)/,$(KERNEL_DEPMOD_STAGING_DIR),$(BOARD_VENDOR_KERNEL_MODULES_LOAD),/)) || exit "$$?"; \ + ,\ + ($(call build-image-kernel-modules-twrp,$$all_modules,$(KERNEL_MODULES_OUT),$(KERNEL_MODULE_MOUNTPOINT)/,$(KERNEL_DEPMOD_STAGING_DIR),$(BOARD_VENDOR_KERNEL_MODULES_LOAD),/)) || exit "$$?"; \ + ) \ $(if $(BOOT_KERNEL_MODULES),\ vendor_boot_modules=$$(for m in $(BOOT_KERNEL_MODULES); do \ p=$$(find $$kernel_modules_dir -type f -name $$m); \ if [ -n "$$p" ]; then echo $$p; else echo "ERROR: $$m from BOOT_KERNEL_MODULES was not found" 1>&2 && exit 1; fi; \ done); \ [ $$? -ne 0 ] && exit 1; \ - ($(call build-image-kernel-modules-twrp,$$vendor_boot_modules,$(TARGET_VENDOR_RAMDISK_OUT),/,$(KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR),$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD))); \ + ($(call build-image-kernel-modules-twrp,$$vendor_boot_modules,$(KERNEL_VENDOR_RAMDISK_MODULES_OUT),/,$(KERNEL_VENDOR_RAMDISK_DEPMOD_STAGING_DIR),$(KERNEL_VENDOR_RAMDISK_KERNEL_MODULES_LOAD),/)) || exit "$$?"; \ + ) \ + $(if $(RECOVERY_KERNEL_MODULES),\ + recovery_modules=$$(for m in $(RECOVERY_KERNEL_MODULES); do \ + p=$$(find $$kernel_modules_dir -type f -name $$m); \ + if [ -n "$$p" ]; then echo $$p; else echo "ERROR: $$m from RECOVERY_KERNEL_MODULES was not found" 1>&2 && exit 1; fi; \ + done); \ + [ $$? -ne 0 ] && exit 1; \ + ($(call build-image-kernel-modules-twrp,$$recovery_modules,$(KERNEL_RECOVERY_MODULES_OUT),/,$(KERNEL_RECOVERY_DEPMOD_STAGING_DIR),$(BOARD_RECOVERY_RAMDISK_KERNEL_MODULES_LOAD),/)) || exit "$$?"; \ ) \ fi @@ -348,10 +464,9 @@ kerneltags: $(KERNEL_CONFIG) .PHONY: kernelsavedefconfig alldefconfig kernelsavedefconfig: $(KERNEL_OUT) - $(call make-kernel-target,$(KERNEL_DEFCONFIG)) - env KCONFIG_NOTIMESTAMP=true \ - $(call make-kernel-target,savedefconfig) - cp $(KERNEL_OUT)/defconfig $(KERNEL_DEFCONFIG_SRC) + $(call make-kernel-config,$(KERNEL_OUT),$(BASE_KERNEL_DEFCONFIG)) + $(call make-kernel-target,savedefconfig) + cp $(KERNEL_OUT)/defconfig $(BASE_KERNEL_DEFCONFIG_SRC) alldefconfig: $(KERNEL_OUT) env KCONFIG_NOTIMESTAMP=true \ @@ -362,35 +477,87 @@ ifneq ($(BOARD_CUSTOM_DTBOIMG_MK),) include $(BOARD_CUSTOM_DTBOIMG_MK) else MKDTIMG := $(HOST_OUT_EXECUTABLES)/mkdtimg$(HOST_EXECUTABLE_SUFFIX) -MKDTBOIMG := $(HOST_OUT_EXECUTABLES)/mkdtboimg.py$(HOST_EXECUTABLE_SUFFIX) +MKDTBOIMG := $(HOST_OUT_EXECUTABLES)/mkdtboimg$(HOST_EXECUTABLE_SUFFIX) + +$(DTBO_OUT): + mkdir -p $(DTBO_OUT) + +ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) +$(BOARD_PREBUILT_DTBOIMAGE): $(INSTALLED_DTBIMAGE_TARGET) +else +$(BOARD_PREBUILT_DTBOIMAGE): $(DTBO_OUT) +endif $(BOARD_PREBUILT_DTBOIMAGE): $(DTC) $(MKDTIMG) $(MKDTBOIMG) -ifeq ($(BOARD_KERNEL_SEPARATED_DTBO),true) $(BOARD_PREBUILT_DTBOIMAGE): @echo "Building dtbo.img" +ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) + $(MKDTBOIMG) create $@ --page_size=$(BOARD_KERNEL_PAGESIZE) $(shell find $(DTBS_OUT) -type f -name "*.dtbo" | sort) +else + $(hide) find $(DTBO_OUT)/arch/$(KERNEL_ARCH)/boot/dts -type f -name "*.dtbo" | xargs rm -f $(call make-dtbo-target,$(KERNEL_DEFCONFIG)) - $(call make-dtbo-target,dtbs) + $(call make-dtbo-target,$(TARGET_KERNEL_DTB)) +ifeq ($(BOARD_KERNEL_SEPARATED_DTBO),true) ifdef BOARD_DTBO_CFG $(MKDTBOIMG) cfg_create $@ $(BOARD_DTBO_CFG) -d $(DTBO_OUT)/arch/$(KERNEL_ARCH)/boot/dts else $(MKDTBOIMG) create $@ --page_size=$(BOARD_KERNEL_PAGESIZE) $(shell find $(DTBO_OUT)/arch/$(KERNEL_ARCH)/boot/dts -type f -name "*.dtbo" | sort) -endif +endif # BOARD_DTBO_CFG else -$(BOARD_PREBUILT_DTBOIMAGE): - @echo "Building dtbo.img" - $(call make-dtbo-target,$(KERNEL_DEFCONFIG)) - $(call make-dtbo-target,dtbo.img) + $(call make-dtbo-target,$(TARGET_KERNEL_DTBO)) endif # BOARD_KERNEL_SEPARATED_DTBO + $(hide) touch -c $(DTBO_OUT) +endif # BOARD_USES_QCOM_MERGE_DTBS_SCRIPT endif # BOARD_CUSTOM_DTBOIMG_MK endif # TARGET_NEEDS_DTBOIMAGE/BOARD_KERNEL_SEPARATED_DTBO ifeq ($(BOARD_INCLUDE_DTB_IN_BOOTIMG),true) +ifneq ($(BOARD_CUSTOM_DTBIMG_MK),) +include $(BOARD_CUSTOM_DTBIMG_MK) +else ifeq ($(BOARD_PREBUILT_DTBIMAGE_DIR),) -$(INSTALLED_DTBIMAGE_TARGET): $(DTC) +$(DTB_OUT): + mkdir -p $(DTB_OUT) +ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) +$(DTBS_BASE): + mkdir -p $(DTBS_BASE) +$(DTBS_OUT): + mkdir -p $(DTBS_OUT) +endif + +ifdef BOARD_DTB_CFG +MKDTBOIMG := $(HOST_OUT_EXECUTABLES)/mkdtboimg$(HOST_EXECUTABLE_SUFFIX) +$(INSTALLED_DTBIMAGE_TARGET): $(MKDTBOIMG) +endif +ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) +$(INSTALLED_DTBIMAGE_TARGET): $(HOST_OUT_EXECUTABLES)/fdtget $(HOST_OUT_EXECUTABLES)/fdtput $(HOST_OUT_EXECUTABLES)/fdtoverlay $(HOST_OUT_EXECUTABLES)/fdtoverlaymerge $(HOST_OUT_EXECUTABLES)/ufdt_apply_overlay $(DTBS_BASE) $(DTBS_OUT) +endif +$(INSTALLED_DTBIMAGE_TARGET): $(DTC) $(DTB_OUT) +ifeq ($(TARGET_WANTS_EMPTY_DTB),true) + @rm -f $@ + echo "empty" > $@ +else @echo "Building dtb.img" + $(hide) find $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts -type f -name "*.dtb" | xargs rm -f $(call make-dtb-target,$(KERNEL_DEFCONFIG)) - $(call make-dtb-target,dtbs) + $(call make-dtb-target,$(TARGET_KERNEL_DTB)) +ifdef BOARD_DTB_CFG + $(MKDTBOIMG) cfg_create $@ $(BOARD_DTB_CFG) -d $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts +else +ifeq ($(BOARD_USES_QCOM_MERGE_DTBS_SCRIPT),true) + $(hide) find $(DTBS_BASE) -type f -name "*.dtb*" | xargs rm -f + $(hide) find $(DTBS_OUT) -type f -name "*.dtb*" | xargs rm -f + mv $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/qcom/*.dtb $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/*/*.dtbo $(DTBS_BASE)/ + PATH=$(abspath $(HOST_OUT_EXECUTABLES)):$${PATH} python3 $(BUILD_TOP)/vendor/twrp/build/tools/merge_dtbs.py $(DTBS_BASE) $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts/vendor/qcom $(DTBS_OUT) + cat $(shell find $(DTB_OUT)/out -type f -name "${TARGET_MERGE_DTBS_WILDCARD}.dtb" | sort) > $@ +else cat $(shell find $(DTB_OUT)/arch/$(KERNEL_ARCH)/boot/dts -type f -name "*.dtb" | sort) > $@ +endif # BOARD_USES_QCOM_MERGE_DTBS_SCRIPT +endif # BOARD_DTB_CFG + $(hide) touch -c $(DTB_OUT) +endif # !TARGET_WANTS_EMPTY_DTB + endif # !BOARD_PREBUILT_DTBIMAGE_DIR +endif # BOARD_CUSTOM_DTBIMG_MK endif # BOARD_INCLUDE_DTB_IN_BOOTIMG endif # FULL_KERNEL_BUILD @@ -402,21 +569,43 @@ define twrp-depmod $(DEPMOD) -b $(TARGET_RECOVERY_ROOT_OUT)/vendor 1.1 endef endif + +ifeq ($(FULL_RECOVERY_KERNEL_BUILD),true) + +$(RECOVERY_KERNEL_OUT): + mkdir -p $(RECOVERY_KERNEL_OUT) + +$(RECOVERY_KERNEL_CONFIG): $(ALL_RECOVERY_KERNEL_DEFCONFIG_SRCS) + @echo "Building Recovery Kernel Config" + $(call make-kernel-config,$(RECOVERY_KERNEL_OUT),$(RECOVERY_DEFCONFIG)) + +$(TARGET_PREBUILT_INT_RECOVERY_KERNEL): $(RECOVERY_KERNEL_CONFIG) $(DEPMOD) $(DTC) + @echo "Building Recovery Kernel Image ($(BOARD_KERNEL_IMAGE_NAME))" + $(call make-recovery-kernel-target,$(BOARD_KERNEL_IMAGE_NAME)) + + +endif + ## Install it ifeq ($(NEEDS_KERNEL_COPY),true) -file := $(INSTALLED_KERNEL_TARGET) -ALL_PREBUILT += $(file) -$(file) : $(KERNEL_BIN) | $(ACP) | $(DEPMOD) - $(transform-prebuilt-to-target) ifneq ($(TW_LOAD_VENDOR_MODULES),) ifdef TARGET_PREBUILT_KERNEL $(call twrp-depmod) endif endif -ALL_PREBUILT += $(INSTALLED_KERNEL_TARGET) +$(INSTALLED_KERNEL_TARGET): $(KERNEL_BIN) + $(transform-prebuilt-to-target) endif +ifeq ($(RECOVERY_KERNEL_COPY),true) +$(INSTALLED_RECOVERY_KERNEL_TARGET): $(RECOVERY_BIN) + $(transform-prebuilt-to-target) +endif + +.PHONY: recovery-kernel +recovery-kernel: $(INSTALLED_RECOVERY_KERNEL) + .PHONY: kernel kernel: $(INSTALLED_KERNEL_TARGET) diff --git a/build/tools/merge_dtbs.py b/build/tools/merge_dtbs.py new file mode 100755 index 0000000..898be4c --- /dev/null +++ b/build/tools/merge_dtbs.py @@ -0,0 +1,436 @@ +#! /usr/bin/env python3 + +# Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of The Linux Foundation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import copy +import os +import sys +import subprocess +import shutil +from itertools import product, combinations_with_replacement, chain + +def split_array(array, cells): + """ + Helper function for parsing fdtget output + """ + if array is None: + return None + assert (len(array) % cells) == 0 + return frozenset(tuple(array[i*cells:(i*cells)+cells]) for i in range(len(array) // cells)) + +class DeviceTreeInfo(object): + def __init__(self, plat, board, pmic): + self.plat_id = plat + self.board_id = board + self.pmic_id = pmic + + def __str__(self): + s = "" + if self.plat_id is not None: + s += " msm-id = <{}>;".format(" ".join(map(str, self.plat_id))) + if self.board_id is not None: + s += " board-id = <{}>;".format(" ".join(map(str, self.board_id))) + if self.pmic_id is not None: + s += " pmic-id = <{}>;".format(" ".join(map(str, self.pmic_id))) + return s.strip() + + def __repr__(self): + return "<{} {}>".format(self.__class__.__name__, str(self)) + + def has_any_properties(self): + return self.plat_id is not None or self.board_id is not None or self.pmic_id is not None + + def __sub__(self, other): + """ + This devicetree has plat, board, and pmic id described like this: + msm-id = , + board-id = , + pmic-id = <0, 1> + + Other has plat, board, pmic are: + msm-id = , + board-id = + pmic-id = <0> + + (self - other) will split self into a set of devicetrees with different identifers + and meets the following requirements: + - One of the devicetrees matches the IDs supported by other + - The devices which self matches are still supported (through 1 or more extra devicetrees) + by creating new devicetrees with different plat/board/pmic IDs + """ + assert self.plat_id is None or isinstance(self.plat_id, (set, frozenset)) + assert self.board_id is None or isinstance(self.board_id, (set, frozenset)) + assert self.pmic_id is None or isinstance(self.pmic_id, (set, frozenset)) + assert other in self + + new_plat = other.plat_id is not None and self.plat_id != other.plat_id + new_board = other.board_id is not None and self.board_id != other.board_id + new_pmic = other.pmic_id is not None and self.pmic_id != other.pmic_id + + res = set() + # Create the devicetree that matches other exactly + s = copy.deepcopy(self) + if new_plat: + s.plat_id = other.plat_id + if new_board: + s.board_id = other.board_id + if new_pmic: + s.pmic_id = other.pmic_id + res.add(s) + + # now create the other possibilities by removing any combination of + # other's plat, board, and/or pmic. Set logic (unique elemnts) handles + # duplicate devicetrees IDs spit out by this loop + for combo in combinations_with_replacement([True, False], 3): + if not any((c and n) for (c, n) in zip(combo, (new_plat, new_board, new_pmic))): + continue + s = copy.deepcopy(self) + if combo[0] and new_plat: + s.plat_id -= other.plat_id + if combo[1] and new_board: + s.board_id -= other.board_id + if combo[2] and new_pmic: + s.pmic_id -= other.pmic_id + res.add(s) + return res + + def __hash__(self): + # Hash should only consider msm-id/board-id/pmic-id + return hash((self.plat_id, self.board_id, self.pmic_id)) + + def __and__(self, other): + s = copy.deepcopy(self) + for prop in ['plat_id', 'board_id', 'pmic_id']: + if getattr(self, prop) is None or getattr(other, prop) is None: + setattr(s, prop, None) + else: + setattr(s, prop, getattr(self, prop) & getattr(other, prop)) + return s + + def _do_equivalent(self, other, property): + other_prop = getattr(other, property) + self_prop = getattr(self, property) + if other_prop is None: + return True + return self_prop == other_prop + + def __eq__(self, other): + """ + Checks whether other plat_id, board_id, pmic_id matches either identically + or because the property is none + """ + if not isinstance(other, DeviceTreeInfo): + return False + if not other.has_any_properties(): + return False + return all(map(lambda p: self._do_equivalent(other, p), ['plat_id', 'board_id', 'pmic_id'])) + + + def _do_gt(self, other, property): + other_prop = getattr(other, property) + self_prop = getattr(self, property) + # if either property doesn't exist, it could merge in ABL + if self_prop is None or other_prop is None: + return True + # convert to iterable for convenience of below check + if isinstance(other_prop, tuple): + # if this property is all 0s, ABL coud match with anything on other + other_prop = [other_prop] + assert hasattr(other_prop, '__iter__') + if len(other_prop) == 1 and all(p == 0 for p in next(iter(other_prop))): + return True + # Test if this property intersects with other property + if hasattr(self_prop, '__contains__') and not isinstance(self_prop, tuple): + return any(p in self_prop for p in other_prop) + else: + return self_prop in other_prop + + def __gt__(self, other): + """ + Test if other is a more specific devicetree for self + + This is used to test whether other devicetree applies to self by ABL matching rules + """ + if not isinstance(other, DeviceTreeInfo): + return False + if not other.has_any_properties(): + return False + return all(map(lambda p: self._do_gt(other, p), ['plat_id', 'board_id', 'pmic_id'])) + + + def _do_contains(self, other, property): + other_prop = getattr(other, property) + self_prop = getattr(self, property) + # if other property doesn't exist, it can apply here + if other_prop is None: + return True + # if self and other are sets, use "issubset". Handle special case where other set is + # empty, in which case they aren't compatible because other_prop should be None + if isinstance(self_prop, (set, frozenset)) and isinstance(other_prop, (set, frozenset)): + return len(other_prop) > 0 and other_prop.issubset(self_prop) + # unpack to one item for convience of below check + if hasattr(other_prop, '__len__') and not isinstance(other_prop, tuple): + if len(other_prop) == 1: + other_prop = next(iter(other_prop)) + # if this is a single value (tuple), not a list of them, other needs to match exactly + if isinstance(self_prop, tuple): + return self_prop == other_prop + # otherwise, use contains if possible (e.g. list or set of tuples) + if hasattr(self_prop, '__contains__'): + return other_prop in self_prop + return False + + def __contains__(self, other): + """ + Test if other devicetree covers this devicetree. That is, the devices other devicetree + matches is a subset of the devices this devicetree matches + """ + if not isinstance(other, DeviceTreeInfo): + return False + if not other.has_any_properties(): + return False + return all(map(lambda p: self._do_contains(other, p), ['plat_id', 'board_id', 'pmic_id'])) + +class DeviceTree(DeviceTreeInfo): + def __init__(self, filename): + self.filename = filename + msm_id = split_array(self.get_prop('/', 'qcom,msm-id', check_output=False), 2) + board_id = split_array(self.get_prop('/', 'qcom,board-id', check_output=False), 2) + # default pmic-id-size is 4 + pmic_id_size = self.get_prop('/', 'qcom,pmic-id-size', check_output=False) or 4 + pmic_id = split_array(self.get_prop('/', 'qcom,pmic-id', check_output=False), pmic_id_size) + super().__init__(msm_id, board_id, pmic_id) + + if not self.has_any_properties(): + print('WARNING! {} has no properties and may match with any other devicetree'.format(self.filename)) + + def get_prop(self, node, property, prop_type='i', check_output=True): + r = subprocess.run(["fdtget", "-t", prop_type, self.filename, node, property], + check=check_output, stdout=subprocess.PIPE, + stderr=None if check_output else subprocess.DEVNULL) + if r.returncode != 0: + return None + out = r.stdout.decode("utf-8").strip() + + out_array = None + if prop_type[-1] == 'i' or prop_type[-1] == 'u': + out_array = [int(e) for e in out.split(' ')] + if prop_type[-1] == 'x': + out_array = [int(e, 16) for e in out.split(' ')] + if out_array is not None: + if len(out_array) == 0: + return None + if len(out_array) == 1: + return out_array[0] + return out_array + + return out + + def __str__(self): + return "{} [{}]".format(super().__str__(), self.filename) + +class InnerMergedDeviceTree(DeviceTreeInfo): + """ + InnerMergedDeviceTree is an actual representation of a merged devicetree. + It has a platform, board, and pmic ID, the "base" devicetree, and some set of add-on + devicetrees + """ + def __init__(self, filename, plat_id, board_id, pmic_id, techpacks=None): + self.base = filename + self.techpacks = techpacks or [] + super().__init__(plat_id, board_id, pmic_id) + + def try_add(self, techpack): + if not isinstance(techpack, DeviceTree): + raise TypeError("{} is not a DeviceTree object".format(repr(techpack))) + intersection = techpack & self + if intersection in self: + self.techpacks.append(intersection) + return True + return False + + def save(self, name=None, out_dir='.'): + if name is None: + name = self.get_name() + + out_file = os.path.join(out_dir, name) + ext = os.path.splitext(os.path.basename(self.base))[1] + + # This check might fail in future if we get into an edge case + # when splitting the base devicetree into multiple merged DTs + assert not os.path.exists(out_file) + + if len(self.techpacks) == 0: + cmd = ['cp', self.base, out_file] + else: + if ext == '.dtb': + cmd = ['fdtoverlay'] + else: + cmd = ['fdtoverlaymerge'] + cmd.extend(['-i', self.base]) + cmd.extend([tp.filename for tp in self.techpacks]) + cmd.extend(['-o', out_file]) + + print(' {}'.format(' '.join(cmd))) + subprocess.run(cmd, check=True) + + if self.plat_id: + plat_iter = self.plat_id if isinstance(self.plat_id, tuple) else chain.from_iterable(self.plat_id) + cmd = ['fdtput', '-t', 'i', out_file, '/', 'qcom,msm-id'] + list(map(str, plat_iter)) + print(' {}'.format(' '.join(cmd))) + subprocess.run(cmd, check=True) + + if self.board_id: + board_iter = self.board_id if isinstance(self.board_id, tuple) else chain.from_iterable(self.board_id) + cmd = ['fdtput', '-t', 'i', out_file, '/', 'qcom,board-id'] + list(map(str, board_iter)) + print(' {}'.format(' '.join(cmd))) + subprocess.run(cmd, check=True) + + if self.pmic_id: + pmic_iter = self.pmic_id if isinstance(self.pmic_id, tuple) else chain.from_iterable(self.pmic_id) + cmd = ['fdtput', '-t', 'i', out_file, '/', 'qcom,pmic-id'] + list(map(str, pmic_iter)) + print(' {}'.format(' '.join(cmd))) + subprocess.run(cmd, check=True) + + return DeviceTree(out_file) + + def get_name(self): + ext = os.path.splitext(os.path.basename(self.base))[1] + base_parts = self.filename_to_parts(self.base) + return '-'.join(chain.from_iterable([base_parts] + [self.filename_to_parts(tp.filename, ignored_parts=base_parts) for tp in self.techpacks])) + ext + + @staticmethod + def filename_to_parts(name, ignored_parts=[]): + # Extract just the basename, with no suffix + filename = os.path.splitext(os.path.basename(name))[0] + parts = filename.split('-') + return [part for part in parts if part not in ignored_parts] + + def __str__(self): + return "{} [{} + {{{}}}]".format(super().__str__(), self.base, " ".join(t.filename for t in self.techpacks)) + +class MergedDeviceTree(object): + def __init__(self, other): + self.merged_devicetrees = {InnerMergedDeviceTree(other.filename, other.plat_id, other.board_id, other.pmic_id)} + + def try_add(self, techpack): + did_add = False + for mdt in self.merged_devicetrees.copy(): + # techpack and kernel devicetree need only to overlap in order to merge, + # and not match exactly. Think: venn diagram. + # Need 2 things: The devicetree part that applies to + # both kernel and techpack intersection = (techpack & mdt) + # and the part that applies only to kernel difference = (mdt - intersection) + # Note that because devicetrees are "multi-dimensional", doing (mdt - intersection) + # may result in *multiple* devicetrees + + # techpack may apply to a superset of devices the mdt applies to + # reduce the techpack to just the things mdt has: + intersection = techpack & mdt + if intersection not in mdt: + continue + # mdt may apply to a superset of devices the techpack DT applies to + # (mdt - intersection) splits mdt into appropriate number of devicetrees + # such that we can apply techpack onto one of the resulting DTs in the + # difference + difference = mdt - intersection + if len(difference) > 1: + print('Splitting {}'.format(mdt)) + print(' because {}'.format(techpack)) + self.merged_devicetrees.remove(mdt) + self.merged_devicetrees.update(difference) + + for mdt in self.merged_devicetrees: + if mdt.try_add(techpack): + did_add = True + return did_add + + + def save(self, out_dir): + assert len(self.merged_devicetrees) > 0 + if len(self.merged_devicetrees) == 1: + name = os.path.basename(next(iter(self.merged_devicetrees)).base) + else: + name = None + for mdt in self.merged_devicetrees: + print() + yield mdt.save(name, out_dir) + +def parse_dt_files(dt_folder): + for root, dirs, files in os.walk(dt_folder): + for filename in files: + if os.path.splitext(filename)[1] not in ['.dtb', '.dtbo']: + continue + filepath = os.path.join(root, filename) + yield DeviceTree(filepath) + +def main(): + if len(sys.argv) != 4: + print("Usage: {} " + .format(sys.argv[0])) + sys.exit(1) + + # 1. Parse the devicetrees -- extract the device info (msm-id, board-id, pmic-id) + bases = parse_dt_files(sys.argv[1]) + techpacks = parse_dt_files(sys.argv[2]) + + # 2.1: Create an intermediate representation of the merged devicetrees, starting with the base + merged_devicetrees = list(map(lambda dt: MergedDeviceTree(dt), bases)) + # 2.2: Try to add techpack devicetree to each base DT + for techpack in techpacks: + did_add = False + for dt in merged_devicetrees: + if dt.try_add(techpack): + did_add = True + if not did_add: + print('WARNING! Could not apply {} to any devicetrees'.format(techpack)) + + print() + print('==================================') + created = [] + # 3. Save the deviectrees to real files + for dt in merged_devicetrees: + created.extend(dt.save(sys.argv[3])) + + print() + print('==================================') + # 4. Try to apply merged DTBOs onto merged DTBs, when appropriate + # This checks that DTBOs and DTBs generated by merge_dtbs.py can be merged by bootloader + # at runtime. + for base, dtbo in product(created, created): + if os.path.splitext(base.filename)[1] != '.dtb' or os.path.splitext(dtbo.filename)[1] != '.dtbo': + continue + # See DeviceTreeInfo.__gt__; this checks whether dtbo is more specific than the base + if dtbo > base: + cmd = ['ufdt_apply_overlay', base.filename, dtbo.filename, '/dev/null'] + print(' '.join(cmd)) + subprocess.run(cmd, check=True) + + +if __name__ == "__main__": + main() diff --git a/build/tools/roomservice.py b/build/tools/roomservice.py index 8983888..5d01d63 100755 --- a/build/tools/roomservice.py +++ b/build/tools/roomservice.py @@ -43,7 +43,7 @@ except ImportError: DEBUG = False custom_local_manifest = ".repo/local_manifests/roomservice.xml" -custom_default_revision = os.getenv('ROOMSERVICE_DEFAULT_BRANCH', 'android-12.1') +custom_default_revision = os.getenv('ROOMSERVICE_DEFAULT_BRANCH', 'android-14') custom_dependencies = "twrp.dependencies" org_manifest = "TeamWin" # leave empty if org is provided in manifest org_display = "TeamWin" # needed for displaying diff --git a/config/BoardConfigKernel.mk b/config/BoardConfigKernel.mk index 7042ccc..6a02545 100644 --- a/config/BoardConfigKernel.mk +++ b/config/BoardConfigKernel.mk @@ -1,4 +1,4 @@ -# Copyright (C) 2018-2020 The LineageOS Project +# Copyright (C) 2018-2024 The LineageOS Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -31,6 +31,27 @@ # x86_64-linux-android- for x86 # # TARGET_KERNEL_CLANG_COMPILE = Compile kernel with clang, defaults to true +# TARGET_KERNEL_CLANG_VERSION = Clang prebuilts version, optional, defaults to clang-stable +# TARGET_KERNEL_CLANG_PATH = Clang prebuilts path, optional +# +# TARGET_KERNEL_LLVM_BINUTILS = Use LLVM binutils, defaults to true +# TARGET_KERNEL_NO_GCC = Fully compile the kernel without GCC. +# Defaults to false +# TARGET_KERNEL_VERSION = Reported kernel version in top level kernel +# makefile. Can be overriden in device trees +# in the event of prebuilt kernel. +# +# TARGET_KERNEL_DTBO_PREFIX = Override path prefix of TARGET_KERNEL_DTBO. +# Defaults to empty +# TARGET_KERNEL_DTBO = Name of the kernel Makefile target that +# generates dtbo.img. Defaults to dtbo.img +# TARGET_KERNEL_DTB = Name of the kernel Makefile target that +# generates the *.dtb targets. Defaults to dtbs +# +# TARGET_KERNEL_EXT_MODULE_ROOT = Optional, the external modules root directory +# Defaults to empty +# TARGET_KERNEL_EXT_MODULES = Optional, the external modules we are +# building. Defaults to empty # # KERNEL_TOOLCHAIN_PREFIX = Overrides TARGET_KERNEL_CROSS_COMPILE_PREFIX, # Set this var in shell to override @@ -40,7 +61,7 @@ # is in PATH # USE_CCACHE = Enable ccache (global Android flag) -BUILD_TOP := $(shell pwd) +BUILD_TOP := $(abspath .) TARGET_AUTO_KDIR := $(shell echo $(TARGET_DEVICE_DIR) | sed -e 's/^device/kernel/g') TARGET_KERNEL_SOURCE ?= $(TARGET_AUTO_KDIR) @@ -51,40 +72,37 @@ endif TARGET_KERNEL_ARCH := $(strip $(TARGET_KERNEL_ARCH)) ifeq ($(TARGET_KERNEL_ARCH),) -KERNEL_ARCH := $(TARGET_ARCH) + KERNEL_ARCH := $(TARGET_ARCH) else -KERNEL_ARCH := $(TARGET_KERNEL_ARCH) + KERNEL_ARCH := $(TARGET_KERNEL_ARCH) endif -CLANG_PREBUILTS := $(BUILD_TOP)/prebuilts/clang/host/$(HOST_PREBUILT_TAG)/clang-r416183b1 -GCC_PREBUILTS := $(BUILD_TOP)/prebuilts/gcc/$(HOST_PREBUILT_TAG) -# arm64 toolchain -KERNEL_TOOLCHAIN_arm64 := $(GCC_PREBUILTS)/aarch64/aarch64-linux-android-4.9/bin -KERNEL_TOOLCHAIN_PREFIX_arm64 := aarch64-linux-android- -# arm toolchain -KERNEL_TOOLCHAIN_arm := $(GCC_PREBUILTS)/arm/arm-linux-androideabi-4.9/bin -KERNEL_TOOLCHAIN_PREFIX_arm := arm-linux-androidkernel- -# x86 toolchain -KERNEL_TOOLCHAIN_x86 := $(GCC_PREBUILTS)/x86/x86_64-linux-android-4.9/bin -KERNEL_TOOLCHAIN_PREFIX_x86 := x86_64-linux-android- +KERNEL_VERSION := $(shell grep -s "^VERSION = " $(TARGET_KERNEL_SOURCE)/Makefile | awk '{ print $$3 }') +KERNEL_PATCHLEVEL := $(shell grep -s "^PATCHLEVEL = " $(TARGET_KERNEL_SOURCE)/Makefile | awk '{ print $$3 }') +TARGET_KERNEL_VERSION ?= $(shell echo $(KERNEL_VERSION)"."$(KERNEL_PATCHLEVEL)) -TARGET_KERNEL_CROSS_COMPILE_PREFIX := $(strip $(TARGET_KERNEL_CROSS_COMPILE_PREFIX)) -ifneq ($(TARGET_KERNEL_CROSS_COMPILE_PREFIX),) -KERNEL_TOOLCHAIN_PREFIX ?= $(TARGET_KERNEL_CROSS_COMPILE_PREFIX) -else -KERNEL_TOOLCHAIN ?= $(KERNEL_TOOLCHAIN_$(KERNEL_ARCH)) -KERNEL_TOOLCHAIN_PREFIX ?= $(KERNEL_TOOLCHAIN_PREFIX_$(KERNEL_ARCH)) +# 5.10+ can fully compile without GCC by default +ifneq ($(KERNEL_VERSION),) + ifeq ($(shell expr $(KERNEL_VERSION) \>= 6), 1) + TARGET_KERNEL_NO_GCC ?= true + else ifeq ($(shell expr $(KERNEL_VERSION) \>= 5), 1) + ifeq ($(shell expr $(KERNEL_PATCHLEVEL) \>= 10), 1) + TARGET_KERNEL_NO_GCC ?= true + endif + endif endif -ifeq ($(KERNEL_TOOLCHAIN),) -KERNEL_TOOLCHAIN_PATH := $(KERNEL_TOOLCHAIN_PREFIX) -else -KERNEL_TOOLCHAIN_PATH := $(KERNEL_TOOLCHAIN)/$(KERNEL_TOOLCHAIN_PREFIX) +ifeq ($(TARGET_KERNEL_NO_GCC), true) + KERNEL_NO_GCC := true endif -# We need to add GCC toolchain to the path no matter what -# for tools like `as` -KERNEL_TOOLCHAIN_PATH_gcc := $(KERNEL_TOOLCHAIN_$(KERNEL_ARCH)) +ifneq ($(TARGET_KERNEL_CLANG_VERSION),) + KERNEL_CLANG_VERSION := clang-$(TARGET_KERNEL_CLANG_VERSION) +else + # Use the default version of clang if TARGET_KERNEL_CLANG_VERSION hasn't been set by the device config + KERNEL_CLANG_VERSION := clang-r487747c +endif +TARGET_KERNEL_CLANG_PATH ?= $(BUILD_TOP)/prebuilts/clang/host/$(HOST_PREBUILT_TAG)/$(KERNEL_CLANG_VERSION) ifneq ($(USE_CCACHE),) ifneq ($(CCACHE_EXEC),) @@ -93,65 +111,120 @@ ifneq ($(USE_CCACHE),) endif endif -ifneq ($(TARGET_KERNEL_CLANG_COMPILE),false) - KERNEL_CROSS_COMPILE := CROSS_COMPILE="$(KERNEL_TOOLCHAIN_PATH)" -else - KERNEL_CROSS_COMPILE := CROSS_COMPILE="$(CCACHE_BIN) $(KERNEL_TOOLCHAIN_PATH)" -endif - -# Needed for CONFIG_COMPAT_VDSO, safe to set for all arm64 builds -ifeq ($(KERNEL_ARCH),arm64) - KERNEL_CROSS_COMPILE += CROSS_COMPILE_ARM32="$(KERNEL_TOOLCHAIN_arm)/$(KERNEL_TOOLCHAIN_PREFIX_arm)" -endif - # Clear this first to prevent accidental poisoning from env KERNEL_MAKE_FLAGS := -# Add back threads, ninja cuts this to $(nproc)/2 -KERNEL_MAKE_FLAGS += -j$(shell prebuilts/tools-lineage/$(HOST_PREBUILT_TAG)/bin/nproc --all) - -ifeq ($(KERNEL_ARCH),arm) - # Avoid "Unknown symbol _GLOBAL_OFFSET_TABLE_" errors - KERNEL_MAKE_FLAGS += CFLAGS_MODULE="-fno-pic" -endif - -ifeq ($(KERNEL_ARCH),arm64) - # Avoid "unsupported RELA relocation: 311" errors (R_AARCH64_ADR_GOT_PAGE) - KERNEL_MAKE_FLAGS += CFLAGS_MODULE="-fno-pic" -endif - -ifeq ($(HOST_OS),darwin) - KERNEL_MAKE_FLAGS += HOSTCFLAGS="-I$(BUILD_TOP)/external/elfutils/libelf -I/usr/local/opt/openssl/include -fuse-ld=lld" HOSTLDFLAGS="-L/usr/local/opt/openssl/lib -fuse-ld=lld" -else - KERNEL_MAKE_FLAGS += CPATH="/usr/include:/usr/include/x86_64-linux-gnu" HOSTCFLAGS="-fuse-ld=lld" HOSTLDFLAGS="-L/usr/lib/x86_64-linux-gnu -L/usr/lib64 -fuse-ld=lld" -endif - -ifneq ($(TARGET_KERNEL_ADDITIONAL_FLAGS),) - KERNEL_MAKE_FLAGS += $(TARGET_KERNEL_ADDITIONAL_FLAGS) -endif +# Add back threads, ninja cuts this to $(getconf _NPROCESSORS_ONLN)/2 +KERNEL_MAKE_FLAGS += -j$(shell getconf _NPROCESSORS_ONLN) TOOLS_PATH_OVERRIDE := \ - LD_LIBRARY_PATH=$(BUILD_TOP)/prebuilts/tools-lineage/$(HOST_PREBUILT_TAG)/lib:$$LD_LIBRARY_PATH \ PERL5LIB=$(BUILD_TOP)/prebuilts/tools-lineage/common/perl-base -ifeq ($(KERNEL_ARCH),arm64) - # Add 32-bit GCC to PATH so that arm-linux-androidkernel-as is available for CONFIG_COMPAT_VDSO - TOOLS_PATH_OVERRIDE += PATH=$(BUILD_TOP)/prebuilts/tools-lineage/$(HOST_PREBUILT_TAG)/bin:$(KERNEL_TOOLCHAIN_arm):$$PATH +ifneq ($(KERNEL_NO_GCC), true) + GCC_PREBUILTS := $(BUILD_TOP)/prebuilts/gcc/$(HOST_PREBUILT_TAG) + # arm64 toolchain + KERNEL_TOOLCHAIN_arm64 := $(GCC_PREBUILTS)/aarch64/aarch64-linux-android-4.9/bin + KERNEL_TOOLCHAIN_PREFIX_arm64 := aarch64-linux-android- + # arm toolchain + KERNEL_TOOLCHAIN_arm := $(GCC_PREBUILTS)/arm/arm-linux-androideabi-4.9/bin + KERNEL_TOOLCHAIN_PREFIX_arm := arm-linux-androidkernel- + # x86 toolchain + KERNEL_TOOLCHAIN_x86 := $(GCC_PREBUILTS)/x86/x86_64-linux-android-4.9/bin + KERNEL_TOOLCHAIN_PREFIX_x86 := x86_64-linux-android- + + TARGET_KERNEL_CROSS_COMPILE_PREFIX := $(strip $(TARGET_KERNEL_CROSS_COMPILE_PREFIX)) + ifneq ($(TARGET_KERNEL_CROSS_COMPILE_PREFIX),) + KERNEL_TOOLCHAIN_PREFIX ?= $(TARGET_KERNEL_CROSS_COMPILE_PREFIX) + else + KERNEL_TOOLCHAIN ?= $(KERNEL_TOOLCHAIN_$(KERNEL_ARCH)) + KERNEL_TOOLCHAIN_PREFIX ?= $(KERNEL_TOOLCHAIN_PREFIX_$(KERNEL_ARCH)) + endif + + ifeq ($(KERNEL_TOOLCHAIN),) + KERNEL_TOOLCHAIN_PATH := $(KERNEL_TOOLCHAIN_PREFIX) + else + KERNEL_TOOLCHAIN_PATH := $(KERNEL_TOOLCHAIN)/$(KERNEL_TOOLCHAIN_PREFIX) + endif + + # We need to add GCC toolchain to the path no matter what + # for tools like `as` + KERNEL_TOOLCHAIN_PATH_gcc := $(KERNEL_TOOLCHAIN_$(KERNEL_ARCH)) + + ifneq ($(TARGET_KERNEL_CLANG_COMPILE),false) + KERNEL_CROSS_COMPILE := CROSS_COMPILE="$(KERNEL_TOOLCHAIN_PATH)" + else + KERNEL_CROSS_COMPILE := CROSS_COMPILE="$(CCACHE_BIN) $(KERNEL_TOOLCHAIN_PATH)" + endif + + # Needed for CONFIG_COMPAT_VDSO, safe to set for all arm64 builds + ifeq ($(KERNEL_ARCH),arm64) + KERNEL_CROSS_COMPILE += CROSS_COMPILE_ARM32="$(KERNEL_TOOLCHAIN_arm)/$(KERNEL_TOOLCHAIN_PREFIX_arm)" + KERNEL_CROSS_COMPILE += CROSS_COMPILE_COMPAT="$(KERNEL_TOOLCHAIN_arm)/$(KERNEL_TOOLCHAIN_PREFIX_arm)" + endif + + ifeq ($(TARGET_KERNEL_CLANG_COMPILE),false) + ifeq ($(KERNEL_ARCH),arm) + # Avoid "Unknown symbol _GLOBAL_OFFSET_TABLE_" errors + KERNEL_MAKE_FLAGS += CFLAGS_MODULE="-fno-pic" + endif + + ifeq ($(KERNEL_ARCH),arm64) + # Avoid "unsupported RELA relocation: 311" errors (R_AARCH64_ADR_GOT_PAGE) + KERNEL_MAKE_FLAGS += CFLAGS_MODULE="-fno-pic" + endif + endif + + KERNEL_MAKE_FLAGS += CPATH="/usr/include:/usr/include/x86_64-linux-gnu" HOSTLDFLAGS="-L/usr/lib/x86_64-linux-gnu -L/usr/lib64 -fuse-ld=lld" + + ifeq ($(KERNEL_ARCH),arm64) + # Add 32-bit GCC to PATH so that arm-linux-androidkernel-as is available for CONFIG_COMPAT_VDSO + TOOLS_PATH_OVERRIDE += PATH=$(BUILD_TOP)/prebuilts/tools-lineage/$(HOST_PREBUILT_TAG)/bin:$(KERNEL_TOOLCHAIN_arm):$$PATH + else + TOOLS_PATH_OVERRIDE += PATH=$(BUILD_TOP)/prebuilts/tools-lineage/$(HOST_PREBUILT_TAG)/bin:$$PATH + endif + + # Set the full path to the clang command and LLVM binutils + KERNEL_MAKE_FLAGS += HOSTCC=$(TARGET_KERNEL_CLANG_PATH)/bin/clang + KERNEL_MAKE_FLAGS += HOSTCXX=$(TARGET_KERNEL_CLANG_PATH)/bin/clang++ + ifneq ($(TARGET_KERNEL_CLANG_COMPILE), false) + ifneq ($(TARGET_KERNEL_LLVM_BINUTILS), false) + KERNEL_MAKE_FLAGS += LD=$(TARGET_KERNEL_CLANG_PATH)/bin/ld.lld + KERNEL_MAKE_FLAGS += AR=$(TARGET_KERNEL_CLANG_PATH)/bin/llvm-ar + endif + endif else - TOOLS_PATH_OVERRIDE += PATH=$(BUILD_TOP)/prebuilts/tools-lineage/$(HOST_PREBUILT_TAG)/bin:$$PATH + KERNEL_MAKE_FLAGS += HOSTCFLAGS="--sysroot=$(BUILD_TOP)/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8/sysroot -I$(BUILD_TOP)/prebuilts/kernel-build-tools/linux-x86/include" + KERNEL_MAKE_FLAGS += HOSTLDFLAGS="--sysroot=$(BUILD_TOP)/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8/sysroot -Wl,-rpath,$(BUILD_TOP)/prebuilts/kernel-build-tools/linux-x86/lib64 -L $(BUILD_TOP)/prebuilts/kernel-build-tools/linux-x86/lib64 -fuse-ld=lld --rtlib=compiler-rt" + + TOOLS_PATH_OVERRIDE += PATH=$(BUILD_TOP)/prebuilts/tools-lineage/$(HOST_PREBUILT_TAG)/bin:$(TARGET_KERNEL_CLANG_PATH)/bin:$$PATH endif # Set DTBO image locations so the build system knows to build them ifeq (true,$(filter true, $(TARGET_NEEDS_DTBOIMAGE) $(BOARD_KERNEL_SEPARATED_DTBO))) -BOARD_PREBUILT_DTBOIMAGE ?= $(TARGET_OUT_INTERMEDIATES)/DTBO_OBJ/arch/$(KERNEL_ARCH)/boot/dtbo.img + TARGET_KERNEL_DTBO_PREFIX ?= + TARGET_KERNEL_DTBO ?= dtbo.img + BOARD_PREBUILT_DTBOIMAGE ?= $(TARGET_OUT_INTERMEDIATES)/DTBO_OBJ/arch/$(KERNEL_ARCH)/boot/$(TARGET_KERNEL_DTBO_PREFIX)$(TARGET_KERNEL_DTBO) endif +# Set the default dtb target +TARGET_KERNEL_DTB ?= dtbs + +# Set no external modules by default +TARGET_KERNEL_EXT_MODULE_ROOT ?= +TARGET_KERNEL_EXT_MODULES ?= + # Set use the full path to the make command KERNEL_MAKE_CMD := $(BUILD_TOP)/prebuilts/build-tools/$(HOST_PREBUILT_TAG)/bin/make -# Set the full path to the clang command -KERNEL_MAKE_FLAGS += HOSTCC=$(CLANG_PREBUILTS)/bin/clang -KERNEL_MAKE_FLAGS += HOSTCXX=$(CLANG_PREBUILTS)/bin/clang++ +# Use LLVM's substitutes for GNU binutils +ifneq ($(TARGET_KERNEL_CLANG_COMPILE), false) + ifneq ($(TARGET_KERNEL_LLVM_BINUTILS), false) + KERNEL_MAKE_FLAGS += LLVM=1 LLVM_IAS=1 + endif +endif + +# Pass prebuilt LZ4 path +KERNEL_MAKE_FLAGS += LZ4=$(BUILD_TOP)/prebuilts/kernel-build-tools/linux-x86/bin/lz4 # Since Linux 4.16, flex and bison are required KERNEL_MAKE_FLAGS += LEX=$(BUILD_TOP)/prebuilts/build-tools/$(HOST_PREBUILT_TAG)/bin/flex @@ -159,10 +232,13 @@ KERNEL_MAKE_FLAGS += YACC=$(BUILD_TOP)/prebuilts/build-tools/$(HOST_PREBUILT_TAG KERNEL_MAKE_FLAGS += M4=$(BUILD_TOP)/prebuilts/build-tools/$(HOST_PREBUILT_TAG)/bin/m4 TOOLS_PATH_OVERRIDE += BISON_PKGDATADIR=$(BUILD_TOP)/prebuilts/build-tools/common/bison +# Since Linux 5.10, pahole is required +KERNEL_MAKE_FLAGS += PAHOLE=$(BUILD_TOP)/prebuilts/kernel-build-tools/linux-x86/bin/pahole + # Set the out dir for the kernel's O= arg # This needs to be an absolute path, so only set this if the standard out dir isn't used OUT_DIR_PREFIX := $(shell echo $(OUT_DIR) | sed -e 's|/target/.*$$||g') KERNEL_BUILD_OUT_PREFIX := ifeq ($(OUT_DIR_PREFIX),out) -KERNEL_BUILD_OUT_PREFIX := $(BUILD_TOP)/ + KERNEL_BUILD_OUT_PREFIX := $(BUILD_TOP)/ endif diff --git a/config/BoardConfigSoong.mk b/config/BoardConfigSoong.mk index 0b8c06b..dbaa987 100644 --- a/config/BoardConfigSoong.mk +++ b/config/BoardConfigSoong.mk @@ -9,6 +9,7 @@ EXPORT_TO_SOONG := \ KERNEL_MAKE_FLAGS \ PATH_OVERRIDE_SOONG \ TARGET_KERNEL_CONFIG \ + TARGET_KERNEL_SOURCE \ TARGET_KERNEL_HEADERS_SOURCE \ TW_THEME \ TW_CUSTOM_THEME \ @@ -43,7 +44,7 @@ SOONG_CONFIG_twrpVarsPlugin := define addVar SOONG_CONFIG_twrpVarsPlugin += $(1) - SOONG_CONFIG_twrpVarsPlugin_$(1) := $$(subst ",\",$$($1)) + SOONG_CONFIG_twrpVarsPlugin_$(1) := $($1) endef $(foreach v,$(EXPORT_TO_SOONG),$(eval $(call addVar,$(v)))) diff --git a/tools/clean_headers.sh b/tools/clean_headers.sh new file mode 100755 index 0000000..627f646 --- /dev/null +++ b/tools/clean_headers.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -eu + +export ANDROID_BUILD_TOP="$PWD" + +./bionic/libc/kernel/tools/clean_header.py -u \ + "$1/usr/include/asm-generic/signal.h"