Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qt5 + cmake doesn't seem to work at all #1642

Closed
uwehermann opened this issue Jan 22, 2017 · 43 comments · Fixed by #2453
Closed

Qt5 + cmake doesn't seem to work at all #1642

uwehermann opened this issue Jan 22, 2017 · 43 comments · Fixed by #2453
Labels

Comments

@uwehermann
Copy link
Contributor

TL;DR: MXE+Qt5+cmake doesn't seem to work.

Hi, I've been trying for quite a while to make sigrok (www.sigrok.org) Windows packages using Qt5 + MXE, without any success unfortunately (our current packages use Qt4, which has also been a challenge to implement as well, but that's somewhat working at least).

For our purposes we're depending on a number of specific things that need to work together:

  • MXE target "i686-w64-mingw32.static.posix" (we need C++11 + threads etc.)
    (and static builds of everything else in MXE and outside MXE, of course)
  • cmake (used by our PulseView frontend)
  • Qt5 (we cannot and don't want to remain stuck with Qt4 forever, for many different reasons, including features from Qt5 we want, and bugfixes from Qt5 we need)

Within Qt5 we need the following: Qt5Core, Qt5Gui, Qt5Svg and various static plugins (directly or indirectly) such as qsvg, QWindowsIntegrationPlugin and such.

I've spent countless days trying to get a successful build, but I didn't get anywhere near a successful build that will also work at runtime.

So my question is whether I'm doing something wrong or whether there are bugs in MXE e.g. regarding i686-w64-mingw32.static.posix+Qt5+cmake that would prevent this from working?

In order to get something reproducible that demonstrates the problem without too many dependencies on all kinds of other stuff we do in sigrok, I've created this demo repo here:

https://github.com/uwehermann/qt5helloworld

It contains a simple project that I generated in qtcreator on Linux which basically just shows an empty window. I added the simplest-possible CMakeLists.txt file for buiding it, and two shell scripts to demonstrate exactly how I'm building.

  • The Linux build script works fine, I get an executable and I can run the executable successfully.
  • The MXE script doesn't yield a successful build, there are many linker errors (this is with MXE git as of today, only "make qt5", no Qt4 in the MXE paths anywhere).

I've tried all kinds of things in CMakeLists.txt, the source code itself, random MXE patching, nothing has worked sufficiently well so far.

Can someone please verify that the repo I provided does indeed build fine on Linux and doesn't build with MXE?

If yes, any patches against MXE and/or that repo to make this simple project build and run successfully would be really appreciated. It would at least be a basis for further work (I'm pretty sure the static Qt5 plugins will be the next major issue causing headaches after that).

Please let me know if you need any more info. Thanks!

@tonytheodore
Copy link
Member

Can someone please verify that the repo I provided does indeed build fine on Linux and doesn't build with MXE?

Static Qt/Cmake has been a long term issue, the helloworld has a whole bunch of linking errors.

It's not a real solution, but you can add some helpers using pkg-config:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8858e19..2dc780e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,5 +6,10 @@ set(CMAKE_AUTOUIC ON)
 find_package(Qt5Widgets REQUIRED)
 find_package(Qt5Gui REQUIRED)
 find_package(Qt5Svg REQUIRED)
+
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(QT5SVG Qt5Svg)
+link_directories(${QT5SVG_LIBRARY_DIRS})
+
 add_executable(qt5helloworld WIN32 main.cpp mainwindow.cpp)
-target_link_libraries(qt5helloworld Qt5::Widgets Qt5::Gui Qt5::Svg)
+target_link_libraries(qt5helloworld Qt5::Widgets Qt5::Gui Qt5::Svg ${QT5SVG_LIBRARIES})

@tonytheodore
Copy link
Member

tonytheodore commented Jan 22, 2017

It doesn't run however, neither does test-qtbase-pkgconfig.exe. Both are missing the windows platform plugin - not sure how to fix that.

@tonytheodore
Copy link
Member

I guess the next thing to try is compare the makefiles generated by qmake to see how it links the platform plugins.

@tonytheodore
Copy link
Member

Okay, this runs:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8858e19..14779e8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,5 +6,16 @@ set(CMAKE_AUTOUIC ON)
 find_package(Qt5Widgets REQUIRED)
 find_package(Qt5Gui REQUIRED)
 find_package(Qt5Svg REQUIRED)
+
+foreach(plugin ${Qt5Gui_PLUGINS})
+  get_target_property(_loc ${plugin} LOCATION)
+  message("Plugin ${plugin} is at location ${_loc}")
+  set(plugin_libs ${plugin_libs} ${_loc})
+endforeach()
+
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(QT5SVG Qt5Svg)
+link_directories(${QT5SVG_LIBRARY_DIRS})
+
 add_executable(qt5helloworld WIN32 main.cpp mainwindow.cpp)
-target_link_libraries(qt5helloworld Qt5::Widgets Qt5::Gui Qt5::Svg)
+target_link_libraries(qt5helloworld Qt5::Widgets Qt5::Gui Qt5::Svg ${plugin_libs} -lQt5PlatformSupport ${QT5SVG_LIBRARIES} )
diff --git a/main.cpp b/main.cpp
index b48f94e..2b246bc 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,6 +1,9 @@
 #include "mainwindow.h"
 #include <QApplication>
 
+#include <QtPlugin>
+Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
+
 int main(int argc, char *argv[])
 {
     QApplication a(argc, argv);

qmake creates a file *_plugin_import.cpp which has:

// This file is autogenerated by qmake. It imports static plugin classes for
// static plugins specified using QTPLUGIN and QT_PLUGIN_CLASS.<plugin> variables.
#include <QtPlugin>
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
Q_IMPORT_PLUGIN(QICOPlugin)
Q_IMPORT_PLUGIN(QGenericEnginePlugin)
Q_IMPORT_PLUGIN(QNativeWifiEnginePlugin)
Q_IMPORT_PLUGIN(QSQLiteDriverPlugin)
Q_IMPORT_PLUGIN(QMYSQLDriverPlugin)
...etc

You should be able to use some of the introspection features of cmake to get the actual plugins you need and link them in order, possibly with some manual ones -lQt5PlatformSupport.

tonytheodore added a commit to tonytheodore/mxe that referenced this issue Jan 23, 2017
tested on i686-w64-mingw32.shared i686-w64-mingw32.static

minimal example for mxe#1642
@tonytheodore
Copy link
Member

@uwehermann I've added a minimal test build https://github.com/mxe/mxe/pull/1645/files. I haven't tested with *posix, but that should help narrow it down. The key steps seem to be:

  • using Q_IMPORT_PLUGIN(QFooPlugin) macro
  • adding Qt5::QFooPlugin to target_link_libraries (better to list only the ones actually used)
  • using pkg-config to add missing static dependency libs (maybe adding some manually)

Is the Linux build a static build?

@avih
Copy link
Contributor

avih commented Jan 23, 2017

@tonytheodore thanks for pointing me here. So should it be possible to work around it with some CMakeFiles.txt changes (listed just above this comment)? or should it be possible after more MXE changes e.g. to qtbase.mk (such as the pending PR #1645 does)?

@tonytheodore
Copy link
Member

@avih #1645 is just an example and doesn't affect any functionality. The changes mentioned above are a starting point for a "smallish" projects, but larger projects (quassel, sigrok) would probably need a fair amount of work to build and maintain.

Ideally, qt5 should be patched so the supplied cmake modules are aware of static dependencies, but I can't see there is really even a starting point for that in the way the files are generated.

@tonytheodore
Copy link
Member

@avih see 9cb27ce for a real example of getting it to work in a smaller project.

@avih
Copy link
Contributor

avih commented Jan 23, 2017

@tonytheodore thanks. I feel that this is way over my head (I know very little about Qt and cmake), but after some messing about with CMakeList.txt as well as editing generated cmake files (specifically src/CMakeFiles/quasselclient.dir/linklibs.rsp at the build dir), I managed to build quassel-client and get an executable, which displays this message when launched:

---------------------------
quassel
---------------------------
This application failed to start because it could not find or load the Qt platform plugin "windows"
in "".

Reinstalling the application may fix this problem.
---------------------------
OK   
---------------------------

Which feels to me somewhat related to what #1645 does - possibly related to libqwindows.a, though i also linked it manually (at /i686-w64-mingw32.static/qt5/plugins/platforms) and I still get the same message.

But anyway, it's probably a waste of time, as I assume it would build successfully when linking dynamically. If you even manage to build quassel client statically, ping me ;) (I can build it on windows using the mingw qt sdk).

@mabrand
Copy link
Member

mabrand commented Jan 23, 2017

Have you looked at the information about static plugins here?
http://doc.qt.io/qt-5/plugins-howto.html
Qmake does most of the work. I haven't looked at cmake for a long time, but I wouldn't be surprised if you have to take care of details of static plugin linking yourself if you are not using qmake.

@uwehermann
Copy link
Contributor Author

Alright, thanks for the hints, I've been playing around a bit more and found this to be the minimal set of changes to get my test application linked (and the executable also runs fine on Windows):

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8858e19..2d22773 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,8 +3,14 @@ project(qt5helloworld)
 set(CMAKE_AUTOMOC ON)
 set(CMAKE_AUTORCC ON)
 set(CMAKE_AUTOUIC ON)
+find_package(PkgConfig REQUIRED)
 find_package(Qt5Widgets REQUIRED)
 find_package(Qt5Gui REQUIRED)
 find_package(Qt5Svg REQUIRED)
 add_executable(qt5helloworld WIN32 main.cpp mainwindow.cpp)
-target_link_libraries(qt5helloworld Qt5::Widgets Qt5::Gui Qt5::Svg)
+pkg_check_modules(QT5ALL Qt5Widgets Qt5Gui Qt5Svg)
+foreach(plugin ${Qt5Widgets_PLUGINS} ${Qt5Gui_PLUGINS} ${Qt5Svg_PLUGINS})
+  get_target_property(_loc ${plugin} LOCATION)
+  set(plugin_libs ${plugin_libs} ${_loc})
+endforeach()
+target_link_libraries(qt5helloworld Qt5::Widgets Qt5::Gui Qt5::Svg Qt5::QWindowsIntegrationPlugin -lQt5PlatformSupport ${QT5ALL_LDFLAGS})
diff --git a/main.cpp b/main.cpp
index b48f94e..2b246bc 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,6 +1,9 @@
 #include "mainwindow.h"
 #include <QApplication>

+#include <QtPlugin>
+Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
+
 int main(int argc, char *argv[])
 {
     QApplication a(argc, argv);

Note the use of the _LDFLAGS variable there, which resolves some more issues compared to just _LIBRARIES, it seems.

I'll see if I can use this method to get a working sigrok build and report back. It's somewhat of a hack to (ab)use pkg-config instead of using the cmake facilities of course, but it's certainly a good thing to have a workaround at least for the time being.

@tonytheodore
Copy link
Member

*_LDFLAGS sets the -L... flags also if you aren't using link_directories(${*_LIBRARY_DIRS}). You also don't need the plugin_libs loop if you are setting Qt5::Q*Plugin explicitly in target_link_libraries.

It's somewhat of a hack to (ab)use pkg-config instead of using the cmake facilities of course

Indeed, but I can't find any built-in cmake facilities for this - does the static build work on Linux?

@tonytheodore
Copy link
Member

To get minimal Pulseview built:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ee58ce2..d21b957 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -81,6 +81,7 @@ if(FORCE_QT4)
 	set(Qt5Core_FOUND FALSE)
 else()
 	find_package(Qt5Core QUIET)
+	pkg_check_modules(QT5ALL REQUIRED Qt5Widgets Qt5Gui Qt5Svg)
 endif()
 
 if(Qt5Core_FOUND)
@@ -460,9 +461,7 @@ if(WIN32)
 	# On Windows we need to statically link the libqsvg imageformat
 	# plugin (and the QtSvg component) for SVG graphics/icons to work.
 	add_definitions(-DQT_STATICPLUGIN)
-	link_directories("${QT_PLUGINS_DIR}/imageformats")
-	list(APPEND PULSEVIEW_LINK_LIBS "-lqsvg")
-	list(APPEND PULSEVIEW_LINK_LIBS ${QT_QTSVG_LIBRARY})
+	list(APPEND PULSEVIEW_LINK_LIBS Qt5::QSvgPlugin)
 endif()
 
 if(ANDROID)
@@ -490,6 +489,7 @@ target_link_libraries(${PROJECT_NAME} ${PULSEVIEW_LINK_LIBS})
 if(WIN32)
 	# Pass -mwindows so that no "DOS box" opens when PulseView is started.
 	set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-mwindows")
+	target_link_libraries(${PROJECT_NAME} Qt5::QWindowsIntegrationPlugin -lQt5PlatformSupport ${QT5ALL_LDFLAGS})
 endif()
 
 #===============================================================================
diff --git a/main.cpp b/main.cpp
index 0396706..1041e85 100644
--- a/main.cpp
+++ b/main.cpp
@@ -46,7 +46,8 @@
 #ifdef _WIN32
 // The static qsvg lib is required for SVG graphics/icons (on Windows).
 #include <QtPlugin>
-Q_IMPORT_PLUGIN(qsvg)
+Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
+Q_IMPORT_PLUGIN(QSvgPlugin)
 #endif
 
 void usage()

Use the mxe cmake wrapper:

i686-w64-mingw32.static.posix-cmake \
    -DENABLE_DECODE=OFF \
    -DENABLE_SIGNALS=OFF \
    -DENABLE_TESTS=OFF \
    -DDISABLE_WERROR=ON \
    -DSTATIC_PKGDEPS_LIBS=ON \
    <path to git repo>

open app and click around:
image

@uwehermann
Copy link
Contributor Author

Nice, thanks! Will test the last one ASAP.
You're right, the loop was indeed no longer needed, forgot to drop it there.
The Linux build was not a static build, thinko on my side, sorry.

@tonytheodore
Copy link
Member

With updated #1645, pkg-config libs are automatically included so the only changes required are for plugins:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ee58ce2..fc555d6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -460,9 +460,7 @@ if(WIN32)
 	# On Windows we need to statically link the libqsvg imageformat
 	# plugin (and the QtSvg component) for SVG graphics/icons to work.
 	add_definitions(-DQT_STATICPLUGIN)
-	link_directories("${QT_PLUGINS_DIR}/imageformats")
-	list(APPEND PULSEVIEW_LINK_LIBS "-lqsvg")
-	list(APPEND PULSEVIEW_LINK_LIBS ${QT_QTSVG_LIBRARY})
+	list(INSERT PULSEVIEW_LINK_LIBS 0 Qt5::QSvgPlugin)
 endif()
 
 if(ANDROID)
@@ -490,6 +488,7 @@ target_link_libraries(${PROJECT_NAME} ${PULSEVIEW_LINK_LIBS})
 if(WIN32)
 	# Pass -mwindows so that no "DOS box" opens when PulseView is started.
 	set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-mwindows")
+	target_link_libraries(${PROJECT_NAME} Qt5::QWindowsIntegrationPlugin -lQt5PlatformSupport)
 endif()
 
 #===============================================================================
diff --git a/main.cpp b/main.cpp
index 0396706..fef6f6f 100644
--- a/main.cpp
+++ b/main.cpp
@@ -43,10 +43,11 @@
 
 #include "config.h"
 
-#ifdef _WIN32
+#if defined(_WIN32) && defined(QT_STATICPLUGIN)
 // The static qsvg lib is required for SVG graphics/icons (on Windows).
 #include <QtPlugin>
-Q_IMPORT_PLUGIN(qsvg)
+Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
+Q_IMPORT_PLUGIN(QSvgPlugin)
 #endif
 
 void usage()

@uwehermann
Copy link
Contributor Author

Thanks, gave the last patch a test-run after building a completely fresh MXE from scratch as of today. Still getting a bunch of linker errors, but I'll look into it in more detail in a bit.

@tonytheodore
Copy link
Member

The last patch needs #1645 to be merged, use the previous one until then.

@uwehermann
Copy link
Contributor Author

I had already tried the previous patch, yielded linker errors here too.

FWIW, I'm running a minimally modified sigrok-cross-mingw script, something like this:

diff --git a/cross-compile/mingw/sigrok-cross-mingw b/cross-compile/mingw/sigrok-cross-mingw
index 8465f4a..312affc 100755
--- a/cross-compile/mingw/sigrok-cross-mingw
+++ b/cross-compile/mingw/sigrok-cross-mingw
@@ -57,10 +57,11 @@ export PATH=$MXE/usr/bin:$PATH

 TOOLCHAIN_TRIPLET="$TARGET-w64-mingw32.static.posix"

+CMAKE="$TOOLCHAIN_TRIPLET-cmake"
+
 P="$PREFIX/lib/pkgconfig"
 P2="$MXE/usr/$TOOLCHAIN_TRIPLET/lib/pkgconfig"
 C="--host=$TOOLCHAIN_TRIPLET --prefix=$PREFIX CPPFLAGS=-D__printf__=__gnu_printf__"
-CM="-DCMAKE_TOOLCHAIN_FILE=$MXE/usr/$TOOLCHAIN_TRIPLET/share/cmake/mxe-conf.cmake"
 L="--disable-shared --enable-static"

 if [ $TARGET = "i686" ]; then
@@ -196,11 +197,12 @@ cd ..
 # PulseView
 $GIT_CLONE git://sigrok.org/pulseview
 cd pulseview
+patch -p1 < ../../x.patch
 if [ $DEBUG = 1 ]; then
        # Allow a "DOS box" to open on Windows, it'll contain logging output.
        patch -p1 < ../../pv_mwindows.patch
 fi
-cmake $CM -DCMAKE_INSTALL_PREFIX:PATH=$PREFIX -DDISABLE_WERROR=y -DENABLE_TESTS=y .
+$CMAKE -DCMAKE_INSTALL_PREFIX:PATH=$PREFIX -DDISABLE_WERROR=y -DENABLE_TESTS=y .
 make $PARALLEL $V
 if [ $DEBUG = 1 ]; then
        make install $V

(x.patch being one of your patches above)

I tried with just "cmake" and "-DCMAKE_TOOLCHAIN_FILE=..." as well as with using "i686-w64-mingw32.static.posix-cmake", doesn't seem to make a difference.

@tonytheodore
Copy link
Member

Could you post the log? I'm building it as an mxe plugin and can't replicate (see log). I don't think it matters, but I'm also using a minimal libsigrok with these options:

        --enable-cxx \
        --disable-python \
        --disable-ruby \
        --disable-java \
        --without-libserialport \
        --without-libftdi \
        --without-libusb \
        --without-librevisa \
        --without-libgpib \
        --without-libieee1284

and none of the other libs in sigrok-cross-mingw.

@uwehermann
Copy link
Contributor Author

Yeah, shouldn't make a difference in theory, but it depends on what you built inside of MXE, I think. libsigrok's configure will simply not build optional stuff if the requirements are not found, so all the above switches are optional theoretically.

For reference, here's how I build fresh MXE instances (for qt5 only):

make JOBS=4 -j4 MXE_TARGETS=i686-w64-mingw32.static.posix gcc glib \
  libzip libusb1 libftdi1 glibmm qt5 boost check

Will upload a log in a few minutes.

@uwehermann
Copy link
Contributor Author

Log: http://pastebin.com/S7hHkuXM

@uwehermann
Copy link
Contributor Author

(this was with your previous patch and mine for sigrok-cross-mingw, see above)

@tonytheodore
Copy link
Member

Okay, with the script I can see the bzip2 linking errors. This is caused by python installing a bz2.lib that conflicts with the mxe one and for the life of me I can't find an easy way to get cmake to prefer system libs that doesn't also break the modified libusb.

Just removing the file will let the build succeed without any Qt5 issues (using your script changes, #1645 and the last pulseview changes):

diff --git a/cross-compile/mingw/sigrok-cross-mingw b/cross-compile/mingw/sigrok-cross-mingw
index 8465f4a..3d0fed3 100755
--- a/cross-compile/mingw/sigrok-cross-mingw
+++ b/cross-compile/mingw/sigrok-cross-mingw
@@ -92,6 +92,7 @@ mkdir -p $PREFIX
 # and c:\Python32\include have been stored in the Python32_*.tar.gz tarball.
 $WGET http://www.sigrok.org/tmp/Python32_$TARGET.tar.gz -O $PREFIX/Python32.tar.gz
 tar xzf $PREFIX/Python32.tar.gz -C $PREFIX
+rm $PREFIX/Python32/libs/*bz2*

 # Create a dummy python3.pc file so that pkg-config finds Python 3.
 mkdir -p $PREFIX/lib/pkgconfig

I also skipped the makensis steps, full log here: https://gist.github.com/tonytheodore/f6a28caecc1d8680b63d20464c606d16

@tonytheodore
Copy link
Member

I've added support for correct ordering of plugins to #1645 and now the following works:

diff --git a/cross-compile/mingw/sigrok-cross-mingw b/cross-compile/mingw/sigrok-cross-mingw
index 8465f4a..27120f7 100755
--- a/cross-compile/mingw/sigrok-cross-mingw
+++ b/cross-compile/mingw/sigrok-cross-mingw
@@ -57,10 +57,11 @@ export PATH=$MXE/usr/bin:$PATH
 
 TOOLCHAIN_TRIPLET="$TARGET-w64-mingw32.static.posix"
 
+CMAKE="$TOOLCHAIN_TRIPLET-cmake"
+
 P="$PREFIX/lib/pkgconfig"
 P2="$MXE/usr/$TOOLCHAIN_TRIPLET/lib/pkgconfig"
 C="--host=$TOOLCHAIN_TRIPLET --prefix=$PREFIX CPPFLAGS=-D__printf__=__gnu_printf__"
-CM="-DCMAKE_TOOLCHAIN_FILE=$MXE/usr/$TOOLCHAIN_TRIPLET/share/cmake/mxe-conf.cmake"
 L="--disable-shared --enable-static"
 
 if [ $TARGET = "i686" ]; then
@@ -103,7 +104,7 @@ includedir=\${prefix}/include
 Name: Python
 Description: Python library
 Version: 3.2
-Libs: -L$PREFIX/Python32/libs -lpython32
+Libs: $PREFIX/Python32/libs/libpython32.a
 Cflags: -I$PREFIX/Python32/include
 EOF
 
@@ -196,11 +197,12 @@ cd ..
 # PulseView
 $GIT_CLONE git://sigrok.org/pulseview
 cd pulseview
+patch -p1 < ../../x.patch
 if [ $DEBUG = 1 ]; then
 	# Allow a "DOS box" to open on Windows, it'll contain logging output.
 	patch -p1 < ../../pv_mwindows.patch
 fi
-cmake $CM -DCMAKE_INSTALL_PREFIX:PATH=$PREFIX -DDISABLE_WERROR=y -DENABLE_TESTS=y .
+$CMAKE -DCMAKE_INSTALL_PREFIX:PATH=$PREFIX -DDISABLE_WERROR=y -DENABLE_TESTS=y .
 make $PARALLEL $V
 if [ $DEBUG = 1 ]; then
 	make install $V

Pulseview changes (x.patch):

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ee58ce2..2fd4636 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -446,7 +446,7 @@ set(PULSEVIEW_LINK_LIBS
 
 if(STATIC_PKGDEPS_LIBS)
    link_directories(${PKGDEPS_STATIC_LIBRARY_DIRS})
-   list(APPEND PULSEVIEW_LINK_LIBS ${PKGDEPS_STATIC_LIBRARIES})
+   list(APPEND PULSEVIEW_LINK_LIBS ${PKGDEPS_STATIC_LDFLAGS})
 if(WIN32)
    # Workaround for a MinGW linking issue.
    list(APPEND PULSEVIEW_LINK_LIBS "-llzma -llcms2")
@@ -460,9 +460,13 @@ if(WIN32)
    # On Windows we need to statically link the libqsvg imageformat
    # plugin (and the QtSvg component) for SVG graphics/icons to work.
    add_definitions(-DQT_STATICPLUGIN)
-   link_directories("${QT_PLUGINS_DIR}/imageformats")
-   list(APPEND PULSEVIEW_LINK_LIBS "-lqsvg")
-   list(APPEND PULSEVIEW_LINK_LIBS ${QT_QTSVG_LIBRARY})
+   if(Qt5Core_FOUND)
+        list(APPEND PULSEVIEW_LINK_LIBS Qt5::QWindowsIntegrationPlugin Qt5::QSvgPlugin)
+    else()
+        link_directories("${QT_PLUGINS_DIR}/imageformats")
+        list(APPEND PULSEVIEW_LINK_LIBS "-lqsvg")
+        list(APPEND PULSEVIEW_LINK_LIBS ${QT_QTSVG_LIBRARY})
+    endif()
 endif()
 
 if(ANDROID)
diff --git a/main.cpp b/main.cpp
index 0396706..53c6343 100644
--- a/main.cpp
+++ b/main.cpp
@@ -43,11 +43,16 @@
 
 #include "config.h"
 
-#ifdef _WIN32
+#if defined(_WIN32) && defined(QT_STATICPLUGIN)
 // The static qsvg lib is required for SVG graphics/icons (on Windows).
 #include <QtPlugin>
+#if QT_VERSION >= 0x050000
+Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
+Q_IMPORT_PLUGIN(QSvgPlugin)
+#else
 Q_IMPORT_PLUGIN(qsvg)
 #endif
+#endif
 
 void usage()
 {

Setting Libs: $PREFIX/Python32/libs/libpython32.a and ${PKGDEPS_STATIC_LDFLAGS} fixes the bz2 issues, the rest is pretty straightforward (hopefully).

@tonytheodore
Copy link
Member

@avih, the following changes and build command work, it's mostly a matter of:

  • adding Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin) to some source file
  • adding Qt5::QWindowsIntegrationPlugin to target_link_libraries
i686-w64-mingw32.static-cmake \
    -DWITH_KDE=OFF \
    -DWITH_WEBENGINE=OFF \
    -DSTATIC=ON \
    -DUSE_QT5=ON \
    -DCMAKE_BUILD_TYPE=Release \
    -DWANT_CORE=OFF \
    -DWANT_QTCLIENT=ON \
    -DWANT_MONO=OFF
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 96b66af..bc51643 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -14,7 +14,7 @@ if(BUILD_GUI)
   include_directories(BEFORE uisupport)
   include_directories(BEFORE qtui)
 
-  if(STATIC)
+  if(STATIC_IMAGE_FORMAT_PLUGINS) # mxe has these as builtins
     link_directories(${QT_PLUGINS_DIR}/imageformats)
     set(CLIENT_LIBRARIES ${CLIENT_LIBRARIES} qjpeg qgif)
   endif()
diff --git a/src/common/quassel.h b/src/common/quassel.h
index e9ed0f9..4f5d58f 100644
--- a/src/common/quassel.h
+++ b/src/common/quassel.h
@@ -25,6 +25,11 @@
 #include <QLocale>
 #include <QString>
 
+#include <QtPlugin>
+#if QT_VERSION >= 0x050000
+Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
+#endif
+
 #include "abstractcliparser.h"
 
 class QFile;
diff --git a/src/qtui/CMakeLists.txt b/src/qtui/CMakeLists.txt
index 5fee3df..bef653d 100644
--- a/src/qtui/CMakeLists.txt
+++ b/src/qtui/CMakeLists.txt
@@ -211,4 +211,4 @@ endif()
 add_library(mod_qtui STATIC ${SOURCES} ${SPSRC} ${UI})
 qt_use_modules(mod_qtui Core Gui Network ${QT_MODULES})
 
-target_link_libraries(mod_qtui mod_client mod_common mod_uisupport ${LIBS})
+target_link_libraries(mod_qtui mod_client mod_common mod_uisupport ${LIBS} Qt5::QWindowsIntegrationPlugin)

image

@avih
Copy link
Contributor

avih commented Jan 29, 2017

@tonytheodore thanks! and nice :)

Does it also require something from #1645 ?

[edit]
Without applying #1645 (or rebuilding qt5), but after applying your quassel patches above and using your cmake args (mine were pretty similar too), it completes compiling all the files but fails to link quasselclient.exe - I'm getting tons of undefined references. They seem to refer to freetype, harfbuzz, png, jpeg, bz2, ws2_32, and more.

This is hopefully unrelated, but still worth noting that I enabled subpixel antialiasing for freetype (ft disables it by default), and added harfbuzz for freetype (at freetype.mk), and also fixed an issue in Qt5 where freetype on windows effectively always used gray antialiasing - combined it results in Qt5 apps which can use freetype with subpixel antialiasing, and which work fine for qmake based (MXE, qt5, static) builds.

(I'll probably PR the freetype subpixel AA config and the Qt5 freetype fix - once I can put everything together and confirm it also works for static cmake builds - again, it already works fine for static qmake builds).

@uwehermann
Copy link
Contributor Author

Thanks for all the help! I've finally committed a set of patches which work for me with the current setup. Full details:

Some of the remaining linker errors (other than the bz2 stuff) were related to the PulseView unit tests, which can be fixed by giving them the same link libs explicitly or implicitly.

@tonytheodore
Copy link
Member

@uwehermann, good to hear you got it working - some parts of this made me question whether I understand linking at all!

Unfortunately, it will break with the update to Qt 5.8(#1650). The Qt5PlatformSupport lib seems to have been modularised into Qt5EventDispatcherSupport Qt5AccessibilitySupport Qt5FontDatabaseSupport Qt5ThemeSupport...

@avih the anti-aliasing support sounds like a great feature for windows users. If you have the time, can you get it to work with qmake 5.8 instead of cmake?

It's pretty clear now that cmake needs to be at parity with qmake, I'm reasonably sure I can do that but getting it upstream may be a challenge.

@avih
Copy link
Contributor

avih commented Feb 1, 2017

@avih the anti-aliasing support sounds like a great feature for windows users. If you have the time, can you get it to work with qmake 5.8 instead of cmake?

The patches are for freetype (config) and Qt (fix), and are unrelated to cmake or qmake, and they already work fine for qmake based projects in MXE. My original Qt patch was for 5.7.1 but it was trivial to rebase it to 5.8. I'll PR those at some point.

I also have another related patch which allow env vars override for freetype rendering parameters in Qt (hintstyle and lcdfilter. while subpixel order was already supported previously in Qt with QT_SUBPIXEL_AA_TYPE). This is because Qt doesn't necessarily consider fontconfig correctly on Windows, and this was a small and easy enough patch instead of understanding how Qt interacts with fontconfig+freetype on Windows and possibly fixing it, and also allows controlling this even if fontconfig was not enabled for Qt.

Changing the hintstyle to none/slight in Qt (defaults to full on Windows, none elsewhere) also has the additional benefit of enabling subpixel positioning in Qt (it's an automatic Qt thing), which really unlocks the full potential of text rendering in Qt.

I'll also PR enabling hintslight by default on windows and/or these env vars overrides.

Note that by default freetype is not used on windows (and so none of the above applies by default when running a Qt app), but one could enable it via qt.conf at the same dir as the exe.

It's pretty clear now that cmake needs to be at parity with qmake, I'm reasonably sure I can do that but getting it upstream may be a challenge.

MXE would be a start. You're referring to #1645, yes? It's still not clear to me if your quassel build instructions require #1645 first, and I'm assuming yes (do correct me if I'm wrong), but it doesn't apply anymore to Qt 5.8, and I didn't try it with 5.7.1.

@tonytheodore
Copy link
Member

quassel build instructions require #1645 first, and I'm assuming yes

Yes, the build did require #1645 but the approach of using pkg-config to supplement cmake is too flaky in the face of qt changes. For example, in 5.8, the pkg-config file for Qt5Sql no longer returns the base sql libraries (-lpq -lsybdb etc.) and their dependencies.

These have been moved to plugins and the pkg-config files have no awareness of plugins. The cmake modules are aware of plugins, but only at a single level and don't have awareness of the intermediate libraries (Qt5EventDispatcherSupport Qt5AccessibilitySupport Qt5FontDatabaseSupport Qt5ThemeSupport etc.) and their transitive deps.

All the required metadata is in the qmake prl and pri files, it's "simply" a matter of processing these in a robust way;)

zavorka pushed a commit to zavorka/pulseview that referenced this issue Feb 3, 2017
We currently need to (ab)use pkg-config to get all the required
Qt5 static linking dependencies right, since this doesn't yet
work properly in MXE's cmake.

We use ${PKGDEPS_STATIC_LDFLAGS} instead of ${PKGDEPS_STATIC_LIBRARIES}
to avoid some linker issues related to libbz2.

We need to add Qt5::QSvgPlugin, Qt5::QWindowsIntegrationPlugin,
Qt5PlatformSupport and all the Qt5 libs and their dependencies to
the link libraries list (for both PulseView and the unit tests).

In one of the source code files we need to explicitly list all
static Qt plugins via Q_IMPORT_PLUGIN to make static builds work,
which is currently QWindowsIntegrationPlugin and QSvgPlugin.

We're only focusing on having a working Qt5 build for Windows,
as we no longer need to or want to support Qt4 there.

Details:
mxe/mxe#1642

Thanks to Tony Theodore for the help!

This should also fix bug #871, since we're now building with Qt >= 5.6
which has high-DPI support in general.

Tested via manual specification (might need further changes, though):

  set QT_SCALE_FACTOR=2
  pulseview.exe
asanza pushed a commit to asanza/pulseview that referenced this issue Feb 8, 2017
We currently need to (ab)use pkg-config to get all the required
Qt5 static linking dependencies right, since this doesn't yet
work properly in MXE's cmake.

We use ${PKGDEPS_STATIC_LDFLAGS} instead of ${PKGDEPS_STATIC_LIBRARIES}
to avoid some linker issues related to libbz2.

We need to add Qt5::QSvgPlugin, Qt5::QWindowsIntegrationPlugin,
Qt5PlatformSupport and all the Qt5 libs and their dependencies to
the link libraries list (for both PulseView and the unit tests).

In one of the source code files we need to explicitly list all
static Qt plugins via Q_IMPORT_PLUGIN to make static builds work,
which is currently QWindowsIntegrationPlugin and QSvgPlugin.

We're only focusing on having a working Qt5 build for Windows,
as we no longer need to or want to support Qt4 there.

Details:
mxe/mxe#1642

Thanks to Tony Theodore for the help!

This should also fix bug #871, since we're now building with Qt >= 5.6
which has high-DPI support in general.

Tested via manual specification (might need further changes, though):

  set QT_SCALE_FACTOR=2
  pulseview.exe
uwehermann added a commit to uwehermann/sigrok-util that referenced this issue Feb 17, 2017
This avoids a libbz2 linking issue later on in the PulseView build.

Details:
mxe/mxe#1642

Thanks to Tony Theodore for the help!
@juzzlin
Copy link
Contributor

juzzlin commented Jul 12, 2018

After going through the discussion here I'm now linking my app like this:

target_link_libraries(${BINARY_NAME} Qt5::Widgets Qt5::Xml Qt5::QWindowsIntegrationPlugin)

But I get a lot of stuff like this:


/opt/mxe/usr/i686-w64-mingw32.static/qt5/plugins/platforms/libqwindows.a(qwindowsintegration.o):qwindowsintegration.cpp:(.text+0xcd): undefined reference to `QWindowsFontDatabase::QWindowsFontDatabase()'
/opt/mxe/usr/i686-w64-mingw32.static/qt5/plugins/platforms/libqwindows.a(qwindowsintegration.o):qwindowsintegration.cpp:(.text+0xf1): undefined reference to `vtable for QWindowsFontDatabaseFT'
/opt/mxe/usr/i686-w64-mingw32.static/qt5/plugins/platforms/libqwindows.a(qwindowsintegration.o):qwindowsintegration.cpp:(.text+0x151): undefined reference to `QWindowsFontDatabase::fontSmoothingGamma()'
/opt/mxe/usr/i686-w64-mingw32.static/qt5/plugins/platforms/libqwindows.a(qwindowsintegration.o):qwindowsintegration.cpp:(.text+0x2fc): undefined reference to `QWindowsGuiEventDispatcher::QWindowsGuiEventDispatcher(QObject*)'
/opt/mxe/usr/i686-w64-mingw32.static/qt5/plugins/platforms/libqwindows.a(qwindowsintegration.o):qwindowsintegration.cpp:(.text+0x1ce6): undefined reference to `QWindowsFontDatabase::setFontOptions(unsigned int)'
/opt/mxe/usr/i686-w64-mingw32.static/qt5/plugins/platforms
...

I also have:

#include <QtPlugin>
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)

And

add_definitions(-DQT_STATICPLUGIN)

Am I still missing something?

@tonytheodore
Copy link
Member

That's roughly where I got stuck last time - the cmake modules seem to have no support for the intermediate libraries and their dependencies (Qt5EventDispatcherSupport Qt5AccessibilitySupport Qt5FontDatabaseSupport Qt5ThemeSupport etc.)

To make it work manually, you can browse for likely libs:

$ find usr/i686-w64-mingw32.static/qt5 -name *Support.a
usr/i686-w64-mingw32.static/qt5/lib/libQt5EdidSupport.a
usr/i686-w64-mingw32.static/qt5/lib/libQt5FontDatabaseSupport.a
usr/i686-w64-mingw32.static/qt5/lib/libQt5DeviceDiscoverySupport.a
usr/i686-w64-mingw32.static/qt5/lib/libQt5ThemeSupport.a
usr/i686-w64-mingw32.static/qt5/lib/libQt5EventDispatcherSupport.a
usr/i686-w64-mingw32.static/qt5/lib/libQt5AccessibilitySupport.a
usr/i686-w64-mingw32.static/qt5/lib/libQt5PrintSupport.a
usr/i686-w64-mingw32.static/qt5/lib/libQt5PlatformCompositorSupport.a
usr/i686-w64-mingw32.static/qt5/lib/libQt5FbSupport.a
usr/i686-w64-mingw32.static/qt5/lib/libQt5WindowsUIAutomationSupport.a

or grep through qmake's .pri/.prl files:

$ grep FontDatabase -r usr/i686-w64-mingw32.static/qt5/ --include *.pr*
usr/i686-w64-mingw32.static/qt5//plugins/platforms/qoffscreen.prl:QMAKE_PRL_LIBS = -L$$[QT_INSTALL_LIBS] $$[QT_INSTALL_LIBS]/libQt5EventDispatcherSupport.a -L/Users/tonyt/dev/mxe/usr/i686-w64-mingw32.static/lib/../lib $$[QT_INSTALL_LIBS]/libQt5FontDatabaseSupport.a $$[QT_INSTALL_LIBS]/libQt5Gui.a -lcomdlg32 -loleaut32 -limm32 -lopengl32 -lharfbuzz -lcairo -lgobject-2.0 -lfontconfig -lfreetype -lm -lusp10 -lmsimg32 -lgdi32 -lpixman-1 -lffi -lexpat -lbz2 -lpng16 -lharfbuzz_too -lfreetype_too -lglib-2.0 -lshlwapi -lpcre -lintl -liconv $$[QT_INSTALL_LIBS]/libQt5Core.a -lmpr -lnetapi32 -luserenv -lversion -lws2_32 -lkernel32 -luser32 -lshell32 -luuid -lole32 -ladvapi32 -lwinmm -lz -lpcre2-16
usr/i686-w64-mingw32.static/qt5//plugins/platforms/qwindows.prl:QMAKE_PRL_LIBS = -ldwmapi -lwinspool -L$$[QT_INSTALL_LIBS] $$[QT_INSTALL_LIBS]/libQt5EventDispatcherSupport.a -L/Users/tonyt/dev/mxe/usr/i686-w64-mingw32.static/lib/../lib $$[QT_INSTALL_LIBS]/libQt5FontDatabaseSupport.a $$[QT_INSTALL_LIBS]/libQt5ThemeSupport.a $$[QT_INSTALL_LIBS]/libQt5AccessibilitySupport.a $$[QT_INSTALL_LIBS]/libQt5WindowsUIAutomationSupport.a $$[QT_INSTALL_LIBS]/libQt5Gui.a -lcomdlg32 -loleaut32 -limm32 -lopengl32 -lharfbuzz -lcairo -lgobject-2.0 -lfontconfig -lfreetype -lm -lusp10 -lmsimg32 -lgdi32 -lpixman-1 -lffi -lexpat -lbz2 -lpng16 -lharfbuzz_too -lfreetype_too -lglib-2.0 -lshlwapi -lpcre -lintl -liconv $$[QT_INSTALL_LIBS]/libQt5Core.a -lmpr -lnetapi32 -luserenv -lversion -lws2_32 -lkernel32 -luser32 -lshell32 -luuid -lole32 -ladvapi32 -lwinmm -lz -lpcre2-16
usr/i686-w64-mingw32.static/qt5//plugins/platforms/qminimal.prl:QMAKE_PRL_LIBS = -L$$[QT_INSTALL_LIBS] $$[QT_INSTALL_LIBS]/libQt5EventDispatcherSupport.a -L/Users/tonyt/dev/mxe/usr/i686-w64-mingw32.static/lib/../lib $$[QT_INSTALL_LIBS]/libQt5FontDatabaseSupport.a $$[QT_INSTALL_LIBS]/libQt5Gui.a -lcomdlg32 -loleaut32 -limm32 -lopengl32 -lharfbuzz -lcairo -lgobject-2.0 -lfontconfig -lfreetype -lm -lusp10 -lmsimg32 -lgdi32 -lpixman-1 -lffi -lexpat -lbz2 -lpng16 -lharfbuzz_too -lfreetype_too -lglib-2.0 -lshlwapi -lpcre -lintl -liconv $$[QT_INSTALL_LIBS]/libQt5Core.a -lmpr -lnetapi32 -luserenv -lversion -lws2_32 -lkernel32 -luser32 -lshell32 -luuid -lole32 -ladvapi32 -lwinmm -lz -lpcre2-16 -L/Users/tonyt/dev/mxe/usr/i686-w64-mingw32.static/lib/../lib -lharfbuzz -lcairo -lgobject-2.0 -lfontconfig -lfreetype -lm -lusp10 -lmsimg32 -lgdi32 -lpixman-1 -lffi -lexpat -lbz2 -lpng16 -lz -lharfbuzz_too -lfreetype_too -lglib-2.0 -lws2_32 -lole32 -lwinmm -lshlwapi -lpcre -lintl -liconv
usr/i686-w64-mingw32.static/qt5//lib/Qt5FontDatabaseSupport.prl:QMAKE_PRL_TARGET = libQt5FontDatabaseSupport.a
usr/i686-w64-mingw32.static/qt5//mkspecs/modules/qt_lib_fontdatabase_support_private.pri:QT.fontdatabase_support_private.name = QtFontDatabaseSupport
usr/i686-w64-mingw32.static/qt5//mkspecs/modules/qt_lib_fontdatabase_support_private.pri:QT.fontdatabase_support_private.module = Qt5FontDatabaseSupport
usr/i686-w64-mingw32.static/qt5//mkspecs/modules/qt_lib_fontdatabase_support_private.pri:QT.fontdatabase_support_private.includes = $$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/QtFontDatabaseSupport $$QT_MODULE_INCLUDE_BASE/QtFontDatabaseSupport/5.11.1 $$QT_MODULE_INCLUDE_BASE/QtFontDatabaseSupport/5.11.1/QtFontDatabaseSupport

to find some linker options.

What project are you building and do you know upfront what plugins it's using?

@juzzlin
Copy link
Contributor

juzzlin commented Jul 13, 2018

I'm working on this project: https://github.com/juzzlin/Heimer

I already switched to qmake for Windows build so that I can make the NSIS installer. The original idea was to use CPack to create NSIS installer and it already worked except that the binary didn't work due to this static lib mess :) I might try to manually link to the *Support libraries like you suggested. The application is just a traditional QGraphicsView application without anything special currently. It depends on QtWidgets and QtXml.

@tonytheodore
Copy link
Member

I think pe-util may help here, otherwise "inelegant" solutions I've found before are on the table.

@ArtemPisarenko
Copy link
Contributor

There are definitely some progress made. Trying to build Qt5 application generated in Qt Creator using template "Qt Widgets Application" with current mxe master branch (CMake 3.15.4, Qt 5.14.0) results in just few linking errors:

# x86_64-w64-mingw32.static-cmake /host/home/artem/development/test/mxe_qt_static_app
== Using MXE wrapper: /mxe/usr/bin/x86_64-w64-mingw32.static-cmake
     - cmake version 3.15.4
     - warnings for unused CMAKE_POLICY_DEFAULT variables can be ignored
== Using MXE toolchain: /mxe/usr/x86_64-w64-mingw32.static/share/cmake/mxe-conf.cmake
== Using MXE runresult: /mxe/usr/share/cmake/modules/TryRunResults.cmake
== Adding "-DCMAKE_BUILD_TYPE=Release"
loading initial cache file /mxe/usr/share/cmake/modules/TryRunResults.cmake
-- The CXX compiler identification is GNU 5.5.0
-- Check for working CXX compiler: /mxe/usr/x86_64-pc-linux-gnu/bin/x86_64-w64-mingw32.static-g++
-- Check for working CXX compiler: /mxe/usr/x86_64-pc-linux-gnu/bin/x86_64-w64-mingw32.static-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
CMake Warning:
  Manually-specified variables were not used by the project:

    CMAKE_POLICY_DEFAULT_CMP0017
    CMAKE_POLICY_DEFAULT_CMP0020


-- Build files have been written to: /work/build-HardwareTestApp-mxe-x86_64-w64-mingw32
# make
Scanning dependencies of target mxe_qt_static_app_autogen
[ 10%] Automatic MOC and UIC for target mxe_qt_static_app
[ 10%] Built target mxe_qt_static_app_autogen
Scanning dependencies of target mxe_qt_static_app
[ 20%] Building CXX object CMakeFiles/mxe_qt_static_app.dir/mxe_qt_static_app_autogen/mocs_compilation.cpp.obj
[ 30%] Building CXX object CMakeFiles/mxe_qt_static_app.dir/main.cpp.obj
[ 40%] Building CXX object CMakeFiles/mxe_qt_static_app.dir/widget.cpp.obj
[ 50%] Building CXX object CMakeFiles/mxe_qt_static_app.dir/mxe/usr/x86_64-w64-mingw32.static/qt5/lib/cmake/Qt5Gui/Qt5Gui_QGifPlugin_Import.cpp.obj
[ 60%] Building CXX object CMakeFiles/mxe_qt_static_app.dir/mxe/usr/x86_64-w64-mingw32.static/qt5/lib/cmake/Qt5Gui/Qt5Gui_QICOPlugin_Import.cpp.obj
[ 70%] Building CXX object CMakeFiles/mxe_qt_static_app.dir/mxe/usr/x86_64-w64-mingw32.static/qt5/lib/cmake/Qt5Gui/Qt5Gui_QJpegPlugin_Import.cpp.obj
[ 80%] Building CXX object CMakeFiles/mxe_qt_static_app.dir/mxe/usr/x86_64-w64-mingw32.static/qt5/lib/cmake/Qt5Gui/Qt5Gui_QWindowsIntegrationPlugin_Import.cpp.obj
[ 90%] Building CXX object CMakeFiles/mxe_qt_static_app.dir/mxe/usr/x86_64-w64-mingw32.static/qt5/lib/cmake/Qt5Widgets/Qt5Widgets_QWindowsVistaStylePlugin_Import.cpp.obj
[100%] Linking CXX executable mxe_qt_static_app.exe
/mxe/usr/bin/x86_64-w64-mingw32.static-ld: cannot find -ljasper
/mxe/usr/bin/x86_64-w64-mingw32.static-ld: cannot find -lmng
/mxe/usr/bin/x86_64-w64-mingw32.static-ld: cannot find -ltiff
/mxe/usr/bin/x86_64-w64-mingw32.static-ld: cannot find -lwebpdemux
/mxe/usr/bin/x86_64-w64-mingw32.static-ld: cannot find -lwebpmux
/mxe/usr/bin/x86_64-w64-mingw32.static-ld: cannot find -llcms2
/mxe/usr/bin/x86_64-w64-mingw32.static-ld: cannot find -lwebp
/mxe/usr/bin/x86_64-w64-mingw32.static-ld: cannot find -llzma
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/mxe_qt_static_app.dir/build.make:224: mxe_qt_static_app.exe] Error 1
make[1]: *** [CMakeFiles/Makefile2:77: CMakeFiles/mxe_qt_static_app.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

My words are such optimistic because trying to build a little more complex app (i.e. with more dependencies) gives same result.
Not sure whether should I try apply #1645 because it seems to be out of date. Why I'm tried to make things using latest mxe version is just because I was driven by hope that closed longstanding qt bug will finally resolve issue. Well, it did progress (note cmake output above where it automates integrating static plugins). Maybe it's just not Qt fail, but rather MXE should be updated accordingly...

@ArtemPisarenko
Copy link
Contributor

Yes, that's MXE fault! I've just installed missing dependencies into MXE, i.e packages jasper libmng tiff libwebp lcms lzma, and ... it works now! Qt5 application is built statically and successfully run in windows 10! Unbelievable! Long years of broken MXE+Qt+cmake are finished now! My congratulations!

@ArtemPisarenko
Copy link
Contributor

... but application using QtSerialPort fails to link:

/mxe/usr/x86_64-w64-mingw32.static/qt5/lib/libQt5SerialPort.a(qserialportinfo_win.o):qserialportinfo_win.cpp:(.text$_ZL24deviceInstanceIdentifierm+0x3f): undefined reference to `__imp_CM_Get_Device_IDW'
/mxe/usr/x86_64-w64-mingw32.static/qt5/lib/libQt5SerialPort.a(qserialportinfo_win.o):qserialportinfo_win.cpp:(.text$_ZL22deviceRegistryPropertyPvP16_SP_DEVINFO_DATAm+0x79): undefined reference to `__imp_SetupDiGetDeviceRegistryPropertyW'
/mxe/usr/x86_64-w64-mingw32.static/qt5/lib/libQt5SerialPort.a(qserialportinfo_win.o):qserialportinfo_win.cpp:(.text$_ZN15QSerialPortInfo14availablePortsEv+0x7b): undefined reference to `__imp_SetupDiGetClassDevsW'
/mxe/usr/x86_64-w64-mingw32.static/qt5/lib/libQt5SerialPort.a(qserialportinfo_win.o):qserialportinfo_win.cpp:(.text$_ZN15QSerialPortInfo14availablePortsEv+0x108): undefined reference to `__imp_SetupDiEnumDeviceInfo'
/mxe/usr/x86_64-w64-mingw32.static/qt5/lib/libQt5SerialPort.a(qserialportinfo_win.o):qserialportinfo_win.cpp:(.text$_ZN15QSerialPortInfo14availablePortsEv+0x135): undefined reference to `__imp_SetupDiOpenDevRegKey'
/mxe/usr/x86_64-w64-mingw32.static/qt5/lib/libQt5SerialPort.a(qserialportinfo_win.o):qserialportinfo_win.cpp:(.text$_ZN15QSerialPortInfo14availablePortsEv+0x4d3): undefined reference to `__imp_CM_Get_DevNode_Status'
/mxe/usr/x86_64-w64-mingw32.static/qt5/lib/libQt5SerialPort.a(qserialportinfo_win.o):qserialportinfo_win.cpp:(.text$_ZN15QSerialPortInfo14availablePortsEv+0x865): undefined reference to `__imp_CM_Get_Parent'
/mxe/usr/x86_64-w64-mingw32.static/qt5/lib/libQt5SerialPort.a(qserialportinfo_win.o):qserialportinfo_win.cpp:(.text$_ZN15QSerialPortInfo14availablePortsEv+0x941): undefined reference to `__imp_SetupDiDestroyDeviceInfoList'

@ArtemPisarenko
Copy link
Contributor

... and problem being solved by adding -lsetupapi to target_link_libraries(<app_target> ...) in application cmake file.

@ArtemPisarenko
Copy link
Contributor

ArtemPisarenko commented Jan 15, 2020

I'm sure similar failure with QtSerialPort may happen with any other Qt Add-On (i.e. module not being part of qtbase), and applicable only to static Qt linkage (although I didn't checked shared linkage). For essential modules MXE qtbase package contains fix. It just needs to be applied in same way to all other Qt packages.
I reviewed old patch applied to qtbase and it makes me think that it may be root cause of static linkage failure, because it seems to be incompatible with changes applied in recent qt bugfix. Maybe removing both this patch and fix for qtbase package will solve issue completely, but it needs to be checked...

@ArtemPisarenko
Copy link
Contributor

ArtemPisarenko commented Jan 15, 2020

I found root cause of failure. It's a qtbase mkspecs/features/create_cmake.prf file which misconfigures CMAKE_PRL_FILE_LOCATION_* values for win32/mingw platform. I've patched it, removed fix from qtbase package file in MXE (unnecessary anymore) and rebuild package. Now my application builds and runs fine "out of box". This is only static linkage I've tested.

@tonytheodore
Copy link
Member

For essential modules MXE qtbase package contains fix. It just needs to be applied in same way to all other Qt packages.

That isn't actually a fix, it's a workaround by manually hardcoding the required libs.

The last time I looked at it a few months ago, the platform plugins were being handled correctly, but the transitive dependencies were incorrectly ordered. I'll try to have another look on the weekend.

@ArtemPisarenko
Copy link
Contributor

ArtemPisarenko commented Jan 16, 2020

The last time I looked at it a few months ago, the platform plugins were being handled correctly, but the transitive dependencies were incorrectly ordered.

It isn't platform plugins who caused build fail, but missing package dependencies and another Qt packages (outside of qtbase scope).

I'll try to have another look on the weekend.

That fix/workaround (limited to qtbase currently) isn't actual anymore, because Qt now does it properly itself (starting from version 5.14.0). The reason why it didn't worked is a couple of another issues I discovered above. After I finish a little more testing I'll prepare corresponding fixes to integrate both here and upstream to Qt.

@ArtemPisarenko
Copy link
Contributor

ArtemPisarenko commented Jan 16, 2020

Confirming that Qt shared build works too (provided that application deployed properly, which mostly can be automated using one of tools/copydlldeps.* scripts supplied with MXE)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants