Skip to content

ECMDeprecationSettings: fix linking with static Qt

Since Qt 6.4 there is QT_INLINE_SINCE mechanism which allows Qt to make functions inline while optionally preserving ABI by keeping symbols in shared library.

For shared Qt builds, value of QT_DISABLE_DEPRECATED_BEFORE set when building Qt itself controls whether ABI is preserved or not. If QT_DISABLE_DEPRECATED_BEFORE is set then Qt library doesn't export definitions of such functions (when Qt headers are included by consumers then such functions are always inline). Value of QT_DISABLE_DEPRECATED_BEFORE therefore does not matter for consumers (if they build from source) because we can use inline function regardless of whether it is exported from another shared library or not.

However when Qt is static, then QT_DISABLE_DEPRECATED_BEFORE set when building code that consumes Qt headers (i.e. here) also controls whether these functions are inline when Qt headers are included by consumers. Since everything is then linked in the same executable / shared library, value of QT_DISABLE_DEPRECATED_BEFORE must be the same when building static Qt and when building code that consumes it. Failure to do so will result in ODR violations (for some reason on Linux it's ignored, but MSVC fails at linking step). Qt by default doesn't set QT_DISABLE_DEPRECATED_BEFORE when building itself so we shouldn't do it either.

Related bug: https://bugreports.qt.io/browse/QTBUG-109449

Here is minimal project that demonstrates the issue: https://github.com/equeim/qt-static-linking-error-example. You need to link it with static Qt on Windows (it's already set up to use vcpkg).

Also AFAIK linking against static Qt was completely broken in 6.4.0-6.4.2, and fixed by this commit: https://codereview.qt-project.org/c/qt/qtbase/+/449082. Its description is incorrect though, inlining for static Qt builds is not "never" but controlled by QT_DISABLE_DEPRECATED_BEFORE like I described above.

Merge request reports