当前位置: 首页 > news >正文

openharmony5.0.0中kernel子系统编译构建流程概览(rk3568)

概述

在梳理openharmony对linux内核做了哪些更改时,简单梳理了下kernel部分的编译构建流程,并根据源码做了简单论证。分享出来,希望对大家有所帮助。

系统版本:openharmony5.0.0

开发板:dayu200

编译环境:ubuntu22

执行流程

在kernel\linux\build\目录可以梳理出内核代码的如下执行流程:

在这里插入图片描述

其中BUILD.gn为openharmony中gn+ninja的正常编译流程,调用过程不再跟踪。

BUILD.gn

由执行流程图可知BUILD.gn是通过如下命令进行build_kernel.sh脚本的调用的。

 action("build_kernel") {//定义一个构建任务,action参数用于定义构建过程中的具体操作script = "build_kernel.sh"//指定了用于构建内核的脚本文件为`build_kernel.sh`sources = [ kernel_source_dir ]//指定内核源码目录//kernel/linux/$linux_kernel_versiondeps = [ ":check_build" ]//在执行构建内核任务之前,必须先完成`:check_build`任务,check_build为上文定义的check_build.sh脚本product_path = "vendor/$product_company/$product_name"//产品自定义相关的目录build_type = "standard"//构建类型为标准构建outputs = [ "$root_build_dir/packages/phone/images/$kernel_image" ]//构建的最终输出文件的位置和名称args = [//列出了传递给构建脚本的参数rebase_path(kernel_build_script_dir, root_build_dir),//1.重新计算内核构建脚本目录相对于构建目录根路径的路径,kernel_build_script_dir = "//kernel/linux/build";,定位到out输出的目录rebase_path("$root_out_dir/../KERNEL_OBJ"),//2.重新计算内核对象文件目录相对于某个输出目录的路径rebase_path("$root_build_dir/packages/phone/images"),//3.重新计算内核镜像文件放置目录相对于构建目录根路径的路径build_type,//4.构建类型,这里已经定义为"standard"target_cpu,//5.目标CPU架构,构建内核时需要指定针对哪种CPU架构进行构建product_path,//6.产品路径,已在前面定义device_name,//7.设备名称,表示正在构建内核的具体设备型号linux_kernel_version,//8.Linux内核版本号,表示正在构建的内核的具体版本]}

build_kernel.sh

build_kernel.sh脚本主要进行了kernel_module_build.sh脚本的调用

pushd ${1} #进入编译目录即:
./kernel_module_build.sh ${2} ${4} ${5} ${6} ${7} ${8}
.....对编译文件的复制操作,此处省略

kernel_module_build.sh

此文件主要是将对应的变量做对应的赋值,下面将DAYU200开发板中的编译方法(./build.sh --product-name rk3568)配置选项按实际情况进行了注释

export OUT_DIR=$1 #out
export BUILD_TYPE=$2 #standard
export KERNEL_ARCH=$3 #arm64
export PRODUCT_PATH=$4 #vendor/hihope/rk3568
export DEVICE_NAME=$5 #rk3568
export KERNEL_VERSION=$6#linux-5.10
LINUX_KERNEL_OUT=${OUT_DIR}/kernel/src_tmp/${KERNEL_VERSION}
export OHOS_ROOT_PATH=$(pwd)/../../..
....
make -f kernel.mk

由上可见最终在执行make时使用-f参数指定了kernel.mk文件

kernel.mk

为了简化说明下面将DAYU200(rk3568)开发板相关的内容保留之后的makefile文件保留了,如下:

PRODUCT_NAME=$(TARGET_PRODUCT) #产品的名称,取自环境变量`TARGET_PRODUCT
OHOS_BUILD_HOME := $(realpath $(shell pwd)/../../../) #构建系统的主目录,通过`realpath`和`pwd`命令计算出绝对路径#
KERNEL_SRC_TMP_PATH := $(OUT_DIR)/kernel/${KERNEL_VERSION} #内核源代码的临时路径
KERNEL_OBJ_TMP_PATH := $(OUT_DIR)/kernel/OBJ/${KERNEL_VERSION} #内核编译对象的临时路径#如果`BUILD_TYPE`为`standard`,则设置`BOOT_IMAGE_PATH`和`KERNEL_SRC_TMP_PATH`,并导出`KERNEL_SRC_DIR`环境变量
ifeq ($(BUILD_TYPE), standard)BOOT_IMAGE_PATH = $(OHOS_BUILD_HOME)/device/board/hisilicon/hispark_taurus/uboot/prebuiltsKERNEL_SRC_TMP_PATH := $(OUT_DIR)/kernel/src_tmp/${KERNEL_VERSION}export KERNEL_SRC_DIR=out/KERNEL_OBJ/kernel/src_tmp/${KERNEL_VERSION}
endifKERNEL_SRC_PATH := $(OHOS_BUILD_HOME)/kernel/linux/${KERNEL_VERSION}#内核源代码的实际路径
KERNEL_PATCH_PATH := $(OHOS_BUILD_HOME)/kernel/linux/patches/${KERNEL_VERSION}#内核补丁文件的路径
KERNEL_CONFIG_PATH := $(OHOS_BUILD_HOME)/kernel/linux/config/${KERNEL_VERSION}#内核配置文件的路径
PREBUILTS_GCC_DIR := $(OHOS_BUILD_HOME)/prebuilts/gcc#预编译的GCC工具链路径
CLANG_HOST_TOOLCHAIN := $(OHOS_BUILD_HOME)/prebuilts/clang/ohos/linux-x86_64/llvm/bin#预编译的Clang工具链路径#
KERNEL_HOSTCC := $(CLANG_HOST_TOOLCHAIN)/clang #用于主机编译的工具链
KERNEL_PREBUILT_MAKE := make #使用的`make`工具
CLANG_CC := $(CLANG_HOST_TOOLCHAIN)/clang #交叉编译工具链的前缀,初始为空KERNEL_CROSS_COMPILE :=
......KERNEL_TARGET_TOOLCHAIN := $(PREBUILTS_GCC_DIR)/linux-x86/aarch64/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/binKERNEL_TARGET_TOOLCHAIN_PREFIX := $(KERNEL_TARGET_TOOLCHAIN)/aarch64-linux-gnu-#选择相应的交叉编译工具链和前缀
.....KERNEL_CROSS_COMPILE += CC="$(CLANG_CC)"
KERNEL_CROSS_COMPILE += CROSS_COMPILE="$(KERNEL_TARGET_TOOLCHAIN_PREFIX)"
KERNEL_MAKE := \PATH="$(BOOT_IMAGE_PATH):$$PATH" \$(KERNEL_PREBUILT_MAKE) #设置`PATH`环境变量并使用`make`命令DEVICE_PATCH_DIR := $(OHOS_BUILD_HOME)/kernel/linux/patches/${KERNEL_VERSION}/$(DEVICE_NAME)_patch
DEVICE_PATCH_FILE := $(DEVICE_PATCH_DIR)/$(DEVICE_NAME).patch
KERNEL_IMAGE_FILE := $(KERNEL_SRC_TMP_PATH)/arch/$(KERNEL_ARCH)/boot/$(KERNEL_IMAGE)#生成的内核镜像文件路径
DEFCONFIG_FILE := $(DEVICE_NAME)_$(BUILD_TYPE)_defconfig#内核配置文件名
UNIFIED_COLLECTION_PATCH_FILE := ${OHOS_BUILD_HOME}/kernel/linux/common_modules/ucollection/apply_ucollection.sh#统一集合补丁脚本路径#export KBUILD_OUTPUT=$(KERNEL_OBJ_TMP_PATH)#导出`KBUILD_OUTPUT`环境变量,指定内核编译输出路径$(KERNEL_IMAGE_FILE):$(hide) echo "build kernel..."
......$(hide) rm -rf $(KERNEL_SRC_TMP_PATH);mkdir -p $(KERNEL_SRC_TMP_PATH);cp -arfL $(KERNEL_SRC_PATH)/* $(KERNEL_SRC_TMP_PATH)/ # 复制源代码$(hide) $(OHOS_BUILD_HOME)/drivers/hdf_core/adapter/khdf/linux/patch_hdf.sh $(OHOS_BUILD_HOME) $(KERNEL_SRC_TMP_PATH) $(KERNEL_PATCH_PATH) $(DEVICE_NAME) # 调用`patch_hdf.sh`脚本,应用设备驱动框架相关的补丁
......$(hide) cd $(KERNEL_SRC_TMP_PATH) && test -f $(DEVICE_PATCH_FILE) && patch -p1 < $(DEVICE_PATCH_FILE) || true #根据产品路径或设备名称,应用特定的补丁文件ifeq ($(UNIFIED_COLLECTION_PATCH_FILE), $(wildcard $(UNIFIED_COLLECTION_PATCH_FILE)))#如果存在获取进程cpu维测数据的脚本(提升获取CPU使用率的效率的服务),则执行该脚本,此脚本通过创建符号链接,可以方便地将位于不同目录的源码文件链接到内核构建目录中,避免了复制文件的过程$(hide) $(UNIFIED_COLLECTION_PATCH_FILE) $(OHOS_BUILD_HOME) $(KERNEL_SRC_TMP_PATH) $(DEVICE_NAME) $(KERNEL_VERSION)
endif#复制内核配置文件到源代码临时路径。使用`make`命令进行清理、配置、模块准备和编译。$(hide) cp -rf $(KERNEL_CONFIG_PATH)/. $(KERNEL_SRC_TMP_PATH)/$(hide) $(KERNEL_MAKE) -C $(KERNEL_SRC_TMP_PATH) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) distclean #清理$(hide) $(KERNEL_MAKE) -C $(KERNEL_SRC_TMP_PATH) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(DEFCONFIG_FILE) #配置
ifeq ($(KERNEL_VERSION), linux-5.10)$(hide) $(KERNEL_MAKE) -C $(KERNEL_SRC_TMP_PATH) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) modules_prepare #模块准备
endif$(hide) $(KERNEL_MAKE) -C $(KERNEL_SRC_TMP_PATH) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) -j64 $(KERNEL_IMAGE)  #编译
....
#定义一个伪目标`build-kernel`,依赖于`$(KERNEL_IMAGE_FILE)`。
#当运行`make build-kernel`时,会触发内核镜像的构建。
.PHONY: build-kernel
build-kernel: $(KERNEL_IMAGE_FILE)

📑$(hide) 通常用于 make 文件中的命令前缀。它会将命令的输出重定向到 /dev/null,从而隐藏命令的输出。调试时可以在调用 make 时使用 -s 选项来禁用所有命令的输出隐藏。

通过对以上的分析,可总结出我们比较关注的信息如下:

合入HDF补丁(patch_hdf.sh)

在第47行中可见HDF的补丁合入方法,合入不同内核版本对应的HDF内核补丁:

$(hide) $(OHOS_BUILD_HOME)/drivers/hdf_core/adapter/khdf/linux/patch_hdf.sh $(OHOS_BUILD_HOME) $(KERNEL_SRC_TMP_PATH) $(KERNEL_PATCH_PATH) $(DEVICE_NAME)

patch_hdf.sh脚本四个参数含义为:第一个入参为工程根目录路径,第二入参为内核目录路径,第三个入参为内核版本路径,第四个参数是当前设备名

此文件主要执行将hdf相关的补丁(kernel\linux\pathces\linux-5.10\rk3568_patch\hdf.patch)打入到系统中,具体的操作可以直接参看源码中的脚本文件drivers\hdf_core\adapter\khdf\linux\patch_hdf.sh

特定补丁文件

/kernel/linux/patches/${KERNEL_VERSION}/$(DEVICE_NAME)_patch目录中合入特定补丁$(DEVICE_NAME).patch,

$(hide) cd $(KERNEL_SRC_TMP_PATH) && test -f $(DEVICE_PATCH_FILE) && patch -p1 < $(DEVICE_PATCH_FILE) || true 
  • $(hide) :这是 make 工具的一个特性,用于隐藏命令的输出。它会将命令的输出重定向到 /dev/null,使得构建日志更加简洁,只显示关键信息。
  • cd $(KERNEL_SRC_TMP_PATH) :切换到内核源码所在的临时目录 $(KERNEL_SRC_TMP_PATH)
  • test -f $(DEVICE_PATCH_FILE) :检查设备补丁文件 $(DEVICE_PATCH_FILE) 是否存在。如果文件存在,命令返回真(退出码为 0);如果文件不存在,命令返回假(退出码为非 0)。
  • patch -p1 < $(DEVICE_PATCH_FILE) :应用补丁文件 $(DEVICE_PATCH_FILE)-p1 参数表示剥离补丁路径中的一层目录,即假设补丁是相对于内核源码根目录的一级目录创建的。
  • || true :如果前面的命令(即 test -fpatch 的组合)执行失败(返回非 0 退出码),则执行 true 命令,true 命令总是返回真(退出码为 0)。这可以避免构建过程因为补丁文件不存在或应用补丁失败而中断。

在我拿到的这份源码中没有rk3568.patch这个补丁,所以true很重要,表示此特定补丁为可选项

内核编译配置

在58行中可见如下脚本

 $(KERNEL_MAKE) -C $(KERNEL_SRC_TMP_PATH) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(DEFCONFIG_FILE)

经过上下文的分析可将此脚本解释为

make -C /out/kernel/src_tmp/linux-5.10 ARCH=arm64 CC=/prebuilts/clang/ohos/linux-x86_64/llvm/bin/clang CROSS_COMPILE=/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- rk3568_standard_defconfig
  • -C /out/kernel/src_tmp/linux-5.10 :指定了内核源码所在的目录,make 会进入该目录下进行编译操作,而不是在当前目录。

在这里插入图片描述

  • ARCH=arm64 :定义了目标架构为 ARM64,这意味着要编译出适用于 ARM64 架构设备的内核。
  • CC=/prebuilts/clang/ohos/linux-x86_64/llvm/bin/clang :指定了 C 编译器的路径,这里使用的是 Clang 编译器,它位于 /prebuilts/clang/ohos/linux-x86_64/llvm/bin/ 目录下。

在这里插入图片描述

  • CROSS_COMPILE=/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- :指定了交叉编译前缀,用于构建目标架构(ARM64)上的可执行文件。这个前缀指向了交叉编译工具链的目录,aarch64-linux-gnu- 表示该工具链是针对 aarch64 架构的 Linux 系统的。

在这里插入图片描述

  • rk3568_standard_defconfig :指定使用的内核配置文件。这个文件定义了内核的各种配置选项,如要包含的驱动、功能模块等。它会使内核编译过程按照该配置文件中的设置来进行,生成符合特定硬件平台(这里是 rk3568)需求的内核配置。

通过对上文的分析发现没有对kernel进行打补丁,后经搜索发现在device\board\hihope\rk3568\kernel\目录中包含对kernel的操作,如下

#device\board\hihope\rk3568\kernel\build_kernel.sh
patch -p1 < ${KERNEL_PATCH}#KERNEL_PATCH即为/kernel/linux/patches/linux-5.10/rk3568_patch/kernel.patch

此目录也包含厂家对系统其他的特殊处理,整体流程与上文分析的类似,此处不再详细说明。

相关文章:

  • 可视化大屏工具对比:GoView、DataRoom、积木JimuBI、Metabase、DataEase、Apache Superset 与 Grafana
  • ArcGIS Pro 3.4 二次开发 - 地图创作 1
  • ArcGIS Pro 3.4 二次开发 - 地图创作 2
  • JavaScript async/await指南
  • 解决Vditor加载Markdown网页很慢的问题(Vite+JS+Vditor)
  • 【请关注】MySQL 中常见的加锁方式及各类锁常见问题及对应的解决方法
  • ES101系列09 | 运维、监控与性能优化
  • 笔记本/台式C盘扩容:删除、压缩、跨分区与重分配—「小白教程」
  • 大模型的外围关键技术
  • 动态规划-1143.最长公共子序列-力扣(LeetCode)
  • OpenCV C++ 学习笔记(五):颜色空间转换、数值类型转换、图像混合、图像缩放
  • Flink 重启后事件被重复消费的原因与解决方案
  • 极智项目 | 基于PyQT+Whisper实现的语音识别软件设计
  • Rust 学习笔记:使用自定义命令扩展 Cargo
  • Matlab2018a---安装教程
  • Bash shell四则运算
  • python,shell,linux,bash概念的不同和对比联系
  • isp调试 blend模式指什么
  • 深圳南柯电子|储能EMC整改:如何节省70%整改费用的实战方法
  • 对比ODR直接赋值的非原子操作和BSRR原子操作
  • 拱墅网站建设/百度首页 百度
  • 微信官网网站/友情链接免费发布平台
  • 西安 美院 网站建设/项目推广渠道有哪些
  • 鲅鱼圈网站建设/原创代写文章平台
  • 安卓移动网站开发详解/石家庄网站建设公司
  • 好看的网站链接/长沙优化网站推广