Yocto:如何让opkg知晓pkg_postinst_ontarget_${PN}中文件已被删除
解决opkg升级时因postinst删除文件导致的警告问题
问题场景与原有代码
在OpenEmbedded/Yocto的recipe中,我们先将固件安装到目标文件系统用于烧录外部MCU,烧录完成后通过pkg_postinst_ontarget_${PN}删除固件文件,但升级包时opkg会抛出找不到旧版本固件的错误。
固件安装的Recipe代码
SRC_URI = " \ file://${FIRMWARE_NAME} \ " FILES_${PN} += " \ /home/root/${FIRMWARE_NAME} \ " do_install() { install -d ${D}${FIRMWARE_INSTALL_DIR} install -m 0644 ${WORKDIR}/${FIRMWARE_NAME} ${D}/${FIRMWARE_INSTALL_DIR}/${FIRMWARE_NAME} }
烧录后删除文件的postinst脚本
pkg_postinst_ontarget_${PN}() { < 用firmware.bin烧录MCU的流程 > rm -f ${FIRMWARE_INSTALL_DIR}/${FIRMWARE_NAME} echo "Deleted ${FIRMWARE_NAME} from filesystem." }
升级时的opkg错误信息
Collected errors: * remove_obsolesced_files: unlinking /home/root/firmware_old_version.bin failed: No such file or directory. * opkg_install_pkg: Failed to determine obsolete files from previously installed firmware-zephyr
解决方案
问题根源是opkg的包管理数据库里记录了该固件属于已安装包,但文件实际已被postinst脚本删除,升级时opkg尝试清理旧文件却找不到,从而报错。以下是三种可行的解决方式:
方法1:在prerm脚本中补全空文件
添加pkg_prerm_ontarget_${PN}脚本,在卸载旧版本包时,若文件已被删除就先创建一个空文件,让opkg能正常完成删除操作:
pkg_prerm_ontarget_${PN}() { if [ ! -f ${FIRMWARE_INSTALL_DIR}/${FIRMWARE_NAME} ]; then touch ${FIRMWARE_INSTALL_DIR}/${FIRMWARE_NAME} fi }
方法2:不让opkg跟踪固件文件
直接从FILES_${PN}中移除固件文件的声明,这样opkg的包数据库不会记录该文件,升级时也不会尝试清理它:
# 删掉原有FILES声明中关于固件的部分 # FILES_${PN} += " \ # /home/root/${FIRMWARE_NAME} \ # "
保持do_install和pkg_postinst_ontarget的逻辑不变即可,完全符合固件仅作为临时烧录文件的使用场景。
方法3:用临时子包管理固件
把固件单独打包成临时子包,完成烧录后自行卸载,让opkg正确处理文件生命周期:
- 在recipe中定义临时子包:
PACKAGES += "${PN}-temp-firmware" FILES_${PN}-temp-firmware = "${FIRMWARE_INSTALL_DIR}/${FIRMWARE_NAME}" ALLOW_EMPTY_${PN} = "1" RDEPENDS_${PN} += "${PN}-temp-firmware"
- 给临时子包添加postinst脚本,烧录后卸载自身:
pkg_postinst_ontarget_${PN}-temp-firmware() { < 用firmware.bin烧录MCU的流程 > rm -f ${FIRMWARE_INSTALL_DIR}/${FIRMWARE_NAME} opkg remove ${PN}-temp-firmware echo "Deleted ${FIRMWARE_NAME} and removed temp package." }
内容的提问来源于stack exchange,提问作者Carton_
相关产品推荐
相关产品推荐

