Yocto交叉编译时libc.so链接脚本致modules_prepare失败的解决问询
搭建Yocto交叉编译环境时内核构建工具编译错误的解决方案
问题背景
在Wind River Linux LTS 22(Yocto衍生版本)的SDK中,执行make modules_prepare构建内核主机工具extract-cert时出现以下错误:
/usr/bin/ld: cannot find /lib64/libc.so.6: No such file or directory /usr/bin/ld: cannot find /usr/lib64/libc_nonshared.a: No such file or directory
对应的构建命令为:
gcc -Wp,-MMD,scripts/.extract-cert.d -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu89 -o scripts/extract-cert scripts/extract-cert.c -L/opt/windriver/wrlinux/22.33/sysroots/core2-64-wrs-linux/usr/lib64 -lcrypto
简化测试命令同样失败,移除-L指定的目标sysroot库路径后即可成功。问题根源是目标sysroot下的libc.so并非实际库文件,而是LD链接脚本,内容如下:
/* GNU ld script Use the shared library, but some functions are only in the static library, so try that secondarily. */ OUTPUT_FORMAT(elf64-x86-64) GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a AS_NEEDED ( /lib64/ld-linux-x86-64.so.2 ) )
核心问题解答
1. 目标sysroot中libc.so文件的作用
该文件是GNU ld链接脚本,是目标系统C库的标准组件,作用是指导链接器为目标程序组合正确的C库依赖:
- 优先链接目标系统的动态C库
/lib64/libc.so.6 - 对仅存在于静态C库
/usr/lib64/libc_nonshared.a中的函数,自动补充静态链接 - 指定目标程序运行时的动态链接器
/lib64/ld-linux-x86-64.so.2
它仅用于目标程序的交叉编译,而非主机工具的构建。
2. 避免其干扰内核构建的方法
内核构建中的extract-cert等工具是运行在主机上的程序,应使用主机系统的C库,而非目标sysroot的库。解决方法分为临时和持久化两种:
- 临时方案:手动删除目标sysroot下的
/opt/windriver/wrlinux/22.33/sysroots/core2-64-wrs-linux/usr/lib64/libc.so,但此操作会影响目标程序的交叉编译,仅适合临时测试。 - 正确方案:构建主机工具时清除目标sysroot库路径的环境变量,执行
make modules_prepare前运行:
或者先重置环境变量再执行构建:make modules_prepare LD_LIBRARY_PATH="" LDFLAGS=""export LD_LIBRARY_PATH="" export LDFLAGS="" make modules_prepare
3. 让Yocto预先准备内核源码,省去modules_prepare步骤
可以实现,通过修改Yocto配置让SDK生成时自动完成内核源码的预处理:
- 创建内核配方的append文件(如
linux-windriver_%.bbappend),添加以下内容:do_install_append() { cd ${S} # 执行modules_prepare生成必要的构建文件 make modules_prepare # 保存配置文件和符号表到SDK的内核源码目录 cp .config ${D}${KERNEL_SRC_PATH}/.config cp Module.symvers ${D}${KERNEL_SRC_PATH}/Module.symvers } - 重新生成包含内核源码的SDK:
安装此SDK后,内核源码已完成bitbake -c populate_sdk <your-image-name>modules_prepare,可直接构建外部模块。
4. SDK安装后消除libc.so相关错误的持久化方案
若无法预先完成源码准备,可修改SDK的环境配置脚本实现自动环境切换:
- 打开SDK安装目录下的
environment-setup-core2-64-wrs-linux文件,添加以下函数:# 准备内核构建环境,清除目标sysroot库路径影响 prepare_kernel_build() { export ORIG_LD_LIBRARY_PATH=$LD_LIBRARY_PATH export ORIG_LDFLAGS=$LDFLAGS export LD_LIBRARY_PATH="" export LDFLAGS="" echo "Kernel build environment prepared. Run 'restore_env' to revert." } # 恢复原交叉编译环境 restore_env() { export LD_LIBRARY_PATH=$ORIG_LD_LIBRARY_PATH export LDFLAGS=$ORIG_LDFLAGS unset ORIG_LD_LIBRARY_PATH ORIG_LDFLAGS echo "Environment restored to cross-compile mode." } - 使用时,先执行
prepare_kernel_build进入内核构建环境,完成构建后执行restore_env恢复交叉编译环境。
内容的提问来源于stack exchange,提问作者penguin359
相关产品推荐
相关产品推荐

