如何编写需要内核源 header 文件的 BitBake driver 配方?

How to write a BitBake driver recipe which requires kernel source header files?

简介

我在 BitBake 配方中有一个 do_install 任务,这是我为 driver 编写的,我在其中执行自定义 install 脚本。任务失败,因为安装脚本无法在 <the image rootfs>/usr/src/kernel 中找到内核源 header 文件。此脚本 运行 在生成的 OS 上没问题。

发生了什么事

这是我食谱的相关部分:

SRC_URI += "file://${TOPDIR}/example"
DEPENDS += " virtual/kernel linux-libc-headers "
do_install () {  
   ( cd ${TOPDIR}/example/Install ; ./install )
}

这是 install 脚本的相关部分:

if [ ! -d "/usr/src/kernel/include"  ]; then
  echo ERROR: Linux kernel source include directory not found.  
  exit 1
fi
cd /usr/src/kernel
make scripts
...
./install_drv pci ${DRV_ARGS}

我检查了更改为 if [ ! -d "/usr/src/kernel" ],但也失败了。 install 将不同的选项传递给 install_drv,我在下面有相关部分:

cd ${DRV_PATH}/pci
make NO_SYSFS=${ARG_NO_SYSFS} NO_INSTALL=${ARG_NO_INSTALL} ${ARGS_HWINT}
if [ ${ARG_NO_INSTALL} == 0 ]; then
  if [ `/sbin/lsmod | grep -ci "uceipci"` -eq 1 ]; then
    ./unload_pci
  fi
  ./load_pci DEBUG=${ARG_DEBUG}
fi

${DRV_PATH}/pci 中的 make 目标 build: 本质上是这样的:

make -C /usr/src/kernel SUBDIRS=${PWD} modules

我的研究

我发现这些评论在 linux-libc-headers.inc 相关:

# You're probably looking here thinking you need to create some new copy
# of linux-libc-headers since you have your own custom kernel. To put 
# this simply, you DO NOT.
#
# Why? These headers are used to build the libc. If you customise the 
# headers you are customising the libc and the libc becomes machine
# specific. Most people do not add custom libc extensions to the kernel
# and have a machine specific libc.
#
# But you have some kernel headers you need for some driver? That is fine
# but get them from STAGING_KERNEL_DIR where the kernel installs itself.
# This will make the package using them machine specific but this is much
# better than having a machine specific C library. This does mean your 
# recipe needs a DEPENDS += "virtual/kernel" but again, that is fine and
# makes total sense.
#
# There can also be a case where your kernel extremely old and you want
# an older libc ABI for that old kernel. The headers installed by this
# recipe should still be a standard mainline kernel, not your own custom 
# one.

我有点不清楚我是否可以 'get' 来自 STAGING_KERNEL_DIR 的 header 正确,因为我没有使用 make。

meta/classes 目录中提供的 kernel.bbclass 中,有这个变量赋值:

# Define where the kernel headers are installed on the target as well as where
# they are staged.
KERNEL_SRC_PATH = "/usr/src/kernel"

此路径稍后会打包到 .bbclass 文件中:

PACKAGES = "kernel kernel-base kernel-vmlinux kernel-image kernel-dev kernel-modules"
...
FILES_kernel-dev = "/boot/System.map* /boot/Module.symvers* /boot/config* ${KERNEL_SRC_PATH} /lib/modules/${KERNEL_VERSION}/build"

更新(1/21):

yocto IRC 频道的建议是使用以下行:

do_configure[depends] += "virtual/kernel:do_shared_workdir"

Yocto Project Reference Manual 证实了这一点,其中指出在 1.8 版中有以下更改:

The kernel build process was changed to place the source in a common shared work area and to place build artifacts separately in the source code tree. In theory, migration paths have been provided for most common usages in kernel recipes but this might not work in all cases. In particular, users need to ensure that ${S} (source files) and ${B} (build artifacts) are used correctly in functions such as do_configure and do_install. For kernel recipes that do not inherit from kernel-yocto or include linux-yocto.inc, you might wish to refer to the linux.inc file in the meta-oe layer for the kinds of changes you need to make. For reference, here is the commit where the linux.inc file in meta-oewas updated.

Recipes that rely on the kernel source code and do not inherit the module classes might need to add explicit dependencies on the do_shared_workdir kernel task, for example:

do_configure[depends] += "virtual/kernel:do_shared_workdir" 

但是我很难将其应用到我的食谱中。据我了解,我应该可以将上面的行更改为:

do_install[depends] += "virtual/kernel:do_shared_workdir"

这意味着 do_install 任务现在必须 运行 在 virtual/kernel 配方的 do_shared_workdir 任务之后,这意味着我应该能够使用共享的 workdir(请参阅下面的问题 3),但我仍然有相同的内核缺失 header 问题。

我的问题

我正在使用来自 git.kernel.org 的自定义 linux 内核 (v3.14)。它继承了 kernel class。以下是我的一些问题:

  1. kernel-dev 不应该是继承 kernel class 的任何食谱的一部分吗? (变量词汇表的this section
  2. 如果我将virtual/kernel添加到DEPENDS变量中,那是否意味着kernel-dev会被引入?
  3. 如果 kernel-dev 是我食谱依赖项的一部分,我是否无法从我的食谱中指向 /usr/src/kernel 目录?根据this reply on the Yocto mailing list,我觉得应该。
  4. 如何正确引用内核源代码 header 文件,最好不更改安装脚本?

我认为没有人能正确回答这里的最后一个问题。您正在使用 non-standard 安装方法:我们不知道如何与之交互...

也就是说,看看 meta/classes/module.bbclass 做了什么。它为make设置了几个相关的变量:KERNEL_SRC=${STAGING_KERNEL_DIR}KERNEL_PATH=${STAGING_KERNEL_DIR}O=${STAGING_KERNEL_BUILDDIR}。也许您的安装程序支持其中一些环境变量,您可以在您的配方中设置它们?

考虑您的环境

请记住,在构建时环境中有不同的环境,包括:

  • 系统根
  • 对于内核,共享工作目录
  • 目标包

kernel-dev 是一个目标包,您可以将其安装到目标系统的 rootfs 中,用于某些东西,例如 perf/oprofile 等分析工具需要的内核符号映射。它在构建时不存在,尽管它的一些内容在 sysroots 或共享工作目录中可用。

指向正确的目录

你的 do_install 运行s 在构建时所以这是在构建系统的构建目录结构中,而不是目标系统。特别是,/usr/src/ 将不正确,它需要是您的构建目录中的某个路径。 virtual/kernel do_shared_workdir 任务填充 ${STAGING_DIR_KERNEL} 因此您可能希望在脚本中切换到该目录。

添加任务依赖性

该:

do_install[depends] += "virtual/kernel:do_shared_workdir

假设 do_configuredo_compile 中的任何内容都不会访问那里的数据,

类依赖项对于您的用例来说看起来是正确的。

重新考虑 module BitBake class

建议查看 module.bbclass 中的其他答案是正确的,因为这说明了如何构建通用内核模块。如果你想使用自定义函数或创建命令,这很好,你可以覆盖它们。如果您真的不想使用它 class,我建议您从中获取灵感。

任务依赖性

virtual/kernel添加到DEPENDS意味着virtual/kernel:do_populate_sysroot必须运行在我们的do_configure任务之前。由于此处需要 do_shared_workdir 的依赖项,virtual/kernel 上的 DEPENDS 是不够的。

问题 3 的答案

将构建 kernel-dev 包,但是需要将其安装到目标映像中并在 运行 时间用于真实目标。您在构建时需要它,因此 kernel-dev 不合适。

其他建议

您可能需要 kernel-devsrc 包用于您正在做的事情,而不是 kernel-dev 包。