共计 2154 个字符,预计需要花费 6 分钟才能阅读完成。
ABI 稳定性
介绍
应用程序二进制接口(ABI)是程序调用函数和使用其他编译程序的数据结构的一种方法,它是应用程序编程接口(API)的编译版本,换句话说,头文件描述了类、函数、数据结构、枚举和常量,使应用程序能够通过编译到一组地址来执行所需的任务,和预期参数值和内存结构大小以及编译 ABI 提供程序的布局。
必须编译使用 ABI 的应用程序,以使可用地址、预期参数值、内存结构大小和布局与编译 ABI 提供程序的那些一致,这通常通过编译 ABI 提供程序提供的头文件来完成。
由于 ABI 的提供者和 ABI 的用户可以在不同的时间使用不同版本的编译器进行编译,因此确保 ABI 兼容性的一部分责任在于编译器。不同版本的编译器,也许由不同的供应商提供,必须从具有特定内容的头文件生成相同的 ABI,并且必须根据头文件中描述所产生的 ABI 约定,使用访问给定头中描述的 API 的 ABI 为应用程序生成代码。现今编译器具有相当好的跟踪记录,即不破坏它们编译的应用程序的 ABI 兼容性。
确保 ABI 兼容性的剩余责任在于团队维护头文件,这些头文件提供了在编译时在 ABI 中保持稳定的 API。可以对头文件进行更改,但必须密切跟踪更改的性质,以确保在编译时,ABI 的更改方式不会使 ABI 的现有用户与新版本不兼容。
Node.js 中的 ABI 稳定性
Node.js 提供由几个独立团队维护的头文件,例如,node.js 团队维护诸如 node.h 和 node_buffer.h 之类的头文件。v8.h 由 V8 团队维护,尽管与 Node.js 团队密切合作,但该团队是独立的,并且有自己的时间表和优先级。因此,Node.js 团队只能部分控制项目提供的头中引入的更改,因此,Node.js 项目采用了语义版本控制。这可确保项目提供的 API 将为一个主要版本中发布的 Node.js 的所有次要版本和修补程序版本提供稳定的 ABI,在实践中,这意味着 Node.js 项目已承诺确保针对给定主要版本的 Node.js 编译的 Node.js 原生插件将在由编译它的主要版本中的任何 Node.js 次要或补丁版本加载时成功加载。
N-API
对 Node.js 配备 API 的需求已经出现,这导致 ABI 在多个 Node.js 主要版本中保持稳定,创建这样一个 API 的动机如下:
JavaScript 语言从很早就开始与自身兼容,而执行 JavaScript 代码的引擎的 ABI 随 Node.js 的每个主要版本而变化。这意味着完全用 JavaScript 编写的 Node.js 包组成的应用程序无需重新编译、重新安装或重新部署,因为 Node.js 的新主要版本被放入生产环境中,此类应用程序运行在该环境中。相反,如果应用程序依赖于包含原生插件的包,则只要将新的主要版本的 Node.js 引入生产环境,就必须重新编译、重新安装和重新部署应用程序。包含原生插件的 Node.js 包与完全用 JavaScript 编写的包之间的这种差异增加了依赖原生插件的生产系统的维护负担。
其他项目已经开始生成 JavaScript 接口,这些接口本质上是 Node.js 的替代实现,由于这些项目通常构建在与 V8 不同的 JavaScript 引擎上,因此它们的原生插件必然采用不同的结构并使用不同的 API。然而,在 Node.js JavaScript API 的不同实现中使用单个 API 作为原生插件将允许这些项目利用围绕 Node.js 积累的 JavaScript 包的生态系统。
Node.js 将来可能包含不同的 JavaScript 引擎,这意味着,在外部,所有 Node.js 接口将保持不变,但 V8 头文件将不存在。如果与 JavaScript 引擎无关的 API 不是由 Node.js 首先提供并由原生插件采用,那么这样的步骤通常会导致 Node.js 生态系统的中断,特别是原生插件的中断。
为此,Node.js 在版本 8.6.0 中引入了 N -API,并将其标记为 Node.js 8.12.0 中项目的稳定组件。API 在头文件 node_api.h 和 node_api_types.h 中定义,并提供跨越 Node.js 主要版本边界的前向兼容性保证,保证可以说明如下:
N-API 的给定版本 n 将在发布它的 Node.js 的主要版本中提供,以及 Node.js 的所有后续版本,包括后续主要版本。
原生插件作者可以通过确保插件仅使用 node_api.h 中定义的 API 以及 node_api_types.h 中定义的数据结构和常量来利用 N -API 前向兼容性保证。通过这样做,作者通过向生产用户表明,对于他们的应用程序来说,添加原生插件不会增加维护负担,就像添加纯 JavaScript 编写的包一样。
N-API 已版本化,因为有时会添加新 API,与语义版本控制不同,N-API 版本控制是累积的。也就是说,每个版本的 N -API 都传达了与 semver 系统中的次要版本相同的含义,意味着对 N -API 所做的所有更改都将向后兼容。此外,在实验标志下添加了新的 N -API,以便社区有机会在生产环境中审核它们。
实验状态意味着,虽然已经注意确保将来不必以 ABI 不兼容的方式修改新 API,在生产中尚未充分证明其正确和有用的设计,因此,在最终纳入即将推出的 N -API 版本之前,可能会进行 ABI 不兼容的更改。也就是说,前向兼容性保证尚未涵盖实验性 N -API。
上一篇:如何发布 N -API 包