Reputation: 83205
This question applies to any language which is written in one language ("source"), e.g. C or Java, and distributed in another ("binary"), e.g. machine code or Java byte code, using dynamic linking.
Suppose a user is already using version A of my library. I release a newer version B.
If he can compile his code without change against B and correctly run with B, the change from A to B is said to be source compatible.
If he can compile his code against A and correctly run with B, the change from A to B is said to be binary compatible. This situation is common when using transitive dependency graphs without isolated module loading (e.g. OSGI). X is compiled against certain versions of Y and Z, and Y was compiled against a different certain version of Z. At runtime, Y's calls into Z may not be correct and may crash.
It is possible for changes to be source compatible, but binary incompatible. It is also possible for changes to be source incompatible and binary compatible.
Which compatibility do I use for semantic versioning? Do I use source compatibility to differentiate between major and minor/patch updates, or do I use binary compatibility to differentiate between major and minor/patch updates?
My current motivation is a Scala library. Scala binary compatibility can be very difficult to analyze and requires an good understand of compiler details. Source compatibility and binary incompatible is very common.
This isn't some bizarre edge case; this problem can appear in most any compiled, dynamically linked language.
Upvotes: 16
Views: 1652
Reputation: 83205
A few months later, I think I have a good conclusion.
Semantic versioning should consider both, and follow the "most changed" one.
If either source compatibility or binary compatibility changes, it should -- according to semantic versioning -- be a new major version.
In my case for Scala, binary compatibility can be sometimes be rather difficult to determine. There are several JAR API diffing tools, e.g. JDiff.
Upvotes: 15
Reputation: 7430
To answer this question, pretend that you are a user that is not also a programmer. From their point of view, source code is worthless; they don't understand it and it's meaningless to them. On the other hand, they have a file containing object code and they know that it needs to go somewhere. Only the version of the binary matters to them.
That's not, however, the end of the story. Your question implicitly contains the kernel of a much better answer. There are two kinds of the compatibility and so there should be two version sequences. The question itself contains a dysfunctional assumption, namely, that there should be only one version sequence.
Now, if you have two version sequences and, in addition, create an automatic way on the user end to convert source-compatible versions into object-compatible versions, you've alleviated your problem. Being able to do this requires explicitly specifying how you do the conversion, such as things like compiler version, interpreter version, command line arguments, etc.
In short, the best answer to the stated question is that it applies to both of them.
Upvotes: 0