当前位置: 首页 > 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

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

http://www.xdnf.cn/news/780877.html

相关文章:

  • 更新已打包好的 Spring Boot JAR 文件中的 class 文件
  • Git 常用命令 - 服务器用
  • Redis线程模型
  • C#面试问题81-100
  • Redisson学习专栏(五):源码阅读及Redisson的Netty通信层设计
  • Python中os模块详解
  • 数组的常用方法有哪些?
  • 解锁Java多级缓存:性能飞升的秘密武器
  • BugKu Web渗透之game1
  • 2025 Java面试大全技术文章大纲
  • 链表题解——反转链表【LeetCode】
  • C++ stl容器之vector用法
  • 经典SQL查询问题的练习第四天
  • Laravel模型状态:深入理解Eloquent的隐秘力量
  • windows安装和部署docker
  • Dockerfile 使用多阶段构建(build 阶段 → release 阶段)前端配置
  • 迅为RK3588开发板RKLLM-Toolkit 环境搭建安装 Miniconda
  • Servlet 快速入门
  • Dify知识库下载小程序
  • OpenCV CUDA模块特征检测------创建Harris角点检测器的GPU实现接口cv::cuda::createHarrisCorner
  • 【Ragflow】25.Ragflow-plus开发日志:excel文件解析新思路/公式解析适配
  • supervisor 常见问题大全
  • Kotlin List 操作全面指南
  • 如何生成和制作PDF文件
  • MybatisPlus--核心功能--service接口
  • [Python] python信号处理绘制信号频谱
  • 《CF912E Prime Gift》
  • 推荐一款PDF压缩的工具
  • Mac版本Android Studio配置LeetCode插件
  • 机器学习——聚类算法