13

这个问题适用于任何用一种语言(“源代码”)编写的语言,例如 C 或 Java,并使用动态链接以另一种语言(“二进制”)分发,例如机器代码或 Java 字节代码。


假设用户已经在使用我的库的 A 版。我发布了一个更新的版本 B。

如果他可以编译他的代码而无需对 B 进行更改并正确地与 B 一起运行,则从 A 到 B 的更改被称为source compatible

如果他可以针对 A 编译他的代码并正确地与 B 一起运行,则从 A 到 B 的更改被称为是二进制兼容的。这种情况在使用没有隔离模块加载的传递依赖图(例如 OSGI)时很常见。X 是针对特定版本的 Y 和 Z 编译的,而 Y 是针对不同的特定版本 Z 编译的。在运行时,Y 对 Z 的调用可能不正确并且可能会崩溃。

更改可能是源兼容的,但二进制不兼容。更改也可能是源不兼容和二进制兼容的。

我将哪种兼容性用于语义版本控制?我是使用源兼容性来区分主要和次要/补丁更新,还是使用二进制兼容性来区分主要和次要/补丁更新?


我目前的动机是 Scala 库。Scala 二进制兼容性可能很难分析,需要对编译器细节有很好的理解。源代码兼容和二进制不兼容是很常见的。

这不是一些奇怪的边缘情况。这个问题可以出现在大多数任何编译的、动态链接的语言中。

4

2 回答 2

12

几个月后,我想我有一个很好的结论。

语义版本控制应该考虑两者,并遵循“变化最大”的一个。

  • 破坏源代码编译是对库用户的不兼容更改。
  • 中断运行时执行是对库用户的不兼容更改。

如果源兼容性或二进制兼容性发生变化,则根据语义版本控制,它应该是新的主要版本。

在我的 Scala 中,二进制兼容性有时很难确定。有几个 JAR API 差异工具,例如JDiff

于 2015-12-10T05:44:43.847 回答
0

要回答这个问题,请假设您是一个用户而不是程序员。在他们看来,源代码一文不值;他们不理解它,这对他们来说毫无意义。另一方面,他们有一个包含目标代码的文件,他们知道它需要去某个地方。只有二​​进制文件的版本对他们很重要。

然而,这并不是故事的结局。您的问题隐含地包含了一个更好答案的核心。兼容性有两种,所以应该有两种版本序列。问题本身包含一个功能失调的假设,即应该只有一个版本序列。

现在,如果您有两个版本序列,另外,在用户端创建一种自动方式将源兼容版本转换为对象兼容版本,那么您的问题就得到了缓解。能够做到这一点需要明确指定如何进行转换,例如编译器版本、解释器版本、命令行参数等。

简而言之,对上述问题的最佳答案是它适用于它们两者。

于 2015-12-03T15:58:10.603 回答