-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
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 redefining SDL_VERSIONNUM
to use a larger "width" for those fields: because SDL_VERSIONNUM
is a compile-time thing rather than a runtime thing, hopefully that won't break anyone?