ABI稳定性将如何永远改变迅速

介绍

随着Swift 5即将发布,人们对其新功能-ABI稳定性有了很多期待。 尽管该消息已广受好评,但人们对ABI的稳定性有一些误解。 在本文中,我将尝试消除一些误解,并解释ABI稳定性将如何永久改变Swift。

什么是ABI稳定性?

简而言之,ABI稳定性意味着Swift标准库和运行时可以嵌入OS本身,而不是随应用程序捆绑提供。 目前,您构建的每个应用程序均随附Swift标准库和运行时的副本,以确保该应用程序可以在不同的OS版本上运行。 在Swift的早期,这曾经是必不可少的,因为作为一种新兴的新兴语言,它易于快速发展和发生重大变化。 但是Swift已经存在了一段时间,并且已经成熟到我们现在可以考虑在操作系统级别集成它的程度。 为了使这成为可能,Swift ABI需要变得稳定,这是对Swift 5的主要关注。

目前,只有Apple OS平台会受到影响,例如iOS和MacOS。 Swift核心团队打算在将来对像Linux这样运行Swift的非Apple平台进行类似的更改。

ABI稳定性的好处

在您的应用程序中拥有Swift标准库的副本具有很大的影响力,因为这会使您的应用程序规模变大。 所有这些都将在Swift 5中进行更改。通过将Swift标准库和运行时嵌入到OS中,可以减小应用程序包的大小,并减少应用程序的下载量。

ABI的稳定性宣称Swift正在成为一种成熟的编程语言。 结果是我们不太可能看到Swift的重大变化。 当您回想起我们从Swift 2迁移到Swift 3时的痛苦时刻,这似乎是一种好处,但有一个警告。 我们将在文章中对此进行进一步讨论。

ABI稳定性的另一个好处是,它将使我们更加接近使第三方Swift二进制框架更加实用—我们将在本文结尾处进一步讨论这一点。

使Swift ABI稳定的尝试并不新鲜

已经有尝试使Swift ABI稳定下来。 ABI稳定性最初是在Swift 3中提出采用的,但最终被推迟了。 Swift 4也发生了同样的事情,因为Swift Core团队已经宣布它是一个艰巨的目标,现在看来Swift 5将实现ABI稳定性。

Objective-C是ABI稳定的,可以预见,因为它是一种更为成熟的语言,并且已经存在了很长时间。 在操作系统级别已经存在一个Objective-C运行时,这意味着Objective-C可以轻松地在不同的编译器版本上运行。 这有助于解释为什么与Swift应用程序相比,Objective-C应用程序具有较小的应用程序下载大小。 但是随着Swift成为稳定的ABI,这可能是促使Objective-C坚持者转换为Swift的动力,因为它将成为一种更可行,稳定和成熟的语言。

ABI稳定性与编译器兼容性有关

二进制文件是已编译的源代码。 ABI或应用程序二进制接口定义二进制文件通过其进行通信的规则。 ABI听起来很像API或应用程序编程接口的工作方式,只是ABI的工作水平很低。

在运行时,Swift程序二进制文件通过ABI与其他库和组件进行交互。 ABI是应用程序二进制接口,或者是独立编译的二进制实体必须符合的规范才能链接在一起并执行。 这些二进制实体必须在许多底层细节上达成一致:如何调用函数,如何在内存中表示其数据,甚至元数据在哪里以及如何访问它们。

本质上,当Swift成为ABI稳定版时,这意味着不同的Swift版本将在OS级别的同一编译器上运行。 因此,Swift 5应用程序和假设的Swift 7应用程序将能够在同一编译器上工作。 您可以将其视为所有未来Swift版本都必须遵循的标准化ABI。 为此,您需要将ABI锁定到将来的编译器版本可以生成符合稳定ABI的二进制文件的程度。 但这会带来重大后果。

在ABI稳定之后,重大的Swift变化将不太可能

有关ABI的决定将产生长期影响,并可能限制该语言将来的发展和演变方式。 未来的Swift版本可以为ABI添加新的,正交的方面,但是声明稳定性时出现的任何无效或不灵活性将(有效)对于该平台永久存在。

如果在宣布ABI稳定时有任何问题,那么这些问题可能会在Swift的整个生命周期中持续存在。 这是本文所提到的永远的大方面。 ABI稳定性将对Swift的发展产生深远的长期影响。 我敢肯定,现在为什么我们必须等待Swift语言变得更加成熟,才可以负责任地实现ABI稳定性。

ABI的稳定性还意味着Swift不太可能看到重大变化。 这并不意味着不会发生重大更改,但是如果这样做,Swift团队将不得不经历一些重大障碍,以使更改与二进制文件兼容。

ABI稳定性只是难题的一部分

真正的愿景是实现Swift版本之间的整体兼容性。 ABI稳定性只是朝这个方向迈出的一步。 迅速的ABI宣言宣布了两个重要目标。

  1. 源代码兼容性 -这意味着使不同版本的Swift源代码在同一编译器上运行。 过去,当引入新的Swift版本时,您需要将代码更改为新的Swift版本。 这不可避免地导致了移植的痛苦,这将使拥有大型代码库的开发人员遭受最严重的打击。 还有版本锁定的问题,您所有的Swift代码都必须使用同一版本进行构建。 这将随着源兼容性而改变。 在这方面已经有了进展。 从Swift 4开始,我们现在具有兼容模式来编译较早版本的Swift。
  2. 二进制框架和运行时稳定性 -目标是使无缝地分发第三方二进制框架成为可能。 使用Objective-C可以完成所有操作,但是使用Swift要做同样的事情。 从技术上讲,您可以创建一个Swift二进制框架,但是它会被锁定为使用它创建的Swift版本。 这意味着使用您的二进制框架的人必须具有相同的Swift版本。 这也给框架的创建者带来了移植之苦的问题。 使二进制框架兼容需要实现两件事,即模块格式稳定性和ABI稳定性。

迈向二进制框架兼容性

二进制框架已编译为源代码,其中包含具有可在应用程序中使用的已定义接口的资源。 关于ABI稳定性,我们正在谈论第三方二进制框架或您创建的可重用解决方案。 创建二进制框架有很多充分的理由。 它有助于隐藏专有代码,保护创作者的知识产权。 它还隐藏了框架采用者不必担心的技术细节。 二进制框架包括两个部分。 第一部分是共享库,根据Apple的说法,该共享库提供了在运行时加载的已编译实现 。 第二个是模块,据Apple所说,该模块传达框架API的源级别信息。 这两个部分都需要二进制兼容。

我们已经详细讨论了ABI稳定性。 在二进制兼容性的上下文中,将Swift标准库和运行时嵌入到操作系统中时,二进制框架的共享库可以在不同版本的Swift中工作。 但这还无法轻松分发Swift二进制框架! 根据Apple的编译器工程师Michael Ilseman的说法:

对于二进制框架,ABI稳定性是必要的,尽管还不够。 模块格式的稳定性也是必需的……。

这意味着当我们获得ABI稳定性时,我们仅达到二进制兼容性的一半。 我们还需要模块格式稳定性。 最终引入Swift 5时,我们不太可能获得模块格式的稳定性,因为它已被描述为可扩展的目标。 一直有人猜测我们可以使用Swift 5.1来获得它,但是我们必须拭目以待。

但是模块格式的稳定性是什么呢? 好了,目前,二进制框架的模块文件使用一种称为“ swiftmodule”的不透明存档格式来描述库的接口。 但是,这与特定版本的编译器相关联,这意味着如果二进制框架是在其他版本的Swift中编译的,则不能使用该二进制框架。 模块稳定性旨在消除此问题。

模块格式的稳定性可稳定模块文件,该文件是编译器对框架公共接口的表示。 这包括API声明和内联代码。 使用框架编译客户端代码时,编译器将模块文件用于必要的任务,例如类型检查和代码生成。

ABI稳定需要多长时间?

您可以使用ABI仪表板跟踪实现ABI稳定性的进度。 ABI稳定性大约有六个先决条件,其中包括有关数据布局,类型元数据,处理,调用约定,运行时和标准库的问题。

图书馆发展

在有关ABI稳定性的大多数讨论中,似乎都忘记了该主题,但它很重要。 基本上,Swift容易出现脆弱的二进制接口问题。 这带来了不便,每个新库或组件版本都需要重新编译。 Swift的主要目的是确保库向后和向前兼容,也就是说,Swift将支持Library Evolution。 这将对围绕ABI稳定性的决策产生影响。

结论

ABI的整体稳定性不会对我们创建应用程序的方式产生深远影响。 但这将对Swift的发展产生影响。 ABI稳定性的真正亮点在于它表明Swift正在成为一种成熟的语言。 要使Swift真正成熟,还需要做更多的工作,但是所有这些工作都会在适当的时候出现。

资料来源和进一步阅读

迅捷的ABI宣言-迈克尔·伊尔瑟曼

图书馆演变-乔丹·罗斯和约翰·麦考尔

Swift编程语言演进

ABI稳定性和其他功能-Jordan Rose

Swift中的二进制框架-Peter Steinberger