译:Swift ABI (一)
翻译自Swift在Github上发布的Swift ABI Manifesto
Swift 4中ABI不会稳定对我们到底有多大影响?ABI究竟是什么?它稳定了又会怎样?达到ABI稳定为什么很困难?有哪些技术细节问题要处理?Swift官方又是如何看待当前Swift发展方向的?Michael Ilseman对这个问题进行了详细的阐述。由于原文较长,11就分几部分陆续分享给大家。希望大家对这个我们平时不太会关注的领域有些了解。
蓝图
当前,Swift最重要的工作之一,就是在多个版本之间保持兼容性。而所谓的兼容性,则是要在源码以及二进制层次上,分别达到它们各自的目标。
在源代码层次实现兼容,也就是让新版本的编译器可以编译老版本的Swift代码。这可以降低开发者在迁移到Swift新版本时的痛苦。没有源代码层次的兼容,用Swift编写的项目就很难得以传承,项目中所有的源代码和使用的程序库必须使用同一个版本的Swift语言。而提供了源代码层次的兼容性,程序库的作者就可以基于某个Swift版本只维护一套代码,并且让程序库的使用者使用更新版本的Swift。
程序库和运行时在二进制上的兼容性则让(用某个版本编译的)程序库在多个不同的Swift版本上进行分发成为可能。二进制的程序库包含了一个Swift module file,它提供了这个程序库API源代码级别的信息;以及一个共享的程序库文件,它包含了在运行时加载的编译之后的代码。因此,实现二进制的兼容性需要完成两目标:
首先,Swift module格式的稳定性可以让编译器用固定的方式表达程序库的公共接口,这也就是Swift module file的稳定性。这包括了API的声明以及代码是否可以inline的表达方式。编译器需要使用module file完成诸多必要的工作,例如,当编译程序库的客户端调用时,对其进行类型检查以及生成调用代码。
其次,ABI的稳定性则为使用不同版本Swift编译的程序库和应用程序提供了兼容性。这是这份文档接下来的部分关注的内容。这份文档探索并解释了什么是Swift ABI,并罗列了宣称Swift ABI已稳定前要进行的调查以及完成的目标。作为Swift社区的一份资源,这份文档也为Swift ABI的发展指明了方向。
这份文档中,会用"SR-xxxx"的形式,引用Swift issue tracking system中的内容。这些内容记录了和Swift ABI相关的工程和设计任务。
什么是ABI?
在运行时,通过Swift编写的二进制程序通过ABI和其他的程序库或组件进行交互。ABI是Application Binary Interface的缩写,它是一个规范,通过这个规范,所有被独立编译的二进制实体才能被链接在一起并执行。这些二进制实体必须在一些很低层的细节上达成一致,例如:如何调用函数,如何在内存中表示数据甚至是如何存储以及访问metadata。
ABI是平台相关的,因为它关注的这些底层细节会受到不同的硬件架构以及操作系统的的影响。大部分的平台都定义了一份可以用于C以及C语言家族代码的“标准ABI”。但Swift是一门和C截然不同的语言,它需要为每一种平台定义自己的ABI。而这份文档中中的绝大部分内容都是和平台无关的,和具体平台相关的考量会影响到Swift ABI的设计和实现细节。如果你要了解不同平台上的“标准ABI”,可以参考附录中的内容。
什么是ABI稳定?
ABI稳定是指把ABI锁定在某种形式,以至于未来的编译器都可以生成遵从这种形式的二进制实体(可以是程序库,也可以是应用程序)。一旦ABI稳定了,就意味着它会伴着这个平台的一生一世,直至日益增长的依赖关系让它走向灭亡。
ABI的稳定性仅会影响到外部可见的公共接口和符号的不变性。而内部使用的符号、调用约定以及内存格局仍旧可以修改而不会破坏ABI约定。例如,未来版本编译器完全可以在保留外部接口函数调用约定的同时,改变内部函数的调用约定。
对ABI做的每一个决定都会对编程语言产生长远的影响,甚至会制约一门编程语言在未来可以发展和进化的空间。Swift未来的版本可能会在更多垂直领域为ABI添加特性,但只要声明了某个平台的ABI已稳定,那么任何在效率以及灵活性上曾经不妥的设计都将永远伴着这个平台存在。
为ABI在垂直领域添加新的特性叫做ABI积累性更新(ABI-additive changes)。每当支持这个特性的Swift版本达到最小目标值的时候,就可以把这个特性纳入积累性更新。这种方式允许我们逐步扩展或锁定ABI中的内容。例如,让ABI支持更多特性,或使用更有效率的数据访问方式等。在这份文档后面,我们会看到很多这样的例子。
ABI稳定了会怎样?
ABI稳定之后,OS发行商就可以把Swift标准库和运行时作为操作系统的一部分嵌入,由于这些标准库和运行时可以支持用更老或更新版本Swift构建的应用程序,这样,开发者就无需在分发应用的同时,还要带上一份自己构建应用时使用的标准库和运行时拷贝。这使得工具和操作系统可以更好的进行集成。
就像之前提到的一样,对二进制程序库来说,ABI稳定是必要但不充分的。模块文件格式的稳定性也是必须的,但这超出了这份文档讨论的范畴。
程序库的进化
通常,如果一门编程语言在表现力和性能上均表现良好,并且还提供了二进制接口,它就很容易表现出二进制接口很脆弱的问题。对于用这种语言编写的程序库或组件来说,要让用户在不重新编译源码的条件下使用新版本的程序库是很难的。当前,Swift主要的前进方向是标准库的进化,自然就要给开发者在维护二进制兼容性这个问题上更多进退的空间。很多实现上的考量的确会对ABI的设计有所影响。
因此,迟迟没有声明ABI稳定的一个主要目的,就是为程序库的进化保留足够的灵活性,而不希望开发者由于ABI的稳定性而限制设计空间。程序库在进化上的考量将会在下面每一个单独的章节中描述,但它们阐述的一个公共的观点则是有些设计细节仍旧没有确定下来。
(To be continue...)