You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Buildroot编译私有内核模块时内核源码不可用的问题排查

问题:Buildroot编译私有内核模块时找不到内核头文件

背景

拿到一个包含私有内核模块源码的.zip包,解压后需运行安装脚本,脚本会解压实际源码并编译内核模块,该过程依赖内核头文件。使用Buildroot 2022.02.1和内核5.15.33。

当前使用的Buildroot .mk文件

FOOCO_VERSION = 1.0
FOOCO_SOURCE = cust_kernel_drvr.zip
FOOCO_SITE = /mnt/third-party/fooco
FOOCO_SITE_METHOD = local

define FOOCO_CONFIGURE_CMDS
    unzip $(@D)/$(FOOCO_SOURCE) -d $(@D)
endef

define FOOCO_BUILD_CMDS
    chmod +x $(@D)/TOOLS/Linux_x64/DRIVER/install
    cd $(@D)/TOOLS/Linux_x64/DRIVER; $(SHELL) ./install
    rm -rf $(@D)
endef

$(eval $(generic-package))

构建错误日志

DEBUG: start | rsync | fooco
>>> fooco 1.0 Syncing from source dir /mnt/third-party/fooco
rsync -au --chmod=u=rwX,go=rX  --exclude .svn --exclude .git --exclude .hg --exclude .bzr --exclude CVS /mnt/third-party/fooco/ /root/buildroot-2022.02.1/output/build/fooco-1.0
DEBUG: end | rsync | fooco
DEBUG: start | configure | fooco
>>> fooco 1.0 Configuring
unzip /root/buildroot-2022.02.1/output/build/fooco-1.0/cust_kernel_drvr.zip -d /root/buildroot-2022.02.1/output/build/fooco-1.0
Archive: /root/buildroot-2022.02.1/output/build/foofo-1.0/cust_kernel_drvr.zip
[snip]
   creating: /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/
   creating: /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/
  inflating: /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/install
  inflating: /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/cust_kernel_drvr-1.2.0.15-0.noarch.rpm
  inflating: /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/cust_kernel_drvr.tar.gz
  inflating: /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/license_gpl.txt
[snip]
DEBUG: end | configure | fooco
DEBUG: start | build | fooco
>>> fooco 1.0 Building
chmod +x /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/install
cd /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER; /bin/bash ./install
Extracting archive..OK!
Compiling the driver...Error: make[1]: Entering directory '/root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/fooco_cust/src/linux/driver'
common.mk:82: *** Kernel header files not in any of the expected locations.
common.mk:83: *** Install the appropriate kernel development package, e.g.
common.mk:84: *** kernel-devel, for building kernel modules and try again.  Stop.
make[1]: Leaving directory '/root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/fooco_cust/src/linux/driver'
Error: unable to find driver file (fooco_cust.ko) in /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/fooco_cust/src/linux/driver
rm -rf /root/buildroot-2022.02.1/output/build/fooco-1.0
DEBUG: end | build | fooco
touch: cannot touch '/root/buildroot-2022.02.1/output/build/fooco-1.0/.stamp_built': No such file or directory
make: *** [/root/buildroot-2022.02.1/output/build/fooco-1.0/.stamp_built] Error 1
package/pkg-generic.mk:289: recipe for target
'/root/buildroot-2022.02.1/output/build/fooco-1.0/.stamp_built' failed

内核模块Makefile的头文件查找路径

该模块的makefile会在以下路径查找内核头文件:

/lib/modules/${BUILD_KERNEL}/source \
/lib/modules/${BUILD_KERNEL}/build \
/usr/src/linux-${BUILD_KERNEL} \
/usr/src/linux-$(${BUILD_KERNEL} | sed 's/-.*//') \
/usr/src/kernel-headers-${BUILD_KERNEL} \
/usr/src/kernel-source-${BUILD_KERNEL} \
/usr/src/linux-$(${BUILD_KERNEL} | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \
/usr/src/linux \
/usr/src/kernels/${BUILD_KERNEL} \
/usr/src/kernels

疑问

为什么内核源码在构建过程中不可见?我以为Buildroot编译内核后,头文件会自动供后续内核模块编译使用,是不是漏了什么设置?


解答

核心原因

Buildroot的内核头文件和编译环境不在模块安装脚本默认查找的路径里:

  • Buildroot将内核构建产物放在$(LINUX_DIR)(通常为output/build/linux-<version>),但模块的Makefile只会去主机系统的标准路径查找,自然找不到对应版本的内核文件。
  • 使用generic-package模板不会自动关联内核构建的依赖和环境变量,无法传递内核路径给模块编译流程。

解决步骤

  1. 添加内核依赖声明
    模块必须在内核编译完成后再构建,需添加依赖:

    FOOCO_DEPENDENCIES = linux
    
  2. 传递内核构建环境给编译流程
    显式告诉模块的makefile内核源码目录,通过KERNELDIR变量传递。修改FOOCO_BUILD_CMDS:

    define FOOCO_BUILD_CMDS
        chmod +x $(@D)/TOOLS/Linux_x64/DRIVER/install
        # 若安装脚本支持参数,直接传递内核路径
        cd $(@D)/TOOLS/Linux_x64/DRIVER; $(SHELL) ./install --kerneldir=$(LINUX_DIR)
        # 若安装脚本不支持参数,跳过脚本的自动编译,手动调用make
        # cd $(@D)/TOOLS/Linux_x64/DRIVER/fooco_cust/src/linux/driver; make KERNELDIR=$(LINUX_DIR)
    endef
    
  3. 移除构建目录删除命令
    原BUILD_CMDS中的rm -rf $(@D)会导致Buildroot无法创建.stamp_built标记文件,直接引发报错,需删除该行。

  4. 改用kernel-module模板(更规范)
    Buildroot提供的kernel-module模板专门用于内核模块编译,会自动处理内核依赖和环境变量,调整后的.mk文件示例:

    FOOCO_VERSION = 1.0
    FOOCO_SOURCE = cust_kernel_drvr.zip
    FOOCO_SITE = /mnt/third-party/fooco
    FOOCO_SITE_METHOD = local
    FOOCO_MODULE_MAKE_OPTS = KERNELDIR=$(LINUX_DIR)
    FOOCO_DEPENDENCIES = linux
    
    define FOOCO_EXTRACT_CMDS
        unzip $(DL_DIR)/$(FOOCO_SOURCE) -d $(@D)
        # 解压内部的tar.gz到指定目录
        tar xf $(@D)/TOOLS/Linux_x64/DRIVER/cust_kernel_drvr.tar.gz -C $(@D)
    endef
    
    define FOOCO_BUILD_CMDS
        $(MAKE) -C $(@D)/fooco_cust/src/linux/driver $(FOOCO_MODULE_MAKE_OPTS)
    endef
    
    define FOOCO_INSTALL_TARGET_CMDS
        $(MAKE) -C $(@D)/fooco_cust/src/linux/driver $(FOOCO_MODULE_MAKE_OPTS) INSTALL_MOD_PATH=$(TARGET_DIR) modules_install
    endef
    
    $(eval $(kernel-module))
    

额外说明

Buildroot的交叉编译环境中,内核头文件不会安装到主机的/usr/src或/lib/modules路径,而是保留在$(LINUX_DIR)下。必须显式传递内核路径给模块的编译流程,否则它只会在主机系统的标准路径查找,无法找到对应版本的内核头文件。


内容的提问来源于stack exchange,提问作者Paul Woods

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 12:30:58