2 常见任务

本章介绍 Yocto Project Linux 内核开发常见任务,包括准备主机和层、修改 配方、打补丁、配置内核、迭代开发、使用自己的源码以及集成树外模块。

备注

本章示例适用于 Yocto Project 2.4 及以后版本。

2 准备内核开发构建主机

开始前应确保主机已准备好使用 Yocto Project,设置方法见 “准备使用 Yocto Project”。

备注

请检出适当开发分支,或从具体标签创建本地分支,以获得所需项目版本。

推荐使用 devtool, 而非传统内核流程。下文介绍两者。

2 准备使用 devtool 开发

以下步骤得到一个干净内核镜像,为 “使用 devtool 修补内核” 做准备:

  1. 初始化环境: 按 准备使用 Yocto Project 准备可运行 devtool 的 Shell。

  2. 准备 local.conf: 默认 MACHINE 为 qemux86-64,适合 64 位 QEMU。 其他目标需修改 Build Directory 中的 build/conf/local.conf,本例目录为 bitbake-builds/build。

    开发内核还需将 kernel-modules 加入 MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS。 本例选择 qemux86,追加如下:

    MACHINE = "qemux86"
    MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS += "kernel-modules"
    
  3. 创建补丁层: 用 create-layer 创建保存内核补丁的层:

    $ cd bitbake-builds/build
    $ bitbake-layers create-layer ../layers/meta-mylayer
    NOTE: Starting bitbake server...
    Add your new layer with 'bitbake-layers add-layer ../layers/meta-mylayer'
    $
    

    备注

    普通层和 BSP 层背景见 “理解和创建层” 及 “BSP 层”。快速建层方法见 “创建自己的层”。

  4. 将层告知构建环境: 按创建提示,将其加入配置文件的 BBLAYERS:

    $ cd bitbake-builds/build
    $ bitbake-layers add-layer ../../meta-mylayer
    NOTE: Starting bitbake server...
    $
    
  5. 构建干净镜像: 最后用 BitBake 构建初始镜像:

    $ bitbake core-image-minimal
    Parsing recipes: 100% |##########################################| Time: 0:00:05
    Parsing of 830 .bb files complete (0 cached, 830 parsed). 1299 targets, 47 skipped, 0 masked, 0 errors.
    WARNING: No packages to add, building image core-image-minimal unmodified
    Loading cache: 100% |############################################| Time: 0:00:00
    Loaded 1299 entries from dependency cache.
    NOTE: Resolving any missing task queue dependencies
    Initializing tasks: 100% |#######################################| Time: 0:00:07
    Checking sstate mirror object availability: 100% |###############| Time: 0:00:00
    NOTE: Executing SetScene Tasks
    NOTE: Executing RunQueue Tasks
    NOTE: Tasks Summary: Attempted 2866 tasks of which 2604 didn't need to be rerun and all succeeded.
    

    若面向真实硬件,可将镜像写入例如 /dev/sdd 的 U 盘启动。Minnowboard 示例见 TipsAndTricks/KernelDevelopmentWithEsdk。

现在可以开始修改,后续见 “使用 devtool 修补内核”。

2 准备传统内核开发

传统流程准备步骤大致相同,但还需创建本地内核源码副本供编辑。以下完成后, 即可按 “使用传统内核开发流程修补内核” 修改源码。

  1. 初始化环境: 按 准备使用 Yocto Project 操作。

  2. 准备 local.conf: 默认 MACHINE 为 qemux86-64,适合 64 位 QEMU;否则 修改构建目录的 build/conf/local.conf,本例为 bitbake-builds/build。

    还需让 MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS 包含内核模块。 本例使用 qemux86,追加:

    MACHINE = "qemux86"
    MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS += "kernel-modules"
    
  3. 创建补丁层: 创建保存补丁的层:

    $ cd bitbake-builds/build
    $ bitbake-layers create-layer ../../meta-mylayer
    NOTE: Starting bitbake server...
    Add your new layer with 'bitbake-layers add-layer ../../meta-mylayer'
    

    备注

    层背景见 “理解和创建层” 和 “BSP 层”;创建方法见 “创建自己的层”。

  4. 加入构建环境: 将层加入 build/conf/bblayers.conf 的 BBLAYERS:

    $ cd bitbake-builds/build
    $ bitbake-layers add-layer ../../meta-mylayer
    NOTE: Starting bitbake server ...
    $
    
  5. 克隆内核 Git 仓库: 受支持仓库位于 https://git.yoctoproject.org/ 的 "Yocto Linux Kernel" 分组。

    建议放在 Source Directory 外,并切换到 standard/base。 以下克隆 linux-yocto-4.12:

    $ cd ~
    $ git clone https://git.yoctoproject.org/linux-yocto-4.12 --branch standard/base
    Cloning into 'linux-yocto-4.12'...
    remote: Counting objects: 6097195, done.
    remote: Compressing objects: 100% (901026/901026), done.
    remote: Total 6097195 (delta 5152604), reused 6096847 (delta 5152256)
    Receiving objects: 100% (6097195/6097195), 1.24 GiB | 7.81 MiB/s, done.
    Resolving deltas: 100% (5152604/5152604), done. Checking connectivity... done.
    Checking out files: 100% (59846/59846), done.
    

    备注

    linux-yocto-4.12 适用于 Yocto Project 2.4 及以后,不适用于更早版本。

  6. 克隆内核缓存仓库: 同样建议放在源码目录外,本例检出 yocto-4.12 分支:

    $ cd ~
    $ git clone https://git.yoctoproject.org/yocto-kernel-cache --branch yocto-4.12
    Cloning into 'yocto-kernel-cache'...
    remote: Counting objects: 22639, done.
    remote: Compressing objects: 100% (9761/9761), done.
    remote: Total 22639 (delta 12400), reused 22586 (delta 12347)
    Receiving objects: 100% (22639/22639), 22.34 MiB | 6.27 MiB/s, done.
    Resolving deltas: 100% (12400/12400), done.
    Checking connectivity... done.
    

准备完成,后续见 “使用传统内核开发流程修补内核”。

2 创建和准备层

修改内核配方时,建议在自己的层中工作,保存 BitBake 追加文件、 自定义配方和补丁。背景见 “理解和创建层”。

备注

bitbake-layers create-layer 可简化创建,见 “创建自己的层”。

为帮助理解,下面不用工具,手动在主目录创建 mylayer:

  1. 创建结构: 执行:

    $ mkdir -p meta-mylayer/conf meta-mylayer/recipes-kernel/linux/linux-yocto
    

    conf 保存配置,recipes-kernel 保存追加文件及补丁。

  2. 创建层配置: 在 meta-mylayer/conf 创建 layer.conf:

    # We have a conf and classes directory, add to BBPATH
    BBPATH .= ":${LAYERDIR}"
    
    # We have recipes-* directories, add to BBFILES
    BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
                ${LAYERDIR}/recipes-*/*/*.bbappend"
    
    BBFILE_COLLECTIONS += "mylayer"
    BBFILE_PATTERN_mylayer = "^${LAYERDIR}/"
    BBFILE_PRIORITY_mylayer = "5"
    

    注意最后三条语句中的 mylayer。

  3. 创建内核追加文件: 在 meta-mylayer/recipes-kernel/linux 创建 linux-yocto_4.12.bbappend,本例使用 linux-yocto-4.12:

    FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
    
    SRC_URI += "file://patch-file-one.patch"
    SRC_URI += "file://patch-file-two.patch"
    SRC_URI += "file://patch-file-three.patch"
    

    FILESEXTRAPATHS 和 SRC_URI 使系统找到补丁。追加文件详见 “通过自己的层追加其他层元数据”。

2 修改已有配方

通常可定制已有 linux-yocto 配方。每个发行版提供几种选择,位于 OpenEmbedded-Core (OE-Core) 的 meta/recipes-kernel/linux。

修改包括:

先准备最小自定义层,见 “创建和准备层”。

2 创建追加文件

在自己的层中创建,与原配方对应命名。例如修改 linux-yocto_6.1.bb 时:

your-layer/recipes-kernel/linux/linux-yocto_6.1.bbappend

首先通过前置 FILESEXTRAPATHS 扩展 FILESPATH:

FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"

本例 ${THISDIR}/${PN} 展开为当前目录 下的 linux-yocto。新增文件应放在:

your-layer/recipes-kernel/linux/linux-yocto/

备注

新机器 BSP 开发还应参阅 Yocto Project 板级支持包(BSP)手册。

例如,meta-yocto-bsp 使用的追加文件:

meta-yocto-bsp/recipes-kernel/linux/linux-yocto_6.1.bbappend

其内容如下,示例提交 ID 可能与上游实际内容不同:

KBRANCH:genericx86  = "v6.1/standard/base"
KBRANCH:genericx86-64  = "v6.1/standard/base"
KBRANCH:beaglebone-yocto = "v6.1/standard/beaglebone"

KMACHINE:genericx86 ?= "common-pc"
KMACHINE:genericx86-64 ?= "common-pc-64"
KMACHINE:beaglebone-yocto ?= "beaglebone"

SRCREV_machine:genericx86 ?= "6ec439b4b456ce929c4c07fe457b5d6a4b468e86"
SRCREV_machine:genericx86-64 ?= "6ec439b4b456ce929c4c07fe457b5d6a4b468e86"
SRCREV_machine:beaglebone-yocto ?= "423e1996694b61fbfc8ec3bf062fc6461d64fde1"

COMPATIBLE_MACHINE:genericx86 = "genericx86"
COMPATIBLE_MACHINE:genericx86-64 = "genericx86-64"
COMPATIBLE_MACHINE:beaglebone-yocto = "beaglebone-yocto"

LINUX_VERSION:genericx86 = "6.1.30"
LINUX_VERSION:genericx86-64 = "6.1.30"
LINUX_VERSION:beaglebone-yocto = "6.1.20"

此文件支持多个随项目发布的 BSP,用 COMPATIBLE_MACHINE 定义机器, 以 KMACHINE 将构建系统机器名映射到内核机器名,并可用 KBRANCH 确保使用适当分支。

虽然本例没用,也可通过 KERNEL_FEATURES 启用内核专用功能。具体提交 指定构建 BSP 所需的精确内核。

该示例缺少开发 BSP 通常需要的内核配置。可以把完整配置或一组片段放在与 追加文件同级、名称与内核主配方相同的目录中,再通过 SRC_URI 引用。

例如,linux-yocto 目录中的 network_configs.cfg 可如此加入:

SRC_URI += "file://network_configs.cfg"

也可将以太网、图形等分组到各自文件:

SRC_URI += "file://myconfig.cfg \
            file://eth.cfg \
            file://gfx.cfg"

FILESEXTRAPATHS 用于扩展处理配方时查找文件和补丁的位置。

备注

还有其他组织方式。例如使用本地内核仓库时,可以检出 meta 分支,修改后 推送到本地裸仓库,直接为 BSP 增加配置。BSP 若最终加入项目,配置通常也 会进入该位置。

一般由维护者把 SRC_URI 中的配置移到 meta 分支。这样既减轻 BSP 开发者 负担,也可利用维护者的全局视角,将多个 BSP 的公共配置提升为公共功能。

2 应用补丁

单个或小系列补丁的处理与其他配方相同:复制到追加文件 FILESEXTRAPATHS 指定位置,再列入 SRC_URI。例如三补丁系列:

SRC_URI += "file://0001-first-change.patch"
SRC_URI += "file://0002-second-change.patch"
SRC_URI += "file://0003-third-change.patch"

下次 BitBake 构建时检测配方变化,先获取并应用补丁,再构建内核。

详细示例见 “使用 devtool 修补内核” 和 “使用传统内核开发流程修补内核”。

2 修改配置

可通过 defconfig 及 SRC_URI 中的配置片段,对最终 .config 作整体或增量修改。

已有完整可用 .config 时,复制到层的 recipes-kernel/linux 下对应 ${PN} 目录,命名为 defconfig,再在追加文件添加:

FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://defconfig"

SRC_URI 指定文件,FILESEXTRAPATHS 扩展搜索目录。

也可使用 do_savedefconfig 生成、仅含非默认值的 defconfig, 但需额外设置 KCONFIG_MODE:

KCONFIG_MODE = "alldefconfig"

备注

系统先应用 defconfig,再应用所有配置片段,最终结果是两者组合,片段 覆盖在基础配置之上。

一般更推荐只描述所需增量。例如,为基本串口控制台创建 8250.cfg,内容如下, 不要缩进:

CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y

追加文件中引入并扩展搜索路径:

FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://8250.cfg"

下次构建会获取并应用新配置。详细示例见 “配置内核”。

2 使用树内 defconfig 文件

有时希望使用内核源码树中该机器的 defconfig,同时保留片段支持。默认系统从 元数据层查找树外文件,并如下配置:

SRC_URI += "file://defconfig"

若不想在层中维护副本,可以使用树内默认配置,仍通过追加文件的 SRC_URI 添加片段。指定方式为:

KBUILD_DEFCONFIG:<machine> ?= "defconfig_file"

以下对基于 Broadcom 2708/2709 的 Raspberry Pi 2 使用机器覆盖设置 KBUILD_DEFCONFIG:

KBUILD_DEFCONFIG:raspberrypi2 ?= "bcm2709_defconfig"

若同时存在树外 defconfig 设置,KBUILD_DEFCONFIG 优先。详情见该变量文档。

2 使用 devtool 修补内核

以下流程展示 devtool 内核修补。

备注

先完成 “准备使用 devtool 开发”。

内核修补可涉及配置、支持硬件的配方,或源码本身。本例继续前述准备流程, 在 calibrate.c 添加 printk,让 QEMU 启动时输出新消息。

  1. 检出源码: 先让 devtool 在工作区检出内核。

    备注

    参阅 “准备使用 devtool 开发”。

    运行:

    $ devtool modify linux-yocto
    
  2. 编辑源码:

    1. 切换目录: 上一步输出源码位置,例如 build/workspace/sources/linux-yocto。编辑前进入该位置:

      $ cd build/workspace/sources/linux-yocto
      
    2. 修改文件: 将 init/calibrate.c 改为:

      void calibrate_delay(void)
      {
          unsigned long lpj;
          static bool printed;
          int this_cpu = smp_processor_id();
      
          printk("*************************************\n");
          printk("*                                   *\n");
          printk("*        HELLO YOCTO KERNEL         *\n");
          printk("*                                   *\n");
          printk("*************************************\n");
      
          if (per_cpu(cpu_loops_per_jiffy, this_cpu)) {
                .
                .
                .
      
  3. 构建更新后的内核: 运行:

    $ devtool build linux-yocto
    
  4. 生成包含新内核的镜像: 运行:

    $ cd ~
    $ devtool build-image core-image-minimal
    

    备注

    原镜像为 Wic 时也可采用替代方法,见 TipsAndTricks/KernelDevelopmentWithEsdk。

  5. 测试新镜像: 用 QEMU 验证。

    1. 启动: 执行:

      $ runqemu qemux86
      
    2. 检查: 以 root 空密码登录,查看启动输出:

      # dmesg | less
      

      向下滚动应看到 printk 新消息。

  6. 暂存并提交: 回到修改 calibrate.c 的目录:

    $ cd build/workspace/sources/linux-yocto
    $ git status
    $ git add init/calibrate.c
    $ git commit -m "calibrate: Add printk example"
    
  7. 导出补丁并创建追加文件: 使用先前的 meta-mylayer:

    $ devtool finish linux-yocto ~/meta-mylayer
    

    备注

    建层方法见 “准备使用 devtool 开发” 第三步。

    完成后,补丁和追加文件位于 ~/meta-mylayer/recipes-kernel/linux。

  8. 构建包含修改的镜像: 在已初始化的终端进入构建目录并运行:

    $ cd bitbake-builds/build
    $ bitbake core-image-minimal
    

2 使用传统内核开发流程修补内核

以下不使用 devtool,作为 “使用 devtool 修补内核” 的另一方案。

备注

先完成 “准备传统内核开发”。

修补可以修改配置、配方或源码。本例同样在 calibrate.c 添加 printk,以 QEMU 启动输出验证,延续传统开发准备流程。

  1. 编辑源码: 假定已按前文克隆本地仓库。

    1. 切换目录: 在修改 calibrate.c 前进入内核仓库:

      $ cd ~/linux-yocto-4.12/init
      
    2. 编辑文件: 修改为:

      void calibrate_delay(void)
      {
          unsigned long lpj;
          static bool printed;
          int this_cpu = smp_processor_id();
      
          printk("*************************************\n");
          printk("*                                   *\n");
          printk("*        HELLO YOCTO KERNEL         *\n");
          printk("*                                   *\n");
          printk("*************************************\n");
      
          if (per_cpu(cpu_loops_per_jiffy, this_cpu)) {
                .
                .
                .
      
  2. 暂存并提交: 使用 Git:

    $ git add calibrate.c
    $ git commit -m "calibrate.c - Added some printk statements"
    

    未提交的修改不会被构建系统获取。

  3. 更新 local.conf 指向源码: 除 kernel-modules 和 qemux86 外,还需通过 SRC_URI 和 SRCREV 指向更新后的仓库:

    $ cd bitbake-builds/build/conf
    

    继续添加:

    SRC_URI:pn-linux-yocto = "git:///path-to/linux-yocto-4.12;protocol=file;name=machine;branch=standard/base; \
                              git:///path-to/yocto-kernel-cache;protocol=file;type=kmeta;name=meta;branch=yocto-4.12;destsuffix=${KMETA}"
    SRCREV_meta:qemux86 = "${AUTOREV}"
    SRCREV_machine:qemux86 = "${AUTOREV}"
    

    备注

    将 path-to 替换为本地仓库路径,确认分支和机器正确。本例分别为 standard/base 和 qemux86。

  4. 构建镜像: 修改已提交且配置已指向源码后:

    $ cd bitbake-builds/build
    $ bitbake core-image-minimal
    
  5. 启动镜像: QEMU 中用 root 空密码登录:

    $ cd bitbake-builds/build
    $ runqemu qemux86
    
  6. 检查变化: 启动时消息可能快速滚过,可用以下命令查看:

    # dmesg | less
    

    应能看到 printk 输出。

  7. 生成补丁: 验证正确后,在内核仓库生成 patch:

    $ cd ~/linux-yocto-4.12/init
    $ git format-patch -1
    0001-calibrate.c-Added-some-printk-statements.patch
    
  8. 移动到层: 为后续构建使用,将补丁移到主目录下先前创建的 meta-mylayer。 yocto-create 当时未生成补丁目录结构,先添加:

    $ cd ~/meta-mylayer
    $ mkdir -p recipes-kernel recipes-kernel/linux/linux-yocto
    

    再移动文件:

    $ mv ~/linux-yocto-4.12/init/0001-calibrate.c-Added-some-printk-statements.patch ~/meta-mylayer/recipes-kernel/linux/linux-yocto
    
  9. 创建追加文件: 在层的 recipes-kernel/linux 创建 linux-yocto_4.12.bbappend,内容如下:

    FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
    SRC_URI += "file://0001-calibrate.c-Added-some-printk-statements.patch"
    

    FILESEXTRAPATHS 和 SRC_URI 使构建系统找到补丁。更多信息见 “创建追加文件”、 “应用补丁” 和 “通过自己的层追加其他层元数据”。

    备注

    要再次构建 core-image-minimal 并检查补丁,可通过以下序列消除 bitbake-builds/build/tmp/work/... 临时源码及之前构建的残留影响:

    $ cd bitbake-builds/build
    $ bitbake -c cleanall linux-yocto
    $ bitbake core-image-minimal -c cleanall
    $ bitbake core-image-minimal
    $ runqemu qemux86
    

2 配置内核

内核配置要确保 .config 包含镜像所需的全部正确设置。可使用 menuconfig 和 配置片段,也可将已知配置保存为 defconfig。本节介绍交互配置、片段及配置 精简,另见 “修改配置”。

2 使用 menuconfig

最简单的方法是使用交互工具 menuconfig,一般介绍见 https://en.wikipedia.org/wiki/Menuconfig。

在项目环境中使用前,需要:

  • 通过 oe-init-build-env 初始化 BitBake 环境。

  • 确认 Source Directory 中的构建配置状态。

  • 在主机安装以下两个包:

    libncurses5-dev
    libtinfo-dev
    

以下初始化环境、运行 do_kernel_configme 并启动 menuconfig, 假定源码顶层目录为 work:

$ cd work
$ source layers/openembedded-core/oe-init-build-env
$ bitbake linux-yocto -c kernel_configme -f
$ bitbake linux-yocto -c menuconfig

界面中可以检查和调整所有参数,完成后退出并保存,即更新 .config。

备注

完整 .config 可用作 defconfig,见 “修改配置”、 “使用树内 defconfig 文件” 和 “创建 defconfig 文件”。

以 linux-yocto-4.12 的 CONFIG_SMP 为例。

备注

系统通过元数据将其识别为 linux-yocto,例如 PREFERRED_VERSION_linux-yocto ?= "4.12%"。

在 "Processor Type and Features" 中,用方向键选择 "Symmetric Multi-Processing Support",按 N 清除星号,退出并保存即可禁用 CONFIG_SMP。

保存后更新的 .config 用于实际内核构建,位于构建目录 tmp/work 中对应内核 的区域。例如 linux-yocto-4.12、x86 QEMU 的路径为:

bitbake-builds/build/tmp/work/qemux86-poky-linux/linux-yocto/4.12.12+gitAUTOINC+eda4d18...
...967-r0/linux-qemux86-standard-build/.config

备注

示例为便于阅读人为折行并省略部分字符,实际路径也随内核而异。

其中可看到禁用 SMP 的设置:

# CONFIG_SMP is not set

一种提取配置变化的方法是:运行 menuconfig 前复制 .config 为另一个文件, 修改并保存后比较差异,再将差异整理为片段,永久保存到层中。

备注

必须复制而非只重命名,构建系统仍需要原 .config。

2 创建 defconfig 文件

Yocto Project 中的 defconfig 通常是从构建复制的 .config,或从内核树移到 配方空间的 defconfig,保存已知配置,供系统生成最终 .config。

备注

项目默认不附带 defconfig 或 .config,最终配置由构建系统生成。

从完整可用 .config 开始,复制到层 recipes-kernel/linux 下对应 ${PN} 目录并命名 defconfig,例如 ~/meta-mylayer/recipes-kernel/linux/linux-yocto/defconfig。追加文件中设置:

FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://defconfig"

SRC_URI 引用文件,FILESEXTRAPATHS 将目录加入 FILESPATH。

备注

系统先应用 defconfig,再将所有片段叠加其上,最终配置是两者组合。

更多信息见 “修改配置”。

2 创建配置片段

配置片段是放在系统可找到位置的一组内核选项,语法与构建目录 .config 相同。 它在 defconfig 之后应用,可以覆盖基础配置。

备注

.config 位置示例见 “使用 menuconfig”。

创建很简单,例如用 Shell 生成 my_changes.cfg,启用多处理器支持并禁用 FPGA 配置框架:

$ echo "CONFIG_SMP=y" >> my_changes.cfg
$ echo "# CONFIG_FPGA is not set" >> my_changes.cfg

备注

所有片段必须使用 .cfg 扩展名,构建系统才会识别。

也可比较原配置与 menuconfig 新配置:

  1. 完成内核配置任务: 至少构建至配置阶段:

    $ bitbake linux-yocto -c kernel_configme -f
    

    这样从已知状态生成 .config。构建状态可能不明确,因此最好在 menuconfig 前运行该任务。

  2. 启动 menuconfig: 执行:

    $ bitbake linux-yocto -c menuconfig
    
  3. 生成片段: diffconfig 将 fragment.cfg 放入 ${WORKDIR}:

    $ bitbake linux-yocto -c diffconfig
    

生成文件是一组 CONFIG_ 赋值,使用方法见 “修改配置”。

备注

也可用于 BSP,见 “BSP 描述”。

片段应放在层内 SRC_URI 指向的可搜索位置,构建系统会将其加入内核配置。 例如,把 myconfig.cfg 放在追加文件同级的 linux-yocto 目录,再添加:

FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://myconfig.cfg"

相关配置可拆为多文件,例如以太网和图形:

SRC_URI += "file://myconfig.cfg \
            file://eth.cfg \
            file://gfx.cfg"

2 验证配置

运行 do_kernel_configcheck:

$ bitbake linux-yocto -c kernel_configcheck -f

请求选项未进入最终 .config,或硬件片段覆盖策略配置时会警告。运行前必须已有 .config,创建方式见 “使用 menuconfig”。

示例输出:

Loading cache: 100% |########################################################| Time: 0:00:00
Loaded 1275 entries from dependency cache.
NOTE: Resolving any missing task queue dependencies

Build Configuration:
    .
    .
    .

NOTE: Executing SetScene Tasks
NOTE: Executing RunQueue Tasks
WARNING: linux-yocto-4.12.12+gitAUTOINC+eda4d18ce4_16de014967-r0 do_kernel_configcheck:
    [kernel config]: specified values did not make it into the kernel's final configuration:

---------- CONFIG_X86_TSC -----------------
Config: CONFIG_X86_TSC
From: /home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/bsp/common-pc/common-pc-cpu.cfg
Requested value:  CONFIG_X86_TSC=y
Actual value:


---------- CONFIG_X86_BIGSMP -----------------
Config: CONFIG_X86_BIGSMP
From: /home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/cfg/smp.cfg
      /home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/defconfig
Requested value:  # CONFIG_X86_BIGSMP is not set
Actual value:


---------- CONFIG_NR_CPUS -----------------
Config: CONFIG_NR_CPUS
From: /home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/cfg/smp.cfg
      /home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/bsp/common-pc/common-pc.cfg
      /home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/defconfig
Requested value:  CONFIG_NR_CPUS=8
Actual value:     CONFIG_NR_CPUS=1


---------- CONFIG_SCHED_SMT -----------------
Config: CONFIG_SCHED_SMT
From: /home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/cfg/smp.cfg
      /home/scottrif/bitbake-builds/build/tmp/work-shared/qemux86/kernel-source/.kernel-meta/configs/standard/defconfig
Requested value:  CONFIG_SCHED_SMT=y
Actual value:



NOTE: Tasks Summary: Attempted 288 tasks of which 285 didn't need to be rerun and all succeeded.

Summary: There were 3 WARNING messages shown.

备注

示例输出为便于阅读人为折行。

日志描述问题及相关配置位置。根据日志调整,再反复运行 do_kernel_configme 和 do_kernel_configcheck, 直至无警告。menuconfig 用法见 使用 menuconfig。

2 精简内核配置文件

反复阅读片段审计结果、修改问题,可使 .config 尽可能精简有效。

构建中的 kernel_configcheck 将最终配置与输入比较,报告:

  • 请求但未进入最终配置的选项。

  • 同一片段中重复的项目。

  • 标记为 required 却被覆盖的项目。

  • 开发板覆盖非板专用选项。

  • 当前内核中根本不存在的无效选项。

备注

还可选报告处理过程中任何被覆盖的选项。

每个警告指向选项列表文件及定义它们的片段,这些文件是精简配置的关键。

流程如下:

  1. 使用已知可用配置: 确认完整配置能够构建并启动,作为基线。

  2. 分别运行配置与检查任务:

    分别执行:

    $ bitbake linux-yocto -c kernel_configme -f
    $ bitbake linux-yocto -c kernel_configcheck -f
    
  3. 处理结果: 根据警告文件:

    • 删除片段中重复定义、但不影响最终配置的值。

    • 分析并酌情删除覆盖必需配置的值。

    • 分析并酌情删除非开发板专用选项。

    • 删除重复和无效项。

  4. 重新配置并检查: 再运行两个任务,检查效果并处理剩余问题。

迭代第二至第四步,最终得到精简配置,然后构建 Linux Yocto 内核。

2 展开变量

可用 bitbake-getvar 查看构建中变量的展开结果:

$ bitbake-getvar -r virtual/kernel VARIABLE

输出详细说明 OpenEmbedded Build System 如何展开并使用变量。

2 处理带 “Dirty” 的内核版本字符串

版本字符串以 "+" 或 "-dirty" 结尾,表示源码目录有未提交修改。清理步骤:

  1. 查找修改: 在本地内核 Git 仓库列出修改、添加或删除的文件:

    $ git status
    
  2. 提交: 无论最终是否保存、导出或使用,都应提交这些修改:

    $ git add
    $ git commit -s -a -m "getting rid of -dirty"
    
  3. 重建内核: 命令因流程而异。devtool 方法见 “使用 devtool 修补内核”, BitBake 方法见 “使用传统内核开发流程修补内核”。

2 使用自己的源码

如果无法采用已有 linux-yocto 配方支持的内核版本,仍可用自己的源码配合 Yocto 内核工具。虽然不能直接利用现有元数据和稳定化成果,仍可使用相同格式 管理自己的元数据,便于未来在共同支持的版本上与 linux-yocto 汇合。

项目提供使用 kernel.org 源码和内核工具的 自定义配方。

基本步骤:

  1. 复制配方: 将 linux-yocto-custom.bb 放入自己的层,合理命名并包含 基线内核版本,例如 linux-yocto-myproject_4.12.bb。

  2. 创建补丁目录: 同目录建立 linux-yocto-myproject 等对应目录,保存 补丁和配置。

  3. 准备配置: 必须提供 defconfig 或配置片段。没有 defconfig 时,可运行:

    $ make defconfig
    

    将生成的 .config 复制到层的 files 目录,命名 defconfig,并加入 SRC_URI。

    make defconfig 生成内核为该架构定义的默认配置,但不保证满足用途或能 启动开发板,非 x86 尤其如此。应查找最接近开发板的配置,例如 ARM 的 arch/arm/configs。

  4. 编辑配方: 按项目修改:

    • SRC_URI:通过 file、git、http 等受支持协议指定 Git 仓库, 并列出 defconfig 或片段。骨架中有语法示例。

    • LINUX_VERSION:使用的内核版本,如 4.12。

    • LINUX_VERSION_EXTENSION:编入内核的 CONFIG_LOCALVERSION, 可通过 uname 查看。

    • SRCREV:构建所用提交 ID。

    • PR:与普通配方相同,通过递增表示配方变化。

    • PV:默认通常足够,结合 LINUX_VERSION 和 +git,打包时在 PKGV 加入版本控制信息。

    • COMPATIBLE_MACHINE:支持的机器。示例默认 "(^$)" 只匹配空串, 刻意使构建失败,必须更改。例如支持 qemux86 和 qemux86-64:

      COMPATIBLE_MACHINE = "qemux86|qemux86-64"
      
  5. 按需继续定制: 与修改已有配方相同,见 “修改现有配方”。

2 使用树外模块

本节介绍在目标构建树外模块,以及将模块集成到构建中。

2 在目标上构建树外模块

传统方式是在正常构建中包含模块,但目标性能足够时,本机编译也可能有用。 不过应先考虑从构建主机使用正确交叉开发环境的优势。

运行 SDK 镜像的目标需要先做准备。所有 *.sdk 镜像默认安装 kernel-dev, 许多还安装 kernel-devsrc,但编译树外模块前仍需生成脚本。

以 root 登录,进入 /usr/src/kernel 并生成脚本:

# cd /usr/src/kernel
# make scripts

所有 SDK 镜像包含 dev-pkgs,因此安装 kernel-dev,适用镜像还安装 devsrc。 SDK 用这些脚本构建模块,准备完成后即可在目标编译。

2 集成树外模块

最好将代码集成进内核,但确需外部模块时,可用 hello-mod 作模板。

复制到层并命名,例如 mymodule_1.0.bb。同目录创建 files,保存源码未包含的 文件和补丁,再按需更新。通常需设置:

根据模块构建系统可能还需调整。典型 Makefile 如下:

obj-m := hello.o

SRC := $(shell pwd)

all:
     $(MAKE) -C $(KERNEL_SRC) M=$(SRC)

modules_install:
     $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
...

关键是 KERNEL_SRC。module 将它和 KERNEL_PATH 设为 ${STAGING_KERNEL_DIR},提供所需内核构建信息。 若模块使用不同变量,可覆盖编译任务或修补 Makefile 采用这些常见变量。

准备好配方后,在机器配置中适当设置下列变量之一以加入镜像:

模块通常不是启动必需,可在某些配置中排除,最灵活的方式是:

MACHINE_EXTRA_RRECOMMENDS += "kernel-module-mymodule"

值由 kernel-module- 加不带 .ko 的模块文件名构成。因为是 RRECOMMENDS 而非 RDEPENDS,模块不可用时不会导致构建失败。

2 检查变更和提交

要了解内核树应用了哪些修改,Git 比跨目录 grep 更高效。

2 内核发生了什么变化?

以下仅是若干 Git 检查方式,并非全部。

备注

不指定提交范围时,kernel.org 历史与 Yocto 修改混合。可以用分支名作为 上下界,仓库界面 https://git.yoctoproject.org/ 可查看分支。

用 git whatchanged 和 commit..commit 查看范围内变化。 例如,linux-yocto-3.19 的 emenlow 分支,以 standard/base 为下界、 standard/emenlow 为上界:

$ git whatchanged origin/standard/base..origin/standard/emenlow

单行摘要:

$ git log --oneline origin/standard/base..origin/standard/emenlow

代码差异:

$ git diff origin/standard/base..origin/standard/emenlow

提交说明和文本差异:

$ git show origin/standard/base..origin/standard/emenlow

为每项变更生成单独补丁,并放到 Documents:

$ git format-patch -o $HOME/Documents origin/standard/base..origin/standard/emenlow

2 显示特定功能或分支变化

标签划分重要功能或分支变更。git show tag 可显示,例如 systemtap:

$ git show systemtap

git branch --contains tag 显示包含该功能的分支:

$ git branch --contains systemtap

2 添加配方空间内核功能

在 配方空间 中,可以用 KERNEL_FEATURES 并在 SRC_URI 指定 SCC 路径添加功能。系统会检查功能 是否存在,缺失则停止构建。功能最后参与配置和补丁处理,因此这样可以强制 确保某功能存在且启用,无需全面审计其他层对 SRC_URI 的添加。

KERNEL_FEATURES 中的 SCC 路径相对于内核元数据根目录。系统搜索 SRC_URI 提供的所有元数据,无论来自 kernel-cache、系统元数据还是配方空间,详见 “内核元数据位置”。

SRC_URI 指定 SCC 后,其所在目录和全部子目录都加入功能搜索路径,因此 一个条目可以暴露多个功能。

以下添加 test.scc:

  1. 创建功能文件: 像补丁、cfg 或其他获取项一样放置 SCC。

    备注

    • 与补丁一样,将所在目录加入获取器搜索路径。

    • 可在该目录下建立其他 SCC,所有子目录都会作为潜在功能目录搜索。

    例如位置为:

    my_recipe
    |
    +-linux-yocto
       |
       +-test.cfg
       +-test.scc
    

    linux-yocto 中同时有 test.scc 和对应 test.cfg。

  2. 加入 SRC_URI: 添加:

    SRC_URI += "file://test.scc"
    

    路径前的空格很重要,因为内容追加到已有值。

  3. 声明为内核功能: 设置:

    KERNEL_FEATURES += "test.scc"
    

    构建内核时就会处理该功能。

    备注

    test.scc 下面的其他功能,其目录相对于 test.scc 所在位置。