kernel.mk: Allow building external kernel modules

Here, we introduce the TARGET_EXTERNAL_KERNEL_MODULES variable
for the list of external modules.

Change-Id: I1f8b7a48e66bb0c9efbc396692e5a7159f0b835c
diff --git a/build/tasks/kernel.mk b/build/tasks/kernel.mk
index 72c32f9..b2f5b49 100644
--- a/build/tasks/kernel.mk
+++ b/build/tasks/kernel.mk
@@ -275,6 +275,14 @@
 $(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)
 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) $(KERNEL_LD) $(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)
@@ -411,6 +419,14 @@
 			$(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 make-external-module-target,$(p),$$rpath,); \
+					$(call make-external-module-target,$(p),$$rpath,INSTALL_MOD_PATH=$(MODULES_INTERMEDIATES) INSTALL_MOD_STRIP=1 KERNEL_UAPI_HEADERS_DIR=$(KERNEL_OUT) modules_install)); \
+			) \
 			kernel_release=$$(cat $(KERNEL_RELEASE)) \
 			kernel_modules_dir=$(MODULES_INTERMEDIATES)/lib/modules/$$kernel_release \
 			$(foreach s, $(TARGET_MODULE_ALIASES),\
diff --git a/config/BoardConfigKernel.mk b/config/BoardConfigKernel.mk
index faaa65b..042fe39 100644
--- a/config/BoardConfigKernel.mk
+++ b/config/BoardConfigKernel.mk
@@ -38,6 +38,11 @@
 #   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
 #                                          toolchain specified in BoardConfig.mk
@@ -158,6 +163,10 @@
 # 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