[Development] QProperty and library coding guide

Thiago Macieira thiago.macieira at intel.com
Fri Jul 24 00:05:35 CEST 2020


On Thursday, 23 July 2020 08:33:39 PDT André Pönitz wrote:
> If Qt would bump major versions once a year, and take that as a chance to
> break BC, would that be a problem, if so, why?

Let's assume Qt remains strictly source compatible, not even by removing 
deprecations. That means we can only do minor fixes, like adjusting data 
members and internal details. Pretty much like Boost and LLVM do. And unlike 
Boost, we'd also make all files co-installable, including development files 
(no unversioned binaries in /usr/bin).

That would mean every single application, library and plugin would need to be 
recompiled. No exceptions. Any plugin that isn't recompiled cannot be loaded 
by the host application that is recompiled. Similarly, the application that 
wasn't recompiled can't load plugins that were.

That completely impedes distribution of software in binary form only. So let's 
stipulate that we don't care about non-Open Source Qt applications on Linux.

It's still a major pain to recompile everything. As a packager in a Linux 
distribution with VERY good automation and access to a lot of computing power 
to recompile everything, it's still too difficult to upgrade Boost or Poppler. 
You have to rebuild the kitchen sink of applications. Some of them fail to 
rebuild because some other dependency was also updated and is no longer or not 
yet supported. If one dependency fails to rebuild, what do you do?

As a Qt Creator developer, you may have seen my reporting of issues with Qt 
Creator failing to compile with an LLVM that was released the week prior. And 
this is with a responsible project like Qt Creator; when I reported an issue 
to another project that shall remain nameless that "build is broken with LLVM 
8, 9 and 10", they replied that I was feeling entitled for support and wasn't 
their main audience -- I could supply the fix or wait a few years. Another 
dependency may be the compiler itself: when Clear Linux upgraded from GCC 9 to 
10, a BIG NUMBER of packages failed to recompile themselves because GCC 
changed to -fno-common as the default in C. So rebuilding the world every year 
is not updating Qt and leaving everything else unchanged.

Staying behind is not an option, because some components will require new 
versions of Qt. Failing to upgrade them may also mean you're out of support 
for security fixes. So the moment you have one component requiring an update, 
you have to move the entire system forward. You have to rebuild everything, 
with the latest dependencies. And you have to do it in one go, since you can't 
do component-by-component for a period of months.

And that was for a distribution that can rebuild the world in a week (Clear 
Linux has a tenth of the packages in Debian). For distributions without such 
access to automation and computing power, rebuilding the world every year is a 
non-starter. Even assuming everything "just builds" which is never the case. 
Even a perfectly source-compatible update of Qt is no such thing: think of 
missing #includes.

And remember the condition that we do not remove deprecated things. The moment 
you do, some applications, libraries, frameworks or plugins stop building 
because they were still using the deprecated API. At best, we'd have to have a 
policy that we need to wait 5 years between deprecation and removal of 
anything.

> Because distributions have a large set of packages that are not
> rebuild at least once a year? Or because users have a few hundred
> packages that they don't want to update otherwise?

Not the latter. Updating packages that were rebuilt is practically mandatory, 
given the world of security issues. The problem is building them.

> > We've seen users of not-systemwide-Qt-OSes having BC issues too. Large
> > projects often have binary artifacts they'd rather not recompile every
> > time.
> "Every time" would be something as or less frequent than the current minor
> release cycles, i.e. twice per year, or less frequent.

Agreed, but if you don't rebuild everything every time, you need to have a 
procedure to determine when to do that and what components you can update in-
between those occurrences. So you're adding overhead. The natural conclusion 
is that they will simply not upgrade the Qt version once a project starts, 
even for major versions of their products.

> > Those teams can be taught to recompile, but that's not their current
> > practice. Breaking BC means subtle errors that are hard do detect and
> > debug.
> Right. But at the same time we accept behaviour changes which can lead to
> similar subtle errors that are hard to detect and debug as well.
> 
> I see no real conceptual difference here.

It's a choice. Behaviour differences that are meant to be bugfixes are 
intentional. Unintentional behaviour changes don't often cause data loss and 
crashes. And when they do, we can often go back and fix the issue (q.v. the 
QJsonValue::fromVariant thread).

A BC break is final. And it often leads to crashes and VERY subtle and hard-
to-debug errors. You won't see the issue in your debugger: your debugger may 
tell you a member contains a given value, but your code loads something else.

You did propose that we change sonames or some other way of marking. So at the 
very least we get failures to load instead of subtle errors. That just leaves 
us with the most annoying output of a broken Qt install, that of a found 
plugin that failed to load:

====
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though 
it was found.
This application failed to start because no Qt platform plugin could be 
initialized. Reinstalling the application may fix this problem.

Available platform plugins are: dxcb, eglfs, linuxfb, minimal, minimalegl, 
offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-
xcomposite-glx, xcb.
====

[No, reinstalling doesn't ever fix the problem]

> In any case, I don't think either use case is an absolute reason for keeping
> BC.

It's a choice.

But I warn against choosing to break too often.

A few years ago, Gtk threatened to do that starting with Gtk 4:
https://lwn.net/Articles/691131/
https://blogs.gnome.org/desrt/2016/06/13/gtk-4-0-is-not-gtk-4/
https://blogs.gnome.org/desrt/2016/06/14/gtk-5-0-is-not-gtk-5/

They changed their minds.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel DPG Cloud Engineering





More information about the Development mailing list