…and it’s still OK.
Please note that this blog post is very old, and not an accurate reflection of the current state of versioning in GTK.
Today is the second day at the GTK hackfest, and we are discussing portals, interactions between applications, and security. That’s not really what this post is about.
Yesterday’s post got quite a lot of feedback. I had a number of discussions with various stakeholders on IRC, and got many nice comments on the post itself. People from a few different distributions, a couple of non-GNOME Gtk-based desktop environments, and a number of app authors have all weighed in positively.
The last post explained the new version policy that we hope to use for the future of Gtk. This post aims to explain some of the benefits of that system, and also why we considered, but ultimately rejected some other options.
The first major takeaway from the new system (and the part that people have been most enthusiastic about) is the fact that this gives many application authors and desktop environments something that they have been asking for for a long time: a version of Gtk that has the features of Gtk 3, but the stability of Gtk 2. Under the proposed scheme, that version of Gtk 3 will be here in about a year. Gtk version (let’s say) 3.26 will be permanently stable, with all of the nice new features that have been added to Gtk 3 over the last 5+ years.
The new system also means that we aim for doing this for our users once per two years from now on. Part of the problem with deciding between Gtk 3 and Gtk 2 was that Gtk 2 was just so old. If we keep the intended two-year cadence, then applications will never have to target a release of Gtk that is more than 18 months older than the most current release. This will reduce a lot of the pain with sticking with the stable version, which is why we anticipate that many more people will choose to do this.
The new arrangement also formalises what a lot of people have been complaining about for a while: Gtk 3 releases, although under an official policy of API compatibility, have often failed to completely live up to this promise. We have also been less than straightforward about exactly what the stability guarantees in Gtk 3 are, which has led to an awful lot of reasonable hesitation about uptake. The new system makes it clear that, during the first 18 months of releases, the Gtk 4 series is absolutely going to be unstable, and you should not target it. On the other hand, when it does become stable, this fact will be very clearly communicated, and you can trust that there will not be any changes of the sort that have hurt some of the users of Gtk 3.
In short: we get more freedom to make major changes during minor releases during the “early days” of a new major version. We advertise this fact clearly. The speed of development will increase. Once we are done breaking things, we very clearly advertise that “Gtk 4 is stable” (around Gtk 4.6). At this point, people know that they can port from Gtk 3 to Gtk 4 and get two years worth of new features with none of the fear about instability.
Most of the negative feedback on yesterday’s post came in the form of confusion about the seemingly complicated scheme that we have selected for the version numbers. Gtk 4.0 is unstable, and so is 4.2 and 4.4, but suddenly 4.6 is the stable version that everyone should use. Meanwhile, Gtk 5.0 is released, which means that everyone should (of course!) use Gtk 4.6… What’s going on here? Have you all lost your minds? Haven’t you people heard about semantic versioning?
This apparent oddness is something that we discussed in quite a lot of detail, and is also the part of the plan that we are probably most open to making changes to as we discuss it in the following months. I don’t think it will change very much though, and here is why:
One possibility that we discussed was to release Gtk 4.0 (gtk-4.0.pc) and tell people that this is the new stable API that they should use. This would not work well with our current situation. There are currently many hundreds of applications using Gtk 3 which would have to go through a mostly-pointless exercise of changing to “gtk-4.pc”, with almost no changes, except a different version. We wanted these people to just be able to continue using Gtk 3, which would suddenly become much more stable than it has been. This is pretty much exactly what everyone has been asking for, in fact.
Let’s say we ignored that and did Gtk 4.0 as the new stable release, anyway. We would want to start working on “Gtk 5” immediately. Where would that work go? What would the version numbers look like? Gtk 4.90-rc, progressing toward Gtk 5.0? We would never have any minor numbers except “.0” followed by alpha/RC numbers in the 90s. This also means that most releases in the “4” series (4.90, etc) would have “gtk-5.pc”. This approach was just too weird. At the end of the 4 cycle, it is reasonable to imagine that instead of 4.7, we might call it 4.99, and have a pkg-config file named “gtk-5.pc”, but we will never have a non-development version (non-odd minor number) with this inconsistency.
We also have to consider that GNOME releases will want to use the new features of Gtk, and that we need to have a versioning scheme that makes sense in context of GNOME. We need to have the Gtk minor releases that go along with each GNOME version. These releases will also need to receive micro releases to fix bugs in the same way that they always have.
Finally: we don’t believe that there is a huge amount of value in following every aspect of semantic versioning just for the sake of it. This sort of thing might seem interesting to users who are not developers, but if you are an actual application author who develops applications in Gtk, then it stands to reason that you probably know some basics about how Gtk works. Part of this knowledge will be understanding the versioning. In any case, if you look at our proposed system, you see that we still mostly follow semver, with only one exception: we allow for API breaks between early even-numbered minor versions. According to many of our critics, we were already kinda doing that anyway.
So that’s all for version numbers.
There is one other complaint that I encountered yesterday that I’d like to address. There is a perception that we have been bad about reviewing patches against Gtk 2.24, and that this lack of attention will mean that we will treat Gtk 3.26 (or whatever) in the same way. This is something that we discussed seriously at the hackfest, after it was raised. One simple thing that I can say is that Gtk 2 has actually seen an awful lot of attention. It has had 30 point releases, including one three months ago. It has had over 100 patches applied so far this year. We could still be doing better. A lot of this comes down to insufficient resources. At the same time, it’s pretty awkward to say this, when people are showing up with patches-in-hand, and we are simply not reviewing them. These people, with a demonstrated interest in bug-fixing stable releases could become new contributors to our project, working in an area where they are sorely needed. We are going to continue discussions about how we can improve our approach here.
tl;dr: The approach we have taken lets everyone make informed decisions about which Gtk version to use, based on public and official information. Today many people say “I’d like to use Gtk 3, but I don’t think it has stabilised enough yet.” Fair enough — we heard you. Soon, Gtk 3 will be much more stable, at which point it will be safer to upgrade. At the same time, we are not going to pretend that Gtk 4.0 is stable at all, or that Gtk 4.2 will look anything like it. When Gtk 4 is stable, we will tell you.
I think people’s main gripe with this scheme is that an indicator of stability in not built into the version itself.
Learning whether a major version of GTK is stable relies on out of band information. That is, looking at GTK 4.6 by itself, one does not know if it can be considered stable or not.
Instead, the developer would need to track down a current “stability” matrix if you will. That is fine if that information is clear and easily accessible, but is not something that many projects have gotten right (those that are not following traditional semver, of course).
We have some ideas here. One of them may be that we have two pkg-config files, one of them named gtk-4 and the other named gtk-4-unstable. gtk-4.pc would only be available after it becomes stable.
On the other hand, maybe we will use gtk-4-stable.pc, which only becomes available once we reach that point. All of these details are yet to be decided.
Using a separate pkg-config name sounds sane to me. I prefer the idea of naming the unstable gtk-4-unstable, because that’s a very clear indication to the developers, sort of like requiring them to #define I_KNOW_THIS_IS_UNSTABLE.
My only concern is that a program that developers will have to change their configure.ac just to build against stable. But developing against unstable means adapting to each release anyway, which means developers probably ought to specify a specific version, rather than a min version.
I think this would be much simpler if you just used, for example, odd major numbers for development releases and even major numbers for stable releases.
So after releasing (stable) 4.0.0, you’d branch off and start developing what will become (unstable) 5.0.0, followed by (unstable) 5.2.0 and so on… After two years, instead of releasing (unstable) 5.6.0 you’d release (stable) 6.0.0, branch off and start working on (unstable) 7.0.0.
Of course you’d be able to release both (unstable) 5.2.1 or (stable) 4.0.1 bugfix releases in the meantime…
Does that make sense? :)
Yes, I’d second that comment. Traditionally, releasing a .0 version is the indicator of stability – from that point, API will evolve, but never break until a new .0 versions appears. When Gtk 3.0 came out, it’s assumed that an app compiled against 3.0 will continue to work against 3.20.
What’s described here is much less clear… if I target Gtk 4.0, you’re saying it may not compile/run on 4.1, much less 4.20. So if I’m writing a Gtk-based app, I have to either ignore the 4.x series until you decide you’ve finished breaking compatibility, or I need to commit to chasing an unstable API. Under this system, it seems like all releases are unstable releases until you decide otherwise.
Contrast this with the current situation, where the release of 4.0 (or at least, an RC) is the thing that tells me that it’s time to start porting code. It’s simple…
Will 3.6, 4.6, 5.6 etc will all get security updates for the forseeable future? Who is going to maintain that many branches in parallel?
This part remains to-be-decided, and it is one of the reasons that we have avoided using the letters “LTS” to this point. This point is very much to be decided, as noted in the post.
I would say that any bugfix (z in x.y.z) in any x.y should be rippled down to x-n.y-t for any active version of the combo n.t.
A bugfix in 5.6.2 (to be called 5.6.3) will be rippled down to 4.6.20 (released as 4.6.21) and 3.6.81 (released as 3.6.82). If a bugfix requires a API change, then 4.6.20 becomes 4.7.z where z is the last release on 4.7.z with z plus 1 (so 4.7.1 if 4.7.0 already exists).
It also gets rippled down to 3.6.82 as 3.7.0 following the same rules, explained earlier, for if a 3.7.0 already exists (so then it’s 3.7.1), or as 3.7.0 if not.
I see no reason why not, so combine this with the techniques introduced by gitflow (develop and master branch with master receiving the releases as merges, and develop receiving the feature branches as merges).
I really hope automated performance regression tests will become a matter of course for GTK+ development – performance regressed heavily during the past few years and nobody seemed to notice because developers are running shiny and powerful machines.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=493714
If you want performance bugs to be fixed in GTK+, please file bug reports about them in bugzilla.gnome.org. We won’t see bug reports in bugs.eclipse.org.
This must be a common problem among library authors? How do other libraries who follow semver.org handle these type of things?
Some strategies that come to mind…
a) Use a release candidate notation. e.g. call it “4.0-rc.1”, “4.0-rc.2”, etc until the point in time the API is stable enough (i.e. formerly known as “4.6”) then drop the rc and call it 4.0 (and celebrate!).
b) After releasing 4.0, if parts of the API *must* change, mark them deprecated instead of breaking compatibility.
c) If a large API break is needed, just throw in the towel and say to heck with 4.x, now it’s 5.0. (It’s just a number after all, there’s lots of them left)
Two cents
> This must be a common problem among library authors?
Gtk’s situation is somewhat unique, since it has long been divided between serving two audiences that very much want something different.
On one hand, it needs to be for GNOME, which has a regular release schedule and expects Gtk to release (non-beta) versions of itself in line with that schedule. On the other hand, GTK also needs to be usable by third party application developers, who have stronger desires for stability.
It is this rather unique situation which has led us to this scheme.
You gave two use-cases. One for non-beta (GNOME) and one for stability (third party application developers). But you forgot to mention everybody else.
Not all third party (application) developers want stability. They want a certain amount of stability. Sure. But some also want (a huge amount of) innovation and experimentation.Some are building with an entirely new concept of UI and input in mind. Gtk+ should be attractive to those developers, too.
But this is something that is always forgotten about, at Gtk+. Yet you see frameworks like GStreamer thrive on being employed and used by innovators that don’t think inside of the box. Cinema streaming of festivals to theaters around the world: gstreamer, live manipulation of TV content: gstreamer, playing video’s on a desktop and in browsers: gstreamer, playing video’s on mobile phones and in infotainment systems for cars: gstreamer, UPnP implementations: gstreamer, etc. Why isn’t Gtk+ allowing this but instead assuming that everything is a desktop or a laptop?
GStreamer has certain targets, too.
The “simple video player” crowd or the “non-linear video editor” crowd or the “music creation software” crowd are not part of these, because software in those cases generally does not use GStreamer and projects that try have a very hard time.
Instead, GStreamer has focused on moderately complex playback solutions and streaming.
> This must be a common problem among library authors? How do other libraries who follow semver.org handle these type of things?
By not breaking compatibility all the time. By having beta branches for upcoming releases until they are ready for guarantees. Basically, you suggestion “a” + rarely if ever actually incrementing the major version.
I think semver still makes sense but to indicate which changes are backwards incompatible within versions i.g. GTK 4.1.0 introduces api changes with respect to 4.0.10.
But this doesn’t indicate whether you should be porting your app to any of these versions, since the “phase” of incompatible changes might still be fast, making the effort to be up to date unworthy, until a stable version is released.
So basically, you’re finally allowing innovation, refactoring and API restructuring to happen at a rapid speed. Good!
I would modularize Gtk+ even further. The guys at Qt have gotten it mostly right at code.qt.io.
http://code.qt.io/cgit/qt/qt5.git/tree gives you the following modules: qt3d, qtactiveqt, qtandroidextras, qtbase, qtcanvas3d, qtconnectivity, qtdeclarative, qtenginio, qtfeedback, qtgraphicaleffects, qtimageformats, qtlocation, qtmacextras, qtmultimedia, qtpim, qtpurchasing, qtqa, qtquick1, qtquickcontrols, qtquickcontrols2, qtrepotools, qtscript, qtsensors, qtserialbus, qtserialport, qtsvg, qtsystems, qttools, qttranslations, qtwayland, qtwebchannel, qtwebengine, qtwebkit, qtwebkit-examples, qtwebsockets, qtwebview, qtwinextras, qtx11extras, qtxmlpatterns
They can all be separately released and versioned (using semver). I think Qt’s modules right now share an API (x.y) version. But why not allow separate API releases too? Just like how Gtk+ 5.0 could be released to work with either GLib 2.0 or 3.0 or …
What you gain is rapid pace of innovation. If glade plus gobject-introspection becomes a combination of what XAML and QML is now, and breaking API changes are needed in Gtk 5.0 to support this, a Gtk 6.0’s development could start to accommodate and abandon the new ideas. The odd and even schema once used by the kernel was imo. quite a nice model for allowing experimental feature development with possibility of API breakage.
I personally think that the fetish born at Guadec in Turkey, of not allowing any API breakage, made Gtk+ miss the boat on smartphones completely (Nokia didn’t like that decision at all). That in turn is making it miss the boat on automotive today.
Don’t miss the boat on VR and augmented reality. But if you do, don’t worry: QML and Qt won’t.
I think another approach is to have an odd even releases for stable in gtk versions.
In this method all major odd number and its point releases will be unstable and when it reaches time for stable release you go to the next major even release, call it stabel and continue development on unstable.
For example all releases 5.0, 5.1, 5.2 etc will be development, after around 2 years of work around you release the stable version as gtk 6.0 and start development on 7.0.
This way in the future you can add patches to gtk 6 and still have proper versioning.
I second your suggestion.
Skip 4.0 and go to 5.0 for unstable, then 6.0 for stable API. This is simple, and developers will never have to ask, search in archives or any thing, because is a simple formula:
Odd versions = Unstable versions, don’t port to it if you need stability.
Even versions = Stable API, port to it is safe.
By a level of .pc files we will have: gtk-5.pc for unstable releases. Use gtk-6.pc for stable ones. This make them parallel installable and you can target your current stable branch of software, like my own projects, to stable GTK+ EVEN versions; while you can target unstable new developments to GTK+ ODD versions searching new features, but with a moving target if you want/need them.
BUG FIXING VERSIONS
We can use minor version for bug fixing releases on stable versions, this is 6.1, 6.2, … 6.27 and so on.
For unstable, no bug fix release is present, you should go to next version to get latest features and bug fixing, this is 5.1, 5.2, 5.3, 5.4.
GNOME STABILITY
GNOME is used by, say, Debian, to provide stable environment, with no stability issues, then you should release GNOME 6.0 with GKT+ 6.0, and feature freeze. This is good, for example for OEM vendors, they want to sell software that will run with no issues in a Desktop Environment, not just a library, moving targets like the ones on Extensions will be a big issue for third party.
UNSTABLE GNOME
GNOME new version for new features should use ODD versions too and depend on ODD GTK+ versions (unstable).
RELEASE FREQUENCY
Now GTK+ and GNOME use time based release, this is Ok in past, but no one now depends on GNOME release schedule any more.
GNOME and GTK+ can be free on release its schedule and got to release early – release often for unstable versions and release when ready fo stable.
So if I understand this right, then there are no more minor version releases. There will be major version alphas then a major version final release and then bugfixes.
GTK 3 has been… complex.
But take GTK 2…
2.0 major release. incompatible with 1.y.z. New features and removed features.
2.0.1 bug fix release of 2.0.0
2.2.0 minor release. compatible with 2.y.z but has new features. no removed features
2.2.1 bug fix of 2.2.0
2.2.2 more bug fixes
2.4.0 minor release
2.4.1 bug fix
The new system is
4.6.0 major version release. Incompatible with GTK 3. New features and removed features.
4.6.1 bug fix
5.6.0 major version release
5.6.1 bug fix
I present a solution for version numbering.
Use odd numbers in first or second version for development.
Make 5.0 the next development release, then 5.1, then 5.2. Have 6.0.0 be the final release. (Instead of 4.0 4.2 4.4 and then 4.6.0 as final release.)
Big fixes on 6 will be 6.0.1 and 6.0.2…
The next development release is 7.0.
The next major version is 8.0.0
This way, *if* you return to minor version updates, then minor version update (new features but compatible API) would be 6.2.0.
Major.minor.bugfix
5.0 first alpha for major releaae
5.1 second alpha for major release
5.2 third alpha for major release
6.0.0 major release
6.0.1 bug fix
6.1.0 first alpha for minor release
6.1.1 second alpha for minor release
6.2.0 minor release
6.2.1 bug fix
6.2.2 bug fix
7.0 first alpha for major release
7.1 second alpha for major release
7.2 third alpha for major release
8.0.0 major release
so the last number is bugfixes.
If x.y then x is odd develop and y is alpha#1, 2, 3…
If x.y.z then x is even and y is even and minor release and z is bug fix OR x is even and y is odd development and z is alpha#1, 2, 3…
OR…. (if you want to swear off major/minor upgrades for good)
5.0 first alpha for major release
5.1 second alpha for major release
5.2 third alpha for major release
6.0 major release
6.1 bug fix
6.2 bug fix
7.0 first alpha for major release
7.1 second alpha for major release
7.2 third alpha for major release
8.0 major release
8.1 bug fix
The versioning scheme is very confusing.
Also what is the point in providing a gtk+-4.2 if the API is changing anyways so much that it is not sane to develop against.
The speed of development should be due to the flexibility in the master branch, not in the release branches.
In case you see a necessity to yield somehow that a version is _very_ API stable, why not just suffix it with `apistable` instead of coding it into the sunversion .6 ?
Easier to grasp, easier to maintain and also more flexible.
How about giving us some Webkit and Webview support for Gnome Shell Extensions with newer versions of GTK.. anything happening or any plans for this?
Hi,
so Gtk goes the same way as TYPO3 already did with the versioning / release workflow in the 7th release cycle and do it again for the 8th.
https://typo3.org/typo3-cms/roadmap/
https://typo3.org/teams-committees/core-development/resources/release-lifecycle/
And the TYPO3 Community knows already, it was a good decision to do so. But, this needs a strong api change and deprecation policy.
So congrats and best regards.
I agree with Leif Gruenwoldt.
Using rc-s seems the best. Have a look at Linux release cycle…
I do like the new scheme though, but the versioning…
Providing a stable Version is never bad. I just hope there is some kind of porting guide from (stable release n) -> (stable release n+1). Something along the lines “Previously you used GTK_FOO(), now we provide GTK_BAR(), with similar features, but better because of…”
I guess what irritates many people is not the numbering scheme (which is a matter of taste), but the implication that a release, once “stable”, will no longer get any new features.
When I target a stable version, I don’t expect it to be frozen in time (modulo bugfixes). I can already get that by shipping my own libraries. By targeting a stable version, I’d ideally hope to get new backward-compatible features for as long as possible, without recompiling.
Instead of this version number shuffling, why not just denote stability with a letter suffix? Marking versions as alpha, beta, and RC qualities?
So, if you’re working on version 4, then you might see a pattern like this: 4.0a, 4.1a, 4.2a, 4.3a, 4.4b, 4.4b, 4.5rc, then 4.6+.
Alpha-quality denoting that it’s not suitable for use unless you’re serious about tracking breakages. Probably only suitable for core Gnome apps as developers put Gtk updates into practice, probably by the same developers working on Gtk. Entire modules may be added, removed, or ripped to shreds in alpha.
Beta-quality denoting that the release is module-stable, but the APIs are not, and things will likely break regularly. 3rd party applications, themes, libraries, and desktop environments using Gtk looking to start significant porting efforts could begin the process here if they plan to release major updates alongside the stable version.
RC denoting that it’s theoretically stable, but if there’s a major issue you will broadcast exactly what breakages will happen and why it happened. Small applications can start porting here to release updates at the same time as stable, but should be aware that they’ll want to watch the release notes.
Once you drop letter suffixes it’s the declaration that things are rock-solid.
With letter notation you aren’t tied to making sure things are stable at an arbitrary version number, separating version and quality notation. If there’s a release that’s particularly smooth you may be able to move into beta and RC earlier in the cycle. If there’s a really rocky release and something is giving everyone headaches you could extend the alpha/beta phases until things solidify.
As a software developer I believe that if we want to be considered a profession, we have to actually be professional in what we do. A small part of this is versioning our software in an intuitive way and not being afraid to make our lives and the lives of the people who interact with our software (developers, packagers, people reporting bugs and end users) better “just for the sake of it”.
You, I and many others here understand this versioning scheme as it at least has its roots in how other GNOME software is versioned. However it is more complicated and as a result worse than semantic versioning which has clear guidelines on this exact situation.
Please do not make us live with more esoteric versioning.
My proposed versioning scheme (the first comment of the previous blog post) provides all of the points made in this new blog post, but is 100% semver compatible, much more clear and straight forward and does not create the apparent confusion infused by the official proposal.
The gist of it is treating each GTK version as a new package, restarting the version number for every release. I’ll attempt to describe it through examples instead this time, in case it may appear more clear to some: (note that the format is )
* GTK4 0.1.0-dev.1 – First development version of GTK4.
* GTK4 0.1.0-rc.2 – Second release candidate of GTK4.
* GTK4 0.1.0 – First GTK4 release (comes alongside a new GNOME version)
* GTK4 0.1.4 – Fourth bugfix release of GTK4 0.1.
* GTK4 0.3.0 – Third GTK4 release (comes alongside a new GNOME version)
* GTK4 1.0.0 – First STABLE release of GTK4.
* GTK4 1.0.2 – Second bugfix release of GTK4 1.0.
* GTK5 0.1-dev.1 – First development version of GTK5.
* GTK5 0.1-rc.3 – Third release candidate of GTK5.
* GTK5 1.0.0 – First STABLE release of GTK5.
And so on, and so forth.
I would appreciate any critics and comments on my proposal.
Here is one crazy idea. What about using negative minor version numbers? Say you start the next series with 4.-6, the next release is 4.-4, then 4.-2, then finally comes the stable 4.0
What I’m missing is the why. Not why two different “stabilities” are needed, that is common in other projects (kernel, firefox, ubuntu all have LTS releases). Assuming the more stable releases have a long enough support life, that sounds great.
No, what I’m missing is: Why must backwards compatibility be sacrificed (so often)? Sure GTK is complex, but the kernel is vastly more complex and manages to consider breaks in ABI compatibility always revertable. This post and the previous basically just states that that’s how it is – is there a good write-up of the justification elsewhere?
https://wiki.gnome.org/Projects/GTK%2B/Lifecycle
Wow, if you must change to one of these, _please_ use the second of these proposals:
“Odd/even major versions”
The alternative idea that “4.0 is not 4” is unusably counterintuitive and, really, just plain ugly.
The information that a package is stable or in development should be communicated by the version string. The developers should not be required to check another source to figure out the status of a package.
If the main reason for this scheme is that Gnome needs new features faster compared to the application developers, then just use a even/odd number notation. This way all the additions to the API can go in the stable packages marked with even numbers. While the breaking changes can go into the development packages marked with odd numbers.
Another thing is that developers in general do not like breaking changes, unless they are the ones that made those breaking changes. Instead of introducing breaking changes often, it would be nicer to mark the deprecated APIs for another stable release. This way the GTK developers will think twice when designing the API and the application developers will have more time to adopt to the new API.
How about you use ubuntu style numberig? just year.month and append LTS to the stable api?