【问题标题】:Semantic versioning: minor or major change? (second part)语义版本控制:小改动还是大改动? (第二部分)
【发布时间】:2020-01-21 16:44:59
【问题描述】:

前段时间I had asked 向共享库的struct 添加字段是否需要根据语义版本控制对版本字符串进行重大或次要更改。少数参与者倾向于提出重大改变。

几个月过去了,我还没有向我的struct 添加任何字段。但现在可能正是这样做的好时机。

但与此同时,我也一直在思考这会如何破坏使用我的库以前版本编译的程序的二进制兼容性,老实说,就我所想的而言,我还没有发现任何可能的二进制兼容性情况休息。

新字段添加到结构的末尾,使用我的库的人通常不会分配这个struct他/她自己,而是接收指向它的指针作为回调函数的参数。这就是我的图书馆所做的一切,用户永远不需要使用这个struct回调图书馆。

当旧程序与新版本的库一起运行时,可能的情况有两种:

  1. 在正常情况下(即旧程序收到指向此struct 的指针并读取它需要的字段),我的库将从现在开始发送指向更大struct 的指针,但旧程序不会知道并且不在乎。
  2. 如果旧程序出于某些未知原因分配了这个struct,它仍然会分配一个较小的结构(这确实是程序在编译时知道的),但我的库不知道它并不关心,因为它永远不需要从用户那里接收这个struct,它只将它作为一个指针发送。

在之前的讨论中,也有人发布了来自Linux Program Library HOWTO — §3.6. Incompatible Libraries的这句话:

当新版本的库与旧版本二进制不兼容时,soname 需要更改。在 C 语言中,库不再兼容二进制有四个基本原因:

  1. 函数的行为发生变化,使其不再符合其原始规范,

  2. 导出的数据项发生变化(例外:将可选项添加到结构的末尾是可以的,只要这些结构仅在库中分配)。

    李>
  3. 导出的函数被移除。

  4. 导出函数的接口发生变化。

案件编号。 2 似乎在谈论不透明的结构。我的struct 不是不透明的,但情况很相似。但真正的问题是,正如我所说,我还没有找到一个单一的场景会在此更改后破坏二进制兼容性。

所以问题还是一样:这是次要版本还是主要版本更改?

【问题讨论】:

  • 您的选择。尽管/因为第 2 点,该更改需要更改主要版本。您似乎不愿意进行主要版本更改 - 但您没有解释为什么?这主要是任意的。我会选择专业,但你对未成年人的论点也支持 AFAICS。
  • @Johnathan 在之前的讨论中,我没有解释很多细节,通常struct 添加字段确实需要更改主要版本。但是,幸运的是,在这种情况下并非如此。如果新版本的源代码和二进制文件都与以前的版本兼容,我认为是语义版本控制本身表明我应该只增加次要版本号而不是主要版本号。我的意思是,这不是语义版本控制的重点,阅读版本更改并准确理解它的含义吗?
  • 正如我所说,您的选择。该决定可能取决于非技术(非语义)问题——您的客户群将如何改变主要版本而不是次要版本;您的营销部门是否更愿意更改主要版本以允许对正在进行的开发等进行更令人兴奋的宣传等。您是否希望并且在技术上可以将共享对象版本与营销版本分离?此时,您需要做出决定。无论您选择哪种方式,您的客户都不太可能抱怨。
  • 您是否提供了一个函数来释放分配的结构,或者分配的结构总是在一个单元中分配,以便简单地调用free() 就足够了。你应该提供这样的功能吗?这让您在未来有更大的灵活性。但是,它的存在与否不一定是控制因素。并且“旧”程序仍然可以分配结构的副本并使用它并释放它。如果额外字段需要辅助分配,则会出现重大问题——因此,我假设额外字段是简单的非指针字段。
  • 因此,您希望别人给您的答案是“(仅)次要版本的更改是可以的”。用不超过两个音节的词来说,就是这样。这也是我的第一条评论,虽然没有那么明确。

标签: c struct shared-libraries versioning semantic-versioning


【解决方案1】:

我能看到的唯一问题是,如果用户做了一些依赖于结构大小的事情,然后在没有更新代码的情况下重新编译程序时会出现意外结果。最有可能受到影响的是像 Gentoo 这样的非二进制发行版,或者可能是 Yocto 构建链。

例如,如果用户将这些结构的数组的内容写入文件,该文件希望在程序下次运行时读取。如果程序根据库的新版本重新编译,如果它不知道版本之间的变化,就会出现问题。如果存在不使用sizeof 等不良做法,则可能会出现另一个问题。

【讨论】:

  • 感谢您的补充。如果他们确实使用sizeof,我看不出二进制不兼容是如何产生的。如果旧程序重新编译,它将自动对齐到新大小(感谢sizeof);而如果程序是在此版本之前编译的,它总是会处理struct 的截断版本——但这没关系,因为截断的struct 正是旧程序所需要的。我看到的唯一可能的突破是手动编写struct 的大小。但这可能会导致机器之间的不兼容,即使根本不更新库!
【解决方案2】:

这是一个重大变化。 SemVer 没有提及二进制兼容性。

您的客户可能正在将数据保存到文件中。如果它是一个二进制文件,那么记录大小刚刚改变。读者如何知道哪些文件记录是旧格式,哪些是新格式?程序如何知道这种结构类型不止一种?

如果针对新定义编写和编译的代码遇到旧格式的数据怎么办?更改 C 结构中的字段数量绝对是 SemVer 的重大更改。现在您可能会在 Linux 内核库的上下文中被忽视,但请注意您的新代码永远不会用于处理旧数据格式。

【讨论】:

    猜你喜欢
    • 2019-07-31
    • 2022-01-02
    • 2016-04-14
    • 2019-04-29
    • 1970-01-01
    • 2018-01-09
    • 2015-08-10
    • 2013-02-15
    • 2017-04-23
    相关资源
    最近更新 更多