OlivierLDff / QtStaticCMake

Collection of macros to generate Qt plugin import statement when building with CMake and a static Qt version
BSD 3-Clause "New" or "Revised" License
27 stars 7 forks source link

error on Ubuntu 18.04 - plugin not found #5

Open TobyEalden opened 3 years ago

TobyEalden commented 3 years ago

Thanks for sharing this useful script.

It is working well for me in my project on macOS and Windows platforms. However when I came to build on Ubuntu 18.04 I get loads of 'undefined reference' errors at link time.

I have created a reproducible example at: https://github.com/TobyEalden/QQuickStaticHelloWorld/tree/ubuntu-issues, simply by adding import QtQuick.Controls 2.5 to main.qml.

I'm running with a static build of 5.15.2, but the same was happening on 5.14.2.

Any ideas much appreciated!

TobyEalden commented 3 years ago

I've attached a log of the build output.

errors.log

OlivierLDff commented 3 years ago

I never tried with ubuntu yet. Do you have a link of already compiled qt static binary? Or at least command for me to reproduce?

Can you check the content of QQuickStaticHelloWorld_qml_plugin_import.cpp ?

TobyEalden commented 3 years ago

Thanks for the fast response!

Do you have a link of already compiled qt static binary? The hello world example doesn't compile so I don't have a binary yet.

To reproduce you can clone my fork at https://github.com/TobyEalden/QQuickStaticHelloWorld and try to build it.

The contents of QQuickStaticHelloWorld_qml_plugin_import.cpp are:

// File Generated via CMake script during build time.
// The purpose of this file is to force the static load of qml plugin during static build
// Please rerun CMake to update this file.
// File will be overwrite at each CMake run.

#include <QtPlugin>

Q_IMPORT_PLUGIN(QtQuick2Plugin);
Q_IMPORT_PLUGIN(QtQuick2WindowPlugin);
Q_IMPORT_PLUGIN(QtQuickControls2Plugin);
Q_IMPORT_PLUGIN(QtQmlPlugin);
Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin);
Q_IMPORT_PLUGIN(QtQmlModelsPlugin);
Q_IMPORT_PLUGIN(QtQmlWorkerScriptPlugin);
Q_IMPORT_PLUGIN(QtQuickControls2UniversalStylePlugin);
Q_IMPORT_PLUGIN(QtQuickControls2FusionStylePlugin);
Q_IMPORT_PLUGIN(QtQuickControls2ImagineStylePlugin);
Q_IMPORT_PLUGIN(QtGraphicalEffectsPlugin);
Q_IMPORT_PLUGIN(QtGraphicalEffectsPrivatePlugin);
Q_IMPORT_PLUGIN(QtQuickControls2MaterialStylePlugin);

And just to point out - this works fine on my Windows and MacOS machines. What's more, if I build against a shared version of Qt rather than static it works too.

From what I can see it is linking with the correct plugin library - but I wonder if there is some issue with the order of the libraries in the link command? I came across this which looks somewhat similar: https://lists.qt-project.org/pipermail/interest/2019-August/033665.html

TobyEalden commented 3 years ago

I've attached the output of the cmake step:

cmake.log

And one more thing I've eliminated - the examples included with the static Qt install build and run fine using the normal qmake method.

OlivierLDff commented 3 years ago

I don't think that those are the problem,

From your log it seems that they is an issue with symbols in Qt5QuickControls2.a

In your CMakeCache.txt what is the value of Qt5QuickControls2_DIR ?

What is very strange is that you don't have problem with qmake. Maybe you can try make VERBOSE=1 and try to find what differ from a qmake project to a cmake project.

To reproduce you can clone my fork at https://github.com/TobyEalden/QQuickStaticHelloWorld and try to build it.

Where can i download your compiled version of static qt?

I know i already tried this script with Qt5.14 on debian. My command to build static qt was:

./configure -nomake examples -nomake tests -opensource -static -confirm-license -prefix ../Qt/5.14.2/gcc_64 -platform linux-g++ -qt-xcb 
-fontconfig -xkbcommon -sm -skip webengine -debug-and-release

make -j
make install
TobyEalden commented 3 years ago
  • but are you compiling release or debug? You can see in cmake logs (debug library not available, use release as fallback). Maybe symbols are not exactly the same.

I'm building Release config - I only built the release config of Qt.

cmake --build . --config Release
  • Can you check if QQuickStylePrivate::reset() is present in /home/nuc/dev/qt-static-release/lib/Qt5QuickControls2.a for example

There is no file Qt5QuickControls2.a anywhere in the qt build or installation folder - should there be?

There is a file /home/nuc/dev/qt-static-release/qml/QtQuick/Controls.2/libqtquickcontrols2plugin.a

From your log it seems that they is an issue with symbols in Qt5QuickControls2.a

In your CMakeCache.txt what is the value of Qt5QuickControls2_DIR ?

Qt5QuickControls2_DIR:PATH=/home/nuc/dev/qt-static-release/lib/cmake/Qt5QuickControls2

What is very strange is that you don't have problem with qmake. Maybe you can try make VERBOSE=1 and try to find what differ from a qmake project to a cmake project.

I did look into this but couldn't see anything obvious. I'll give VERBOSE a go.

To reproduce you can clone my fork at https://github.com/TobyEalden/QQuickStaticHelloWorld and try to build it.

Where can i download your compiled version of static qt?

I guess I could zip up the build folder, but it's probably huge. I just did the standard build from source from the docs. I'm pretty confident the Qt build/installation is fine, since the examples work with no problems.

OlivierLDff commented 3 years ago

Qt5QuickControls2.a might have another name, more libQt5QuickControls2.a maybe? Anyway the symbols you are missing are in there. And libQt5QuickControls2 is different than the plugin one.

TobyEalden commented 3 years ago

Here are two versions of the link.txt produced during builds - one from my Mac version which is working, the other from the ubuntu build which is broken.

Both are linking against a static release build of 5.15.2

I have normalised the Qt base path in both files (using search/replace) so that the file differences are easier to spot.

I used FileMerge.app on my macbook to compare the files, one possible suspect I can see is that the Mac file pulls in /QT-BASE/plugins/styles/libqmacstyle.a (around line 100) but there doesn't appear to be an equivalent on the Ubuntu side?

Screenshot 2021-01-23 at 07 44 16

mac-working.txt ubuntu-broken.txt

TobyEalden commented 3 years ago

And this is the output of a build of the dev/qt-static-build/qtdeclarative/examples/quick/tableview/gameoflife example on the same ubuntu Qt build via the default Qt build system. This example uses import QtQuick.Controls 2 and builds and runs fine (see https://github.com/qt/qtdeclarative/blob/5.15.2/examples/quick/tableview/gameoflife/main.qml#L54).

The only thing that jumps out at me is that it doesn't appear to link to libQt5QuickControls2 at all!

gameoflife.txt

OlivierLDff commented 3 years ago

I'm out of idea why this is not working. libQt5QuickControls2.a seems to be linked fine, but missing symbols are in there. Everything seems fine.

I will see if i have time to compile qt myself and try.

TobyEalden commented 3 years ago

Yeah, it's pretty frustrating - I've been struggling with it for over 2 days so far. My app was failing to link so I tried your QQuickStaticHelloWorld repo and it worked. Then I finally established that by simply adding this line causes it to fail (even though the exact same code works on Windows+Mac).

FWIW this is the latest process I used to install and build Qt (although I've tried various other methods with the same results, including a full Qt build). This version builds pretty quickly on my 4 core ubuntu box (remember to change the -prefix path).

git clone https://github.com/qt/qt5
cd qt5
git checkout 5.15.2
./init-repository -f --module-subset=default,-qtwebengine
cd ..
mkdir qt-static-build
cd qt-static-build
../qt5/configure -prefix /home/nuc/dev/qt-static-release -release -opensource -platform linux-g++ -opengl desktop -static -nomake examples -nomake tests -skip qt3d -skip qtactiveqt -skip qtandroidextras -skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdoc -skip qtdocgallery -skip qtfeedback -skip qtgamepad -skip qtlocation -skip qtlottie -skip qtmacextras -skip qtpurchasing -skip qtqa -skip qtremoteobjects -skip qtscript -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtwebengine -skip qtwayland -skip qtwebglplugin -skip qtwebview -skip qtwinextras -skip qttools -skip qtxmlpatterns -nomake tools -skip qtpim -skip qtnetworkauth
make -j20
make install -j20
OlivierLDff commented 3 years ago

Ok i can reproduce the error. With nm i don't see any QQuickStylePrivate::reset symbol inside Qt5QuickControls2.a. What is strange is that you build is working with qmake. I won't have time to look into this now, i'm out of idea.

TobyEalden commented 3 years ago

What is strange is that you build is working with qmake.

Actually, I just checked and although the examples build fine, they don't run - I get qrc:/main.qml:53:1: module "QtQuick.Controls" plugin "qtquickcontrolsplugin" not found printed in the console.

I won't have time to look into this now, i'm out of idea.

Thanks for your help, much appreciated. I suppose I'll file a bug with Qt, although I'd be surprised if something like this has gone unnoticed, given it is exhibited in 5.14.2 as well. I can't help thinking it's something to do with a pre-existing version of some file or other on Ubuntu systems, since they tend to have Qt pre-installed, although ironically it's the static build that fails whereas a shared build works fine...

BTW - do you know exactly what qt5_import_plugins is supposed to do? It looks promising and when I tried it it seemed to generate the stubs and add them as build targets but it didn't run.

TobyEalden commented 3 years ago

Forget that last comment - the Quick Controls 2 examples do indeed build and run.

[edit] - I've just noticed there is a qmlimportscanner_wrapper.sh in the Qt gallery example folder, which looks like:

#!/bin/sh
LD_LIBRARY_PATH=/home/nuc/dev/qt-static-build/qtdeclarative/lib:/home/nuc/dev/qt-static-build/qtbase/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
export LD_LIBRARY_PATH
QT_PLUGIN_PATH=/home/nuc/dev/qt-static-build/qtbase/plugins${QT_PLUGIN_PATH:+:$QT_PLUGIN_PATH}
export QT_PLUGIN_PATH
exec /home/nuc/dev/qt-static-build/qtdeclarative/bin/qmlimportscanner "$@"

I have tried setting up those environment vars before running cmake on a clean folder but it makes no difference...

This is the build output of the gallery example FWIW:

/home/nuc/dev/qt-static-build/qtbase/bin/qmake
-o
Makefile
/home/nuc/dev/qt5/qtquickcontrols2/examples/quickcontrols2/gallery/gallery.pro
g++
-c
-pipe
-O2
-fno-exceptions
-Wall
-Wextra
-ffunction-sections
-fdata-sections
-D_REENTRANT
-fPIC
-DQT_NO_LINKED_LIST
-DQT_NO_FOREACH
-DQT_NO_JAVA_STYLE_ITERATORS
-DQT_NO_LINKED_LIST
-DQT_NO_EXCEPTIONS
-D_LARGEFILE64_SOURCE
-D_LARGEFILE_SOURCE
-DQT_NO_DEBUG
-DQT_QUICKCONTROLS2_LIB
-DQT_QUICK_LIB
-DQT_GUI_LIB
-DQT_QMLMODELS_LIB
-DQT_QML_LIB
-DQT_NETWORK_LIB
-DQT_CORE_LIB
-I/home/nuc/dev/qt5/qtquickcontrols2/examples/quickcontrols2/gallery
-I.
-I../../../include
-I../../../include/QtQuickControls2
-I/home/nuc/dev/qt-static-build/qtdeclarative/include
-I/home/nuc/dev/qt-static-build/qtdeclarative/include/QtQuick
-I/home/nuc/dev/qt-static-build/qtbase/include
-I/home/nuc/dev/qt-static-build/qtbase/include/QtGui
-I/home/nuc/dev/qt-static-build/qtdeclarative/include/QtQmlModels
-I/home/nuc/dev/qt-static-build/qtdeclarative/include/QtQml
-I/home/nuc/dev/qt-static-build/qtbase/include/QtNetwork
-I/home/nuc/dev/qt-static-build/qtbase/include/QtCore
-I.moc
-I/usr/include/libdrm
-I/home/nuc/dev/qt5/qtbase/mkspecs/linux-g++
-o
.obj/gallery.o
/home/nuc/dev/qt5/qtquickcontrols2/examples/quickcontrols2/gallery/gallery.cpp
/home/nuc/dev/qt-static-build/qtbase/bin/rcc
-name
qmake_qmake_immediate
.rcc/qmake_qmake_immediate.qrc
-o
.rcc/qrc_qmake_qmake_immediate.cpp
g++
-c
-pipe
-O2
-fno-exceptions
-Wall
-Wextra
-ffunction-sections
-fdata-sections
-D_REENTRANT
-fPIC
-DQT_NO_LINKED_LIST
-DQT_NO_FOREACH
-DQT_NO_JAVA_STYLE_ITERATORS
-DQT_NO_LINKED_LIST
-DQT_NO_EXCEPTIONS
-D_LARGEFILE64_SOURCE
-D_LARGEFILE_SOURCE
-DQT_NO_DEBUG
-DQT_QUICKCONTROLS2_LIB
-DQT_QUICK_LIB
-DQT_GUI_LIB
-DQT_QMLMODELS_LIB
-DQT_QML_LIB
-DQT_NETWORK_LIB
-DQT_CORE_LIB
-I/home/nuc/dev/qt5/qtquickcontrols2/examples/quickcontrols2/gallery
-I.
-I../../../include
-I../../../include/QtQuickControls2
-I/home/nuc/dev/qt-static-build/qtdeclarative/include
-I/home/nuc/dev/qt-static-build/qtdeclarative/include/QtQuick
-I/home/nuc/dev/qt-static-build/qtbase/include
-I/home/nuc/dev/qt-static-build/qtbase/include/QtGui
-I/home/nuc/dev/qt-static-build/qtdeclarative/include/QtQmlModels
-I/home/nuc/dev/qt-static-build/qtdeclarative/include/QtQml
-I/home/nuc/dev/qt-static-build/qtbase/include/QtNetwork
-I/home/nuc/dev/qt-static-build/qtbase/include/QtCore
-I.moc
-I/usr/include/libdrm
-I/home/nuc/dev/qt5/qtbase/mkspecs/linux-g++
-o
.obj/qrc_qmake_qmake_immediate.o
.rcc/qrc_qmake_qmake_immediate.cpp
g++
-Wl,-O1
-Wl,--enable-new-dtags
-Wl,--gc-sections
-o
gallery
.obj/gallery.o
.obj/gallery_plugin_import.o
.obj/gallery_qml_plugin_import.o
.obj/qrc_qmake_qmake_immediate.o

/home/nuc/dev/qt-static-build/qtbase/plugins/platforms/libqxcb.a
/home/nuc/dev/qt-static-build/qtbase/plugins/xcbglintegrations/libqxcb-egl-integration.a
/home/nuc/dev/qt-static-build/qtbase/plugins/xcbglintegrations/libqxcb-glx-integration.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5XcbQpa.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5XkbCommonSupport.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5LinuxAccessibilitySupport.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5AccessibilitySupport.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5GlxSupport.a
-lxcb-glx
-lxcb-icccm
-lxcb-image
-lxcb-shm
-lxcb-util
-lxcb-keysyms
-lxcb-randr
-lxcb-render-util
-lxcb-render
-lxcb-shape
-lxcb-sync
-lxcb-xfixes
-lxcb-xinerama
-lxcb-xkb
-lSM
-lICE
-lxkbcommon-x11
-lxkbcommon
/home/nuc/dev/qt-static-build/qtimageformats/plugins/imageformats/libqicns.a
/home/nuc/dev/qt-static-build/qtimageformats/plugins/imageformats/libqtga.a
/home/nuc/dev/qt-static-build/qtimageformats/plugins/imageformats/libqtiff.a
/home/nuc/dev/qt-static-build/qtimageformats/plugins/imageformats/libqwbmp.a
/home/nuc/dev/qt-static-build/qtimageformats/plugins/imageformats/libqwebp.a
/home/nuc/dev/qt-static-build/qtbase/plugins/imageformats/libqgif.a
/home/nuc/dev/qt-static-build/qtbase/plugins/imageformats/libqico.a
/home/nuc/dev/qt-static-build/qtbase/plugins/imageformats/libqjpeg.a
/home/nuc/dev/qt-static-build/qtbase/plugins/egldeviceintegrations/libqeglfs-emu-integration.a
/home/nuc/dev/qt-static-build/qtbase/plugins/egldeviceintegrations/libqeglfs-kms-egldevice-integration.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5EglFsKmsSupport.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5KmsSupport.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5EdidSupport.a
-ldrm
/home/nuc/dev/qt-static-build/qtbase/plugins/egldeviceintegrations/libqeglfs-x11-integration.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5EglFSDeviceIntegration.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5EventDispatcherSupport.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5ServiceSupport.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5ThemeSupport.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5FontDatabaseSupport.a
-lfontconfig
-lfreetype
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5FbSupport.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5EglSupport.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5InputSupport.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5PlatformCompositorSupport.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5DeviceDiscoverySupport.a
-lX11-xcb
-lxcb
-lXext
-lX11
-lEGL
/home/nuc/dev/qt-static-build/qtdeclarative/plugins/qmltooling/libqmldbg_debugger.a
/home/nuc/dev/qt-static-build/qtdeclarative/plugins/qmltooling/libqmldbg_inspector.a
/home/nuc/dev/qt-static-build/qtdeclarative/plugins/qmltooling/libqmldbg_local.a
/home/nuc/dev/qt-static-build/qtdeclarative/plugins/qmltooling/libqmldbg_messages.a
/home/nuc/dev/qt-static-build/qtdeclarative/plugins/qmltooling/libqmldbg_native.a
/home/nuc/dev/qt-static-build/qtdeclarative/plugins/qmltooling/libqmldbg_nativedebugger.a
/home/nuc/dev/qt-static-build/qtdeclarative/plugins/qmltooling/libqmldbg_preview.a
/home/nuc/dev/qt-static-build/qtdeclarative/plugins/qmltooling/libqmldbg_profiler.a
/home/nuc/dev/qt-static-build/qtdeclarative/plugins/qmltooling/libqmldbg_quickprofiler.a
/home/nuc/dev/qt-static-build/qtdeclarative/plugins/qmltooling/libqmldbg_server.a
/home/nuc/dev/qt-static-build/qtdeclarative/lib/libQt5PacketProtocol.a
/home/nuc/dev/qt-static-build/qtdeclarative/plugins/qmltooling/libqmldbg_tcp.a
/home/nuc/dev/qt-static-build/qtbase/plugins/bearer/libqconnmanbearer.a
/home/nuc/dev/qt-static-build/qtbase/plugins/bearer/libqgenericbearer.a
/home/nuc/dev/qt-static-build/qtbase/plugins/bearer/libqnmbearer.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5DBus.a
-ldbus-1
/home/nuc/dev/qt-static-build/qtdeclarative/qml/QtQml/libqmlplugin.a
/home/nuc/dev/qt-static-build/qtquickcontrols2/qml/QtQuick/Templates.2/libqtquicktemplates2plugin.a
/home/nuc/dev/qt-static-build/qtdeclarative/qml/QtQml/Models.2/libmodelsplugin.a
/home/nuc/dev/qt-static-build/qtdeclarative/qml/QtQml/WorkerScript.2/libworkerscriptplugin.a
/home/nuc/dev/qt-static-build/qtdeclarative/qml/QtQuick/Window.2/libwindowplugin.a
/home/nuc/dev/qt-static-build/qtdeclarative/qml/QtQuick.2/libqtquick2plugin.a
/home/nuc/dev/qt-static-build/qtdeclarative/lib/libQt5QmlWorkerScript.a
/home/nuc/dev/qt-static-build/qtdeclarative/qml/QtQuick/Layouts/libqquicklayoutsplugin.a
/home/nuc/dev/qt-static-build/qtquickcontrols2/qml/QtQuick/Controls.2/Material/libqtquickcontrols2materialstyleplugin.a
/home/nuc/dev/qt-static-build/qtquickcontrols2/qml/QtQuick/Controls.2/Universal/libqtquickcontrols2universalstyleplugin.a
/home/nuc/dev/qt-static-build/qtdeclarative/qml/Qt/labs/settings/libqmlsettingsplugin.a
/home/nuc/dev/qt-static-build/qtquickcontrols2/qml/QtQuick/Controls.2/libqtquickcontrols2plugin.a
/home/nuc/dev/qt-static-build/qtquickcontrols2/lib/libQt5QuickControls2.a
/home/nuc/dev/qt-static-build/qtquickcontrols2/lib/libQt5QuickTemplates2.a
/home/nuc/dev/qt-static-build/qtdeclarative/lib/libQt5Quick.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5Gui.a
-lpng16
-lharfbuzz
/home/nuc/dev/qt-static-build/qtdeclarative/lib/libQt5QmlModels.a
/home/nuc/dev/qt-static-build/qtdeclarative/lib/libQt5Qml.a
-lrt
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5Network.a
/home/nuc/dev/qt-static-build/qtbase/lib/libQt5Core.a
-lm
-lz
-licui18n
-licuuc
-licudata
-ldl
/home/nuc/dev/qt-static-build/qtbase/lib/libqtpcre2.a
-lgthread-2.0
-lglib-2.0
-lGL
-lpthread
OlivierLDff commented 3 years ago

I hope you will find, i have no idea where to start to look now because everything look fine to me. Why do you need static linkage on ubuntu? You could simply deploy everything in an AppImage for example.

TobyEalden commented 3 years ago

Why do you need static linkage on ubuntu? You could simply deploy everything in an AppImage for example.

Yeah, I suppose so - I just wanted it to be consistent across the platforms. I also tried it on an RPi 4 and the same thing happens - not surprising I guess.

I've posted a question to the Qt forum - https://forum.qt.io/topic/123037/strange-undefined-reference-link-errors-on-ubuntu-static-build.

Do you know exactly what https://doc.qt.io/qt-5/qtcore-cmake-qt5-import-plugins.html is for? The documentation is a bit vague - is it supposed to be doing what your cmake script does?

OlivierLDff commented 3 years ago

is it supposed to be doing what your cmake script does?

Yes it is doing the same as my script. qt5_import_plugins is quite new (5.14 i think). And it will only import stuff like Qt5::Svg, not stuff with import <Module> <Version> in qml files. You can find the implementation in Qt folder lib/cmake/SomeFileIForgotTheName.Cmake