Package: qt6-base-dev Version: 6.6.2+dfsg-8 Severity: important Justification: build regression affecting multiple downstreams User: debian-cr...@lists.debian.org Usertags: ftcbfs X-Debbugs-Cc: debian-cr...@lists.debian.org Control: affects -1 + src:qt6-declarative
Hi, qt6-declarative fails to cross build from source since around 6.6. The last successful version was 6.4.2+dfsg-4 and the first known failing is 6.6.2+dfsg-3. Since then the failure is: | dh_install -a -O--buildsystem=cmake\+ninja | dh_install: warning: Cannot find (any matches for) "usr/lib/arm-linux-gnueabihf/qt6/qml/QmlTime/qmltime.qmltypes" (tried in ., debian/tmp) | | dh_install: warning: qml6-module-qmltime missing files: usr/lib/arm-linux-gnueabihf/qt6/qml/QmlTime/qmltime.qmltypes | dh_install: error: missing files, aborting | make: *** [debian/rules:17: binary-arch] Error 255 | dpkg-buildpackage: error: debian/rules binary-arch subprocess returned exit status 2 Now getting to the bottom of this is a lot like searching for a needle in a haystack. I haven't found the needle, but I'm pretty confident in discarding much of the haystack. In diagnosing this, I very much relied on differential builds. I instrumented the rules to add --trace-expand to the cmake invocation and compared a native and cross build log. A native build generates the file as: | [4905/6992] cd /<<PKGBUILDDIR>>/obj-x86_64-linux-gnu/tools/qmltime && /<<PKGBUILDDIR>>/obj-x86_64-linux-gnu/lib/qt6/libexec/qmltyperegistrar --generate-qmltypes=/<<PKGBUILDDIR>>/obj-x86_64-linux-gnu/lib/x86_64-linux-gnu/qt6/qml/QmlTime/qmltime.qmltypes --import-name=QmlTime --major-version=1 --minor-version=0 --follow-foreign-versioning @/<<PKGBUILDDIR>>/obj-x86_64-linux-gnu/tools/qmltime/qmltypes/qmltime_foreign_types.txt -o /<<PKGBUILDDIR>>/obj-x86_64-linux-gnu/tools/qmltime/qmltime_qmltyperegistrations.cpp /<<PKGBUILDDIR>>/obj-x86_64-linux-gnu/tools/qmltime/meta_types/qt6qmltime_none_metatypes.json && /usr/bin/cmake -E make_directory /<<PKGBUILDDIR>>/obj-x86_64-linux-gnu/tools/qmltime/.qt/qmltypes && /usr/bin/cmake -E touch /<<PKGBUILDDIR>>/obj-x86_64-linux-gnu/tools/qmltime/.qt/qmltypes/qmltime.qmltypes I could not find qmltime.qmltypes in the cross build log, which initially led me to the wrong path as I was searching for things that would inhibit building it. Eventually, I dug into the differences in the --trace-expand output and noticed that the cross build log has a qmltime_native.qmltypes and that actually gets installed. It just happens to not be called qmltime.qmltypes and that makes dh_install unhappy. So where does this "_native" suffix come from? It originates in /usr/lib/$DEB_HOST_MULTIARCH/cmake/Qt6/QtToolHelpers.cmake: | # Sets QT_WILL_BUILD_TOOLS if tools will be built and QT_WILL_RENAME_TOOL_TARGETS | # if those tools have replaced naming. | function(qt_check_if_tools_will_be_built) | # By default, we build our own tools unless we're cross-building. | set(need_target_rename FALSE) | if(CMAKE_CROSSCOMPILING) | set(will_build_tools FALSE) | if(QT_FORCE_BUILD_TOOLS) | set(will_build_tools TRUE) | set(need_target_rename TRUE) | endif() | else() | set(will_build_tools TRUE) | if(QT_FORCE_FIND_TOOLS) | set(will_build_tools FALSE) | if(QT_FORCE_BUILD_TOOLS) | set(will_build_tools TRUE) | set(need_target_rename TRUE) | endif() | endif() | endif() | | set(QT_WILL_BUILD_TOOLS ${will_build_tools} CACHE INTERNAL "Are tools going to be built" FORCE) | set(QT_WILL_RENAME_TOOL_TARGETS ${need_target_rename} CACHE INTERNAL | "Do tool targets need to be renamed" FORCE) | endfunction() and | # Returns the tool name for a given tool target. | # This is the inverse of qt_get_tool_target_name. | function(qt_tool_target_to_name out_var target) | set(name ${target}) | if (QT_WILL_RENAME_TOOL_TARGETS) | string(REGEX REPLACE "_native$" "" name ${target}) | endif() | set(${out_var} ${name} PARENT_SCOPE) | endfunction() In essence, this is a cross/native difference. When cross compiling, we may decide whether we need to build tools skip them and merely use the native ones. When we do build them, they get renamed. (Why?) In a native build, we can opt to use installed tools by setting QT_FORCE_FIND_TOOLS and then if we still want to build them, they also get renamed. For cross compilation, we're between a rock and a hard place. Either we set QT_FORCE_BUILD_TOOLS (and this seems to be implied by QT_BUILD_TOOLS_WHEN_CROSSCOMPILING, which we already set in d/rules) and then we end up with the _native suffix or we don't set it and then we end up without those tools. In neither case will the build system install them into the desired place. Bummer. I also find the "_native" naming strange. In the Debian world, we tend to use "native" in a similar meaning as "build" (i.e. the architecture we are using to perform the build), but those "*_native" things actually do get compiled with a host architecture compiler. In most other contexts, I would expect the "host" objects to keep their name and perform the renaming on the "build" (or "native") objects. Could it be that this is a bug in qt6-base-dev? I mean the code still is fairly fresh and only broke relatively recently. The last successful build used qt6-base 6.4.2+dfsg-21.1+b1 and the first failing build used 6.6.2+dfsg-8. Digging into the history, https://github.com/qt/qtbase/commit/acfbe3b7795c741b269fc23ed2c51c5937cd7f4f looks very suspicious to me. Could it be that it is the one that breaks it? The underlying bug report is https://bugreports.qt.io/browse/QTBUG-99683. In any case, we should likely replace QT_BUILD_TOOLS_WHEN_CROSSCOMPILING with QT_FORCE_BUILD_TOOLS in most qt6 packages. You can find the affected ones: https://codesearch.debian.net/search?q=QT_BUILD_TOOLS_WHEN_CROSSCOMPILING+path%3Adebian%2Frules&literal=1 Can someone from the Qt team handle this replacement? I mean like committing it to git now without a need to upload this change right now. Would you prefer me filing separate bugs for qt6-wayland, qt6-quick3d, qt6-scxml, qt6-shadertools and qt6-remoteobjects? Is anyone able to take this to Qt upstream? Helmut