GLEP 55:使用 EAPI 后缀的 ebuild 文件(.ebuild-EAPI)

作者 Piotr Jaroszyński <peper@gentoo.org>
类型 标准跟踪
状态 已拒绝
版本 1
创建日期 2007-12-17
最后修改日期 2014-01-23
发布历史 2007-12-17, 2007-12-22, 2009-05-17
GLEP 源代码 glep-0055.rst

"浅学误人,要么深究,要么别碰皮埃里亚的泉水:浅尝辄止会使头脑迷乱,而大量饮用则会使人清醒。"

——亚历山大·蒲柏,《论批评》

状态

该 GLEP 在 2010 年 8 月 23 日的会议上被委员会否决。委员会在 2012 年 5 月 8 日的会议上再次否决了它,赞成从 ebuild 中的 bash 赋值语句中解析 EAPI。

摘要

本 GLEP 提议对 ebuild 使用 EAPI 后缀的文件扩展名(例如,foo-1.2.3.ebuild-1)。

问题

目前在 ebuild 中指定 EAPI 的方式存在缺陷。为了获取 EAPI,包管理器需要加载 ebuild,而 ebuild 本身首先需要 EAPI。否则,它会带来严重的限制,即每个 ebuild 使用任何未来的 EAPI 都必须能够被旧的包管理器加载,因此无法执行以下任何操作

  • 以任何方式更改 inherit 的行为(例如,扩展或更改 eclass 功能)。
  • 以任何合理的方式添加新的全局作用域函数。
  • 扩展 EAPI 中的版本控制规则 - 例如,添加 scm 后缀 - GLEP54 [1] 或允许更合理的版本格式,例如1-rc1, 1-alpha等等,以更紧密地匹配上游。
  • 使用较新的 bash 功能。

当前行为

以下小节显示了如果您在 ebuild 中引入任何上述更改并尝试使用 portage 2.1.6.13 安装它时会发生什么。

继承的不可兼容更改(例如,使其也查看包目录)

sys-apps/foo-1.ebuild:

EAPI="5"
inherit "foo"

DESCRIPTION=""
HOMEPAGE=""
SRC_URI=""
...

结果

*
* ERROR: sys-apps/foo-1 failed.
* Call stack:
*               ebuild.sh, line 1879:  Called _source_ebuild
*               ebuild.sh, line 1818:  Called source '/var/lib/gentoo/repositories/peper/sys-apps/foo/foo-1.ebuild'
*            foo-1.ebuild, line    6:  Called inherit 'foo'
*               ebuild.sh, line 1218:  Called die
* The specific snippet of code:
*              [ ! -e "$location" ] && die "${1}.eclass could not be found by inherit()"
*  The die message:
*   foo.eclass could not be found by inherit()
*
* If you need support, post the topmost build error, and the call stack if relevant.
* This ebuild is from an overlay: '/var/lib/gentoo/repositories/peper/'
*

!!! All ebuilds that could satisfy "sys-apps/foo" have been masked.
!!! One of the following masked packages is required to complete your request:
- sys-apps/foo-1 (masked by: corruption)

当前的 portage 仅在eclass存储库的目录。这会导致致命错误,并且 ebuild 被标记为损坏 - 对用户来说可能非常令人困惑。

新的全局作用域函数

sys-apps/foo-1.ebuild:

EAPI="5"
new_global_scope_function "foo"

DESCRIPTION=""
HOMEPAGE=""
SRC_URI=""
...

结果

/var/lib/gentoo/repositories/peper/sys-apps/foo/foo-1.ebuild: line 7: new_global_scope_function: command not found

!!! All ebuilds that could satisfy "sys-apps/foo" have been masked.
!!! One of the following masked packages is required to complete your request:
- sys-apps/foo-1 (masked by: EAPI 5)

The current version of portage supports EAPI '2'. You must upgrade to a
newer version of portage before EAPI masked packages can be installed.

这不算太糟糕,因为建议用户升级 portage。

新的版本格式

sys-apps/foo-2-rc1.ebuild:

Invalid ebuild name: /var/lib/gentoo/repositories/peper/sys-apps/foo/foo-2-rc1.ebuild

emerge: there are no ebuilds to satisfy "sys-apps/foo"

这不是最佳的错误消息,尤其是在有很多错误消息时。

使用较新的 bash 功能

|&是 bash-4 中添加的一种新的重定向类型。它甚至不能在本地作用域中使用,因为 bash 仍然解析整个 ebuild。

sys-apps/foo-1.ebuild:

EAPI="5"

foo() {
   echo "foo" |& cat
}

结果

/var/lib/gentoo/repositories/peper/sys-apps/foo/foo-1.ebuild: line 8: syntax error near unexpected token `&'
/var/lib/gentoo/repositories/peper/sys-apps/foo/foo-1.ebuild: line 8: ` echo "foo" |& cat'
*
* ERROR: sys-apps/foo-1 failed.
* Call stack:
*               ebuild.sh, line 1879:  Called _source_ebuild
*               ebuild.sh, line 1818:  Called die
* The specific snippet of code:
*      source "${EBUILD}" || die "error sourcing ebuild"
*  The die message:
*   error sourcing ebuild
*
* If you need support, post the topmost build error, and the call stack if relevant.
* This ebuild is from an overlay: '/var/lib/gentoo/repositories/peper/'
*                                                                                                                                                                                                       ... done!

!!! All ebuilds that could satisfy "sys-apps/foo" have been masked.
!!! One of the following masked packages is required to complete your request:
- sys-apps/foo-1 (masked by: corruption)

同样,这不是最佳的错误。

抽象解决方案

此问题的解决方案必须解除这些限制,而唯一的方法是使包管理器能够以无需加载 ebuild 的方式获取 ebuild 的 EAPI。另一个重要要求是解决方案必须向后兼容,这具有使解决方案能够立即应用于 Gentoo 树的良好副作用。与等待任意长的时间相反,因为无论如何时间都不够长,正如在常见 portage 问题页面上列出的问题 - [2] - 所示。

提议的解决方案

提议的解决方案是对 ebuild 使用 EAPI 后缀的文件扩展名。这允许包管理器从 ebuild 文件名中轻松读取 EAPI。它也向后兼容,因为当前 ebuild 通过.ebuild文件扩展名识别,因此包管理器会忽略 EAPI 后缀的 ebuild。

规范

Ebuild 文件名扩展名语法ebuild[-<EAPI>],其中[]表示可选部分,并且<EAPI>是 ebuild 的 EAPI。

ebuild 使用的 EAPI 是如果设置了文件名中包含的 EAPI。否则,将使用 ebuild 内部设置的 EAPI,默认为 0(这是当前行为)。

具有不受支持的 EAPI 的 ebuild 将被屏蔽。

在文件名和 ebuild 中同时设置 EAPI 应被视为错误。

示例

  • pkg-1.ebuild,ebuild 内部未设置 EAPI
    EAPI 默认为 0。
  • pkg-2.ebuild-1,ebuild 内部未设置 EAPI
    使用 EAPI 1。
  • pkg-3.ebuild-1, EAPI="1"
    在两个地方都设置了 EAPI - 错误。

请注意,仍然不允许具有多个具有相同类别、包名称和版本的 ebuild。尽管它具有允许作者提供向后兼容的 ebuild 的优势,但它也会带来问题。第一个是需要严格的 EAPI 排序,第二个是确保单个类别/包版本的每个 ebuild 都等效,即安装其中的任何一个对给定系统具有完全相同的影响。

另请注意,这不是新的限制。已经可以非法地拥有具有不同 EAPI 的多个版本,例如1.0 == 1.00 == 1.00-r0因此,您可以拥有foo-1.0.ebuild使用 EAPI X 和foo-1.00.ebuild使用 EAPI Y。

想法总结

EAPI 后缀的 ebuild 文件(提议的解决方案)

属性
  • 可以立即使用:是
  • 影响性能:否

有人说它清晰简单,也有人说它丑陋且不直观。

文件名中使用 EAPI 并进行一次性扩展更改

提议的文件名格式之一<PKG>-<VER>.eapi-<EAPI>.eb

属性
  • 可以立即使用:是
  • 影响性能:否

这等同于提议的解决方案。

有人说它更好,因为扩展名是静态的。

在 ebuild 内部轻松获取 EAPI

属性
  • 可以立即使用:否
  • 影响性能:是

无法立即使用,因为它会对旧的包管理器触发“当前行为”部分中显示的错误。

性能下降的原因是,在版本格式更改的情况下,包管理器需要 EAPI 来解析 ebuild 的版本。这意味着仅仅选择软件包的最佳版本就需要加载每个可用 ebuild 的 EAPI(来自缓存或 ebuild)。

以下是包管理器如何找出具有 N 个可用版本的软件包的最佳可用版本。

  • 文件名中的 EAPI
    • 读取包含软件包的目录 - readdir()
    • 对于每个 ebuild,读取其 EAPI 并使用它解析其版本 - 无 I/O
    • 对版本进行排序 - 无 I/O
    • 从最高版本到最低版本依次向下
      • 从缓存中获取元数据 - 2 x stat() + read()
      • 如果版本可见,则中断
  • ebuild 中的 EAPI
    • 读取包含软件包的目录 - readdir()
    • 对于每个 ebuild,从缓存中加载其元数据以获取其 EAPI - N x (2 x stat() + read())
    • 对版本进行排序 - 无 I/O
    • 从最高版本到最低版本依次向下
      • (元数据已加载) - 无 I/O
      • 如果版本可见,则中断 - 无 I/O

区别在于包管理器需要访问缓存多少个版本。使用 ebuild 中的 EAPI,它需要对所有版本执行此操作,使用文件名中的 EAPI,它取决于版本的可见性。例如,软件包 foo 的版本为 1、2、3、4、5 和 6。6 被屏蔽,5 为 ~arch,1、2、3 和 4 为 arch。假设用户仅接受此软件包的 arch。使用文件名中的 EAPI,它将仅读取版本 6、5 和 4 的元数据。使用 ebuild 中的 EAPI,它需要加载所有版本的元数据。

很难说平均情况是什么,但肯定最坏的情况(只有最低版本可见)并不常见。

在 ebuild 内部轻松获取 EAPI 并进行一次性扩展更改

属性
  • 可以立即使用:是
  • 影响性能:是

如上一节所述的性能下降。

有人说它清晰简单,也有人说它令人困惑且不直观,因为在其他情况下它是一个 bash 脚本,因此存在任意格式限制。

为不同的 EAPI 使用不同的子目录,例如 cat/pkg/eapiX/

属性
  • 可以立即使用:是
  • 影响性能:是

性能下降的原因是它增加了多个目录读取操作。

有人说它使得维护人员难以查看他们拥有的内容。