3、版本锁定策略:PREFERRED_VERSION的用法,强制指定特定版本,处理多版本共存问题

包依赖冲突,说白了就是「A要1.0,B要2.0,两边互不相让」。我在嵌入式项目里见过太多次这种场面了——编译到一半突然报错,说某个库版本不对,然后整个构建就卡在那里。嗯,这时候你就需要一把「锁」,把版本死死钉住。

Yocto 里这把锁,就是 PREFERRED_VERSION。

3.1 什么是 PREFERRED_VERSION?

它就是一个变量。你告诉 BitBake:「这个包,我就要这个版本,别的版本别给我乱来。」

语法很简单:

PREFERRED_VERSION_pkgname = "版本号"

举个例子:

PREFERRED_VERSION_openssl = "1.1.1"

这样,不管其他配方怎么依赖 openssl,BitBake 都只会选 1.1.1 这个版本。

核心要点:PREFERRED_VERSION 只影响「选择哪个配方」,不影响配方内部的构建逻辑。

3.2 什么时候需要用?

我个人习惯,在以下三种场景里一定会用:

  1. 安全补丁锁定——某个版本有已知漏洞,必须用打了补丁的特定版本
  2. ABI 兼容性——两个库必须用同一套 ABI 编译,否则链接时崩溃
  3. 多版本共存——系统里同时需要两个版本,比如 openssl 1.0 和 1.1

我在项目中遇到过最典型的情况:一个老旧的驱动模块只认 openssl 1.0,但新加的加密服务需要 openssl 1.1。两个版本都得留着,怎么办?

答案就是:用 PREFERRED_VERSION 分别指定。

3.3 多版本共存的实战配置

假设你的 layer 里有这两个配方:

  • openssl_1.0.2.bb
  • openssl_1.1.1.bb

在 local.conf 或 distro.conf 里这样写:

# 默认用 1.1.1
PREFERRED_VERSION_openssl = "1.1.1"

# 但某个老驱动需要 1.0.2
PREFERRED_VERSION_openssl:pn:old-driver = "1.0.2"

这里用了 :pn: 覆盖语法,意思是「只针对 old-driver 这个包,openssl 用 1.0.2」。其他包还是用 1.1.1。

小技巧:你可以用 bitbake -s | grep openssl 查看当前所有可用的 openssl 版本,以及哪个被选中了。

3.4 版本号匹配规则

版本号不是随便写的。Yocto 有一套自己的比较逻辑:

写法 含义 示例
1.1.1 精确匹配 只选 1.1.1
1.1.% 通配符匹配 1.1.0、1.1.1、1.1.2 都行
1.1.1+git% 匹配 git 版本 1.1.1+gitAUTOINC+abcdef1

我个人建议:尽量用精确匹配。通配符虽然方便,但容易引入意外版本。我曾经因为用了 1.1.%,结果新拉取的 1.1.3 改了 API,编译直接炸了。嗯,从那以后我再也不敢偷懒了。

3.5 优先级与冲突处理

如果多个地方都设置了 PREFERRED_VERSION,优先级是这样的:

  1. local.conf 中的设置(最高)
  2. distro.conf 中的设置
  3. machine.conf 中的设置
  4. 配方自带的 DEFAULT_PREFERENCE(最低)

你想想看,如果 distro.conf 里锁了 openssl 1.1.1,但 local.conf 里又写了 1.0.2,那最终用的是 1.0.2。因为 local.conf 优先级最高。

注意:PREFERRED_VERSION 只解决「选哪个版本」的问题。如果两个版本在文件系统里冲突(比如都安装同一个路径),你还需要用 PACKAGE_PREPROCESS_FUNCS 或 ALTERNATIVE 机制来处理。

3.6 实战:用 SVG 图理解版本锁定流程

下面这张图,是我自己画的一个简化流程。你看一眼就明白了:

PREFERRED_VERSION 决策流程 多个配方版本 有 PREFERRED_VERSION? 是 否 强制使用 指定版本 按默认 优先级选 确定唯一版本 进入构建

说白了,BitBake 拿到多个版本时,先看有没有 PREFERRED_VERSION。有,就听你的;没有,就按 DEFAULT_PREFERENCE 和版本号大小自己选。

3.7 避坑指南

我踩过几个坑,写出来给你提个醒:

  • 版本号写错——比如写了 1.1.1 但配方里实际是 1.1.1-r0,匹配不上。用 bitbake -s 确认一下。
  • 覆盖语法不对——:pn: 是硬覆盖,_ 是软覆盖。搞混了可能不生效。
  • 忘记清理缓存——改了 PREFERRED_VERSION 后,最好 bitbake -c cleanall pkgname 一下,否则旧版本可能还在 sstate 缓存里。

一句话总结:PREFERRED_VERSION 就是你的「版本保险丝」。用得好,冲突全消;用不好,编译报错。我个人建议,每个项目开始时就定好版本锁定策略,别等到冲突了再临时抱佛脚。

可可精品资料库