如何编写一个BitBake驱动程序配方,需要内核源头文件?

16

介绍

我在一个BitBake配方中编写了一个名为do_install的任务,用于驱动程序,在该任务中我执行一个自定义的install脚本。该任务失败,因为安装脚本无法在<the image rootfs>/usr/src/kernel中找到内核源文件头。该脚本在生成的操作系统上运行良好。

发生了什么

这是我配方的相关部分:

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.

我有些不清楚如果我没有使用make,是否能够正确地获取STAGING_KERNEL_DIR的头文件。

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项目参考手册的证实,该手册说明在版本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"

这将意味着现在必须在virtual/kernel配方的do_shared_workdir任务之后运行do_install任务,这意味着我应该能够使用共享工作目录(请参见下面的问题3),但我仍然有相同的缺少内核头文件问题。

我的问题

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

  1. 如果继承了kernel类,那么kernel-dev包不应该成为任何配方的一部分吗? (变量词汇表中的这个部分)
  2. 如果我将virtual/kernel添加到DEPENDS变量中,那么kernel-dev会被引入吗?
  3. 如果kernel-dev是我的配方的依赖项之一,那么我是否可以从我的配方指向/usr/src/kernel目录?根据Yocto邮件列表上的这篇回复,我认为我可以。
  4. 如何正确引用内核源文件头文件,最好不更改安装脚本?

你能展示一下你的 example/Install 脚本是做什么的吗?它需要哪些内核头文件?你需要真正的内核头文件,还是只需要 linux-libc-headers? - Anders
我尝试提供足够的细节和源代码来解释我的“install”脚本正在发生什么,请让我知道是否还需要更多帮助。由于这个脚本最终创建了一个模块 - 据我所知 - 我将需要真正的内核头文件。 - karobar
一个标准的模块配方继承了模块,为正常的树外模块构建设置环境。STAGING_KERNEL_DIR是您想要的变量,因为正常的模块配方使用它来查找内核makefile。Module.bbclass还定义了KERNEL_SRC和KERNEL_PATH,它们都指向STAGING_KERNEL_DIR。它还将确保您的依赖关系设置正确。 - Anders
继承模块类似乎是错误的路径,因为“安装”脚本为“make”设置所需的自定义参数,这些参数不仅可以使用模块类进行配置。这也意味着我需要更改几个文件,这些文件不是我的项目的一部分,以使用“KERNEL_SRC”,这似乎是不好的风格。如果您可以就我的三个问题提供一些反馈,我会非常感激。 - karobar
2个回答

15

考虑你的环境

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

  • 系统根目录
  • 对于内核来说,有一个共享的工作目录
  • 目标软件包

kernel-dev 是一个目标软件包,你可以将其安装到目标系统的根文件系统中,用于一些像 perf/oprofile 这样的性能分析工具所需的内核符号映射。它在构建时间不会存在,尽管它的一些内容在系统根目录或共享工作目录中是可用的。

指向正确的目录

你的 do_install 在构建时间运行,因此它是在构建系统的目录结构中,而不是目标系统的目录结构中。特别是,/usr/src/ 不正确,它应该是你构建目录中的某个路径。 virtual/kerneldo_shared_workdir 任务会填充 ${STAGING_KERNEL_DIR},所以你需要在你的脚本中切换到该目录。

添加任务依赖

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

对于您的使用情况,像dependency这样的东西看起来是正确的,假设在do_configure或do_compile中没有访问那里的数据。

重新考虑module BitBake类

其他答案中的建议是正确的,建议查看module.bbclass,因为这说明了如何构建常见的内核模块。如果您想使用自定义函数或执行命令,那么可以覆盖它们。如果您真的不想使用那个类,我建议您从中汲取灵感。

任务依赖关系

将virtual/kernel添加到DEPENDS意味着virtual/kernel:do_populate_sysroot必须在我们的do_configure任务之前运行。由于您在这里需要一个do_shared_workdir的依赖关系,对virtual/kernel的DEPENDS是不够的。

回答第三个问题

kernel-dev包将被构建,但随后需要安装到目标镜像中,并在实际目标上运行时使用。你在构建时需要它,因此kernel-dev并不合适。

其他建议

你可能需要kernel-devsrc包,而不是kernel-dev包。


1
我不认为任何人可以在这里正确回答最后一个问题。您正在使用非标准的安装方法:我们无法知道如何与其进行交互...
话虽如此,请查看meta/classes/module.bbclass执行的操作。它为make设置了几个相关变量:KERNEL_SRC=${STAGING_KERNEL_DIR}KERNEL_PATH=${STAGING_KERNEL_DIR}O=${STAGING_KERNEL_BUILDDIR}。也许您的安装程序支持其中一些环境变量,您可以在配方中设置它们?

谢谢!我的问题并不是关于安装脚本本身,而是关于BitBake能否像从目标rootfs一样运行脚本的能力。我已经更新了我的问题,并提供了更多的澄清,如果您可以再看一下并给我任何反馈,告诉我为什么我的配方无法访问内核头目录,我将不胜感激。 - karobar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接