Is it correct to assume that a dependency can be specified only by the major number? #238

Closed
opened 2026-02-17 11:38:43 -06:00 by GiteaMirror · 8 comments
Owner

Originally created by @takanuva on GitHub (Aug 23, 2016).

So, according to the spec, whenever the API change, the major number should be increased (and the remaining reseted to zero). So, an implication is that the API remains the same if two versions have the same major version number.

Is it also correct to assume that we may always upgrade our dependencies according only to the major version? If the API is the same, for non-fragile languages such as Java, Python or Ruby, this should be enough that we may securely upgrade our dependency from version 1.0.0 to any 1.x.y and it would still work, and thus we only need to keep the major number as a dependency for management. Is this correct?

If so, would this be valid (semantically) to fragile languages such as C or C++, in which the ABI may change as well (e.g., adding a new field to a struct)? Or would ABI changes also imply bumping the major version up?

Originally created by @takanuva on GitHub (Aug 23, 2016). So, according to the spec, whenever the API change, the major number should be increased (and the remaining reseted to zero). So, an implication is that the API remains the same if two versions have the same major version number. Is it also correct to assume that we may always upgrade our dependencies according only to the major version? If the API is the same, for non-fragile languages such as Java, Python or Ruby, this should be enough that _we may securely upgrade our dependency from version 1.0.0 to any 1.x.y and it would still work_, and thus we only need to keep the major number as a dependency for management. Is this correct? If so, would this be valid (semantically) to fragile languages such as C or C++, in which the ABI may change as well (e.g., adding a new field to a struct)? Or would ABI changes also imply bumping the major version up?
GiteaMirror added the consensus seekingquestion labels 2026-02-17 11:38:43 -06:00
Author
Owner

@racerxdl commented on GitHub (Aug 24, 2016):

👍

@racerxdl commented on GitHub (Aug 24, 2016): :+1:
Author
Owner

@zafarkhaja commented on GitHub (Aug 25, 2016):

So, according to the spec, whenever the API change, the major number should be increased...

Not exactly, according to the spec

Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced to the public API...

It's not about what has changed (API, ABI, etc), it's about how it has changed. In other words, to justify incrementing of major version the change, whatever that is, should be backwards incompatible. Yes, the spec talks about API but note the word "public" in front of it, because private APIs don't affect client code.

The rule of thumb

if your changes will break the client code then bump the major version, otherwise you don't have to.

@zafarkhaja commented on GitHub (Aug 25, 2016): > So, according to the spec, whenever the API change, the major number should be increased... Not exactly, according to the spec > Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced to the public API... It's not about _what_ has changed (API, ABI, etc), it's about _how_ it has changed. In other words, to justify incrementing of major version the change, whatever that is, should be backwards incompatible. Yes, the spec talks about API but note the word "public" in front of it, because private APIs don't affect client code. The rule of thumb > if your changes will break the client code then bump the major version, otherwise you don't have to.
Author
Owner

@FichteFoll commented on GitHub (Aug 25, 2016):

Adding a field to a struct could both be a breaking and a non-breaking change depending on how it's used. This could also be part of the api in the sense of documentation, i. e. if it explicitly states the length of a struct or that a certain order/position is guaranteed.

@FichteFoll commented on GitHub (Aug 25, 2016): Adding a field to a struct could both be a breaking and a non-breaking change depending on how it's used. This could also be part of the api in the sense of documentation, i. e. if it explicitly states the length of a struct or that a certain order/position is guaranteed.
Author
Owner

@takanuva commented on GitHub (Aug 25, 2016):

So, @zafarkhaja said:

if your changes will break the client code then bump the major version, otherwise you don't have to.

In my question I did not consider non-breaking API changes (i.e., the addition of functions or classes); so the answer to my first question is "no" (I might need to depend on a minor/patch version as well). What about the second: is it correct to assume I might always increase my dependencies from X.a.b to X.c.d as long as a.b < c.d? Or would there ever be a need to limit a range within the same major X version (e.g., X.a.b < dep < X.c.d)?

@FichteFoll, what about breaking ABI changes that are not public API? In my specific scenario, I got libfoo and libbar, each with its own public API, where libbar depends on libfoo, and both use a private static library libqux (in order to get code reuse without extra dependencies, like gnulib). Then, libbar expects that libfoo got a binary-compatible static version of libqux inside of it. Lets say I modify libqux, and recompile libbar with a new version: user code will only break if they do not update libfoo as well! So, would libbar and/or libfoo need a major version bump in this case?

@takanuva commented on GitHub (Aug 25, 2016): So, @zafarkhaja said: > if your changes will break the client code then bump the major version, otherwise you don't have to. In my question I did not consider non-breaking API changes (i.e., the addition of functions or classes); so the answer to my first question is "no" (I might need to depend on a minor/patch version as well). What about the second: is it correct to assume I might always increase my dependencies from X.a.b to X.c.d as long as a.b < c.d? Or would there ever be a need to limit a range within the same major X version (e.g., X.a.b < dep < X.c.d)? @FichteFoll, what about breaking ABI changes that are not public API? In my specific scenario, I got libfoo and libbar, each with its own public API, where libbar depends on libfoo, and both use a private static library libqux (in order to get code reuse without extra dependencies, like gnulib). Then, libbar expects that libfoo got a binary-compatible static version of libqux inside of it. Lets say I modify libqux, and recompile libbar with a new version: _user code will only break if they do not update libfoo as well_! So, would libbar and/or libfoo need a major version bump in this case?
Author
Owner

@FichteFoll commented on GitHub (Aug 25, 2016):

@takanuva, I suppose in that case libbar explicitly defines the version contraints of libfoo (and the contained libqux). I don't think the user should be expected to update lbfoo by himself, but I don't have enough experience with C++ to definitely comment on that.

@FichteFoll commented on GitHub (Aug 25, 2016): @takanuva, I suppose in that case libbar explicitly defines the version contraints of libfoo (and the contained libqux). I don't think the user should be expected to update lbfoo by himself, but I don't have enough experience with C++ to definitely comment on that.
Author
Owner

@FranklinYu commented on GitHub (Feb 17, 2017):

@takanuva I believe the "API" in semantic versioning just means "interface", so it should include any ABI change.

As for the example you mentioned, I think that's a breaking change for libfoo, but not for libbar. Assume initially they are all of version 1.0. After updating libquz, libfoo should be bumped to 2.0, because libquz is part of its interface. In contrast, libbar may only bump to 1.1, and specify that it depends on libfoo 2.0 or greater, forcing user to upgrade libfoo.

@FranklinYu commented on GitHub (Feb 17, 2017): @takanuva I believe the "API" in semantic versioning just means "interface", so it should include any ABI change. As for the example you mentioned, I think that's a breaking change for libfoo, but not for libbar. Assume initially they are all of version 1.0. After updating libquz, libfoo should be bumped to 2.0, because libquz is part of its interface. In contrast, libbar may only bump to 1.1, and specify that it depends on libfoo 2.0 or greater, forcing user to upgrade libfoo.
Author
Owner

@alexandrtovmach commented on GitHub (Jun 10, 2020):

Thanks everyone for contributions, you're amazing 🎆 Did you find any consensus?

@alexandrtovmach commented on GitHub (Jun 10, 2020): Thanks everyone for contributions, you're amazing :fireworks: Did you find any consensus?
Author
Owner

@alexandrtovmach commented on GitHub (Jun 14, 2021):

Closing as staled, feel free to re-open or create a new issue 👻

@alexandrtovmach commented on GitHub (Jun 14, 2021): Closing as staled, feel free to re-open or create a new issue :ghost:
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/semver#238