Closed smcv closed 2 years ago
An alternative way to get many of the properties I described above, without potentially breaking assumptions around SDL_VERSIONNUM
, would be to introduce a fourth version component (nano version), so that for example regressions in 2.0.22.0 could be fixed in 2.0.22.1:
If it was up to me, I'd personally go for the major/minor/micro, odd/even setup as used in Flatpak and dbus, which I think is fairly straightforward to document and understand.
(Obviously it's not up to me - I am not a SDL maintainer, only a downstream packager and occasional upstream contributor.)
For SDL2 we are limited by the ABI of SDL_VERSIONNUM, where minor can only up to 10. We can definitely move to this scheme in SDL3 however.
In the meantime, we can potentially implement your alternative suggestion with a nano version. We haven't done that because from a manpower perspective we have our hands full simply doing our current full releases and don't have the bandwidth to cherry pick additional interim stable releases.
If someone were willing to do that, we can certainly add release-2.0.N.x branches and I could periodically build releases from that, and SDL_GetRevision() could reflect that in the string returned.
We'll continue to use the odd/even convention for unreleased/released versions. We'll also add rcN tags for release candidates in the future.
@icculus, thoughts?
@slouken are you still planning to bump the version to 2.0.21 for this development cycle?
@slouken are you still planning to bump the version to 2.0.21 for this development cycle?
Yep!
Bumping this out of the 2.0.22 milestone and into our SDL3 planning list, since it would make sense to make significant versioning changes then.
Since we're planning to start SDL3 soon and SDL2 has been using this versioning for almost a decade, we probably shouldn't change this here.
2.0.22 release candidate 1 still thinks it's version 2.0.22 internally, but @slouken tagged it as 2.0.22-RC1
in git, which is a really useful step towards this - thanks for doing that! Doing the same for future RCs would be useful.
You're welcome - will do! :)
SDL 2.0.22 release candidates had quite a lot of regressions, so we had a two steps forward/one step back situation that took a while to sort out. There's still one known regression, #5572, which is not going to be solved until 2.0.24 now.
It's not great that we can't fix regressions without doing a whole new "feature" release, so @slouken asked me to think about this some more.
For SDL2 we are limited by the ABI of SDL_VERSIONNUM, where minor can only up to 10
Since SDL 3 will be incompatible with SDL 2 anyway, we don't actually need SDL_VERSIONNUM
to be a lossless encoding of all possible version numbers, only those that start with a 2; so perhaps we could let the minor version overflow into the thousands digit? That would mean that SDL 2.24.0 would be encoded as 4400, and the highest possible SDL 2 version number 2.255.99 would be 27599. It's a bit nasty, but doesn't seem awful.
The micro version can't go higher than 99 because if it did, that would stop SDL_VERSIONNUM
from being monotonically increasing; and the minor version can't go higher than 255 because SDL_version
uses 1 byte per component.
SDL_VERSION_ATLEAST
could easily be made future-proof by turning it into a more complex expression.
I still think it would be useful to have the versioning structure that GLib and libdbus use, something like this:
Or if making this use of the minor version is off the table as a result of the SDL_VERSIONNUMBER
encoding, then they could perhaps be development prereleases like 2.0.23.1 (read as "2.0.24 beta 1"), followed by stable version 2.0.24.0 and optionally point releases like 2.0.24.1, with the nano version just not appearing in the SDL_VERSIONNUMBER
or SDL_version
?
Either way, to make stable point-releases possible, we'd have to make sure the ABI versioning (LT_CURRENT
, etc.) treats 2.(0.)24.1 as newer than 2.(0.)24.0, but older than 2.(0.)25.0. An easy way to do that would be to always set SDL_INTERFACE_AGE
to 0 for new "feature" versions, even if no new functions have actually been added.
I think both of these comments are good changes. Let's create a PR that implements them and bumps the current development 2.0.23 to 2.23.0?
One question is when do we bump the patch number for development versions? Maybe we never do, and those are always .0, and should never be released in distributions? Or maybe we just do it when/if a development version needs to go into the Steam Linux Runtime, so version comparison works as expected?
Let's create a PR that implements them and bumps the current development 2.0.23 to 2.23.0?
I'll try to do that next week.
One question is when do we bump the patch number for development versions? Maybe we never do, and those are always .0, and should never be released in distributions? Or maybe we just do it when/if a development version needs to go into the Steam Linux Runtime, so version comparison works as expected?
If you want to mark a point in time as "this is a beta/prerelease/whatever, and if you want to look for regressions then this is a good version to synchronize on", then I think it makes sense to give it a unique version number, whether it's going into downstream distributions or not (and even if you don't actually make dist
until you are approaching final release status). When I was chasing regressions in 2.0.22, I found it really useful to be able to say "broken with rc2, fixed in rc3" or similar.
In dbus, we extended the odd/even convention to micro versions: an even micro version like 1.13.18 is a tagged release, and an odd micro version like 1.13.19 indicates some random point in git between 1.13.18 and 1.13.20.
Or if you don't like dbus' approach, then you could bump the micro version (patch number) whenever you do a prerelease, so the progression of versions might go:
and so on.
and should never be released in distributions
The rule I always tell people in projects like dbus and Flatpak is: if you get on the prerelease train, then you have to be prepared to stay on it all the way to the next station. Downstreams can package 1.odd.z versions, but if they do, then it's at their own risk, and they must keep up with the latest releases until they get to the next 1.even.z version (at which point they can decide whether to stay there for a while, or go back to prereleases). Downstreams that do short-term stable releases, like Ubuntu and Fedora, should make sure to avoid shipping a prerelease in those, and downstreams that do long-term stable releases, like Ubuntu LTS and Debian, should definitely be avoiding prereleases.
In Debian, I put 1.odd.z releases (and SDL prereleases, and occasionally git snapshots) in the experimental branch, which is what experimental is for: it's not expected to work smoothly (it's intended to be higher-regression-risk than a rolling release distribution like Arch, for example). Rolling release variants like Debian testing/unstable, and rolling-release-only distributions like Arch, should usually stick to "stable" upstream releases, and maybe some release candidates if the downstream maintainer is being careful enough.
Or if you don't like dbus' approach, then you could bump the micro version (patch number) whenever you do a prerelease, so the progression of versions might go:
- 2.0.22
- (git main becomes 2.23.0)
- 2.23.1 (prerelease)
- 2.23.2 (prerelease)
- 2.24.0
Yes, I think this approach will work best with our workflow.
When you do the PR, can you also submit them for the SDL_* libraries? I'd like to incorporate this change into the next SDL_image and SDL_mixer releases (which I'm working on now)
I think both of these comments are good changes. Let's create a PR that implements them and bumps the current development 2.0.23 to 2.23.0?
When you do the PR, can you also submit them for the SDL_* libraries?
I'll look at that next.
I think this is a bad idea to change this now. If I didn't say that clearly enough, I'm repeating it again.
If we're doing this, let's change this for SDL3 and not change this for SDL2, which is hopefully going into fixes-only mode soon.
I think this is a bad idea to change this now. If I didn't say that clearly enough, I'm repeating it again.
Do I understand correctly from #5602 that after discussion with @slouken, this objection no longer applies?
Do I understand correctly from #5602 that after discussion with @slouken, this objection no longer applies?
Sam made some good points to me; I withdraw my objection.
git main is now versioned 2.23.0, which will lead to 2.23.x prereleases, and eventually 2.24.0 as the next stable release after 2.0.22.
When you do the PR, can you also submit them for the SDL_* libraries? I'd like to incorporate this change into the next SDL_image and SDL_mixer releases (which I'm working on now)
https://github.com/libsdl-org/SDL_image/pull/222 converts SDL_image to be version 2.5.x, so that 2.6.0 will be the next stable release after 2.0.5. Does that numbering make sense to you?
If the SDL_image pull request looks reasonable, I can look at doing similar for SDL_mixer (2.5.x, leading to a 2.6.0 stable release superseding 2.0.4), SDL_ttf (2.19.x, leading to a 2.20.0 stable release superseding 2.0.18), and optionally SDL_net.
If the SDL_image pull request looks reasonable, I can look at doing similar for SDL_mixer (2.5.x, leading to a 2.6.0 stable release superseding 2.0.4), SDL_ttf (2.19.x, leading to a 2.20.0 stable release superseding 2.0.18), and optionally SDL_net.
Yep, that looks good, thanks!
If the SDL_image pull request looks reasonable, I can look at doing similar for SDL_mixer (2.5.x, leading to a 2.6.0 stable release superseding 2.0.4), SDL_ttf (2.19.x, leading to a 2.20.0 stable release superseding 2.0.18), and optionally SDL_net.
These were merged. The next stable "feature" releases will be:
Are there any work items left before we close this?
Are there any work items left before we close this?
I don't think so, unless you want to use this issue to keep track of any regressions that it triggers elsewhere.
FFmpeg has an overly tight version constraint on its dependency: https://trac.ffmpeg.org/ticket/9768.
py-sdl2 was failing CI in Debian. I reported https://github.com/py-sdl/py-sdl2/issues/228 and sent a PR, which was merged.
Some of the recent SDL releases have had regressions that needed to be fixed shortly after release: 2.0.16 had #4630 and a HIDAPI regression, and 2.0.18 had various regressions that led to 2.0.20 being effectively just a bugfix release for 2.0.18.
However, because there's only one branch in git, each new release also picks up new feature work and technical-debt cleanup, which needs some testing before it's ready to go in a release. It also has a risk of causing new regressions, and the cycle continues.
Downstream distributions like the Steam Runtime, Linux distributions, and games that bundle a copy of SDL can work around this by cherry-picking bugfix patches into their copy (and I regularly do this in Debian and the Steam Runtime), but then mechanisms that compare more than one version and try to use the newest are unable to tell which version is newer/better/more-bug-fixed than the other.
The unofficial prereleases that happen before a stable release, such as https://discourse.libsdl.org/t/sdl-2-0-20-prerelease/34342/7, also identify themselves as being the same version as the actual stable release, which seems likely to lead to confusion; and it isn't immediately obvious which git commit they were built from, because there's no tag like
prerelease-2.0.20pre1
that corresponds to them.I think it could be useful to consider changing the version-numbering model for SDL and adjacent libraries (SDL_image, etc.) to avoid those problems:
Major version: continue to use for incompatible changes. If there is a new version that breaks backwards compatibility, it should be SDL 3, similar to how GTK and Qt major versions work (since GTK 2 and at least Qt 3, maybe earlier). Ideally this doesn't happen very often. If the versioning model is that incompatible changes will always result in a major version bump, then SDL 3 could also simplify the SONAME from
libSDL2-2.0.so.0
tolibSDL3.so.0
.Minor version: reset to 0 for a new major version, or increment for new "feature" releases from
main
- the equivalent of 2.0.16 and 2.0.18 for example. These add new features, new API, or potentially destabilizing changes like the recent event-loop improvements.Micro (patch) version: reset to 0 for a new minor version, or increment for new bug-fix releases. For example, if SDL 2.18.0 has regressions or other particularly bad bugs, then 2.18.1 could fix those regressions but not add any new features, new API, or potentially destabilizing changes (which would wait for 2.19 or 2.20 instead). Releases with micro version > 0 should come from a branch that branches off from
main
at the release tag, for example 2.18.1 might come from a2.18.x
branch. Branches can be maintained for as short or as long a time as you want them to be: it would be good to have a clear policy on which ones get security support, but there's no obligation to support anything older than the latest feature release.Shared library version info: currently SDL uses
libtool -version-info
(current, revision, age) under Autotools, or calculates an equivalent version involvingSDL_INTERFACE_AGE
andSDL_BINARY_AGE
under CMake. If the version number looked like I describe above, then I think it might perhaps make sense to switch to a setup where for example SDL 2.0.22 might be followed by 2.24.0, usinglibtool -version-number 0.${SDL_MINOR_VERSION}.${SDL_MICRO_VERSION}
(making sure to choose the initial version number so that all versions sort in the intended order), and similarly the CMake build system usesSOVERSION 0 VERSION 0.${SDL_MINOR_VERSION}.${SDL_MICRO_VERSION}
. That would make sure that both feature and bug-fix versions sort correctly even if releases are made on more than one branch in parallel, and reduce the book-keeping involved.GTK, Qt, Flatpak and dbus are some examples of projects with approximately this versioning model.
For betas and release candidates, there are a few conventions in common use:
GTK, Flatpak and dbus use the "odd/even" model, where an even minor version like Flatpak 1.10.x is a stable release, and an odd minor version like Flatpak 1.11.x is an alpha, beta or release candidate along the path to the next stable release branch 1.12.x. This relies on downstream distributors knowing which branches they should and shouldn't package (most distributors will only want the stable branches), but Github's ability to mark releases as a prerelease helps: for example in https://github.com/flatpak/flatpak/releases it's hopefully fairly obvious that 1.11.x were not intended for wide use.
Lots of projects use a non-numeric suffix for betas, for example many recent GNOME apps use versioning like
41.alpha1
,41.beta1
,41.rc1
, and then41.0
for the final release. Python does something similar. The disadvantage of this is that it can't easily be represented inSDL_version
orSDL_VERSIONNUM
.X11 projects like Xorg use a version number like 1.19.901 to represent 1.20 release candidate 1, and so on. This is like the
rc1
notation, but would be representable inSDL_version
.It would also be nice if there was a representation for intermediate versions in git. At the moment, SDL seems to have the same convention used in dbus, where an odd micro version indicates a git snapshot, and all formal prereleases or releases have an even micro version. This works by releasing 2.0.20, immediately bumping the version number to 2.0.21, and then bumping the version number again to 2.0.22 before the next release, so that if you see a SDL binary that claims to be version 2.0.21, you know that it's a snapshot from somewhere between 2.0.20 and 2.0.22. Keeping that convention, and documenting it, seems like a good idea.
One potential problem with these suggestions is that
SDL_VERSIONNUM
assumes that the minor version is <= 9 and the micro version is <= 99. That could perhaps be avoided by redefiningSDL_VERSIONNUM
to use a larger "width" for those fields: becauseSDL_VERSIONNUM
is a compile-time thing rather than a runtime thing, hopefully that won't break anyone?