0

At the moment, I've got a project with a QT-based GUI, which in turn relies upon a couple of library projects that use DLL files in turn. To distribute the GUI to any PC without QT, I've previously taken the executable that QT Creator generates and put it into a folder containing the relevant DLLs (such as Qt5Core.dll, Qt5Gui.dll, etc). Now I'm trying through QT built static from source to generate a standalone executable - so hopefully just (let's say) gui_project.exe itself can be distributed without a small host of supporting DLL files.

Now I can build the different projects successfully and generate the executable for the GUI (let's call it gui_project.exe), but when I try to run it I'm told I'm missing a DLL file:

"The program can start because Qt5ExtSerialPort1.dll is missing from your computer. Try reinstalling the program to fix this problem."

Now within gui_project.pro, I thought I could point to the .lib file instead of the .dll file. To address this the first, commented out, line is how I did things originally, whereas the second line is my attempt to fix things:

#CONFIG(release, debug|release): LIBS += ../ProcessingLib/release/ProcessingLib.lib ../XpsLib/release/XpsLib.lib -L../SerialPortLib/qextserialport/release -lQt5ExtSerialPort1 /DELAYLOAD:XpsLib.dll
CONFIG(release, debug|release): LIBS += ../ProcessingLib/release/ProcessingLib.lib ../XpsLib/release/XpsLib.lib ../SerialPortLib/qextserialport/release/Qt5ExtSerialPort1.lib /DELAYLOAD:XpsLib.dll

XpsLib is a small project controlling a stepper motor.

I don't know whether I'm deluding myself in thinking I can do away completely with (third-party, e.g. QT's) DLLs, so please put me straight if I got that wrong. Otherwise, any advice on how to debug this problem would be greatly appreciated.

I have tried to research the topic online but I only ended up confusing myself. Also, I'm happy to share my code if that helps - but initially I'll try not to bloat my post as hopefully I've missed something obvious in terms of debugging.

I am using: QT Creator 3.6.0, QT source 5.4.2, [I mistakenly thought it was 5.4.1 originally..] msvc2013_64

------ Update1 ------

I'm going to ask AlexanderVX to elaborate on the section describing the "-MT -MTd options". Thus I'm amending my post to include more (and hopefully!) relevant information:

My main, gui_project.pro file uses these QT components:

QT       += core gui script

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

(So hopefully I've not bother with QtQuick, QML and some of the more involved libraries). Onto the basic libraries, I have added, to get static building working:

CONFIG += static

I installed QT from source (version 5.4.1), to the folder:

U:\QT\

In order to make & configure, I opened Visual Studio 2013's tool, "VS2013 x64 Native Tools Command Prompt", and did:

U:
cd\QT\5.4\src
nmake distclean
configure -release -static -nomake examples -opengl desktop
nmake

Then I went to my project: (Navigated to C:..\gui_project)

nmake clean
qmake -config release
nmake

But rereading the information on the configure command (and with AlexanderVX's advice), I'm guessing out missed some flag(s) from my configure command. But looking at the help available for configure at the command line, the closest to -MT -MTd options that I find is:

    -no-mtdev .......... Do not enable support for mtdev.
 +  -mtdev ............. Enable support for mtdev.

Assuming the above is relevant (-mtdev being the default), should I disable it?

I see your instructions for making statically linked executables made through QT creator; but (fingers crossed) I'm hoping I can master it through the command prompt as an initial step. I do have a 'Bronze' support level with this licence; QT support have helped me to successfully statically build QT from source, but perhaps I have not yet fully appreciated the relevant configuration option(s).

------ Update2 ------

I think my problem is actually in terms of the configuring my project to pull in DLLs (i.e. plug-ins, mostly provided by QT). Following the link that Kuba Oder posted previously, I came across:

http://www.formortals.com/how-to-statically-link-qt-4/

More specifically, trying to apply Step 3, I've add these lines to my project file:

#-------------------------------------------------
#
# Project created by QtCreator 2011-11-24T10:35:18
#
#-------------------------------------------------
QT       += core gui script

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

# Prevent MSVC 2013 complaining "Conversion from string literal loses const qualifier"
QMAKE_CXXFLAGS_RELEASE -= -Zc:strictStrings
# See: http://stackoverflow.com/a/28625430/2903608

TARGET = gui_project
TEMPLATE = app

# Needed for static building?
CONFIG += static

SOURCES += main.cpp \
    ...

HEADERS += mainwindow.h \
    ...

FORMS += \
    ... 

RESOURCES += \
    gui_project.qrc

static {

  # SO (http://stackoverflow.com/a/26777201/2903608) Suggest adding this to libs
  LIBS += -LU:/Qt/5.4/msvc2013_64/plugins/platforms/
  # (The above folder contains for instance qjpeg, a standard plug-in)
  # In a similar vein, let's add this folder which contains Qt5Guis .lib and .dll:
  LIBS += -LU:/Qt/5.4/Src/qtbase/lib/
  LIBS += -LU:/Qt/5.4/msvc2013_64/bin/

  # Relying upon: http://www.formortals.com/how-to-statically-link-qt-4/
  CONFIG += static
  QTPLUGIN += qt5gui Qt5Widgets Qt5ExtSerialPort1
  DEFINES += STATIC
  ...

And I've modified my main.cpp, with the paragraph between the two lines beginning with three /'s:

#include <QApplication>
#include <QSplashScreen>
#include "mainwindow.h"

/// Requirement for Static linking?
#include <QtPlugin>
Q_IMPORT_PLUGIN(qt5gui)
Q_IMPORT_PLUGIN(Qt5Widgets)
Q_IMPORT_PLUGIN(Qt5ExtSerialPort)
///

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    ...
    return app.exec();
}

Unfortunately, I'm now stuck with 3 linking errors, one for each DLL that I'm trying to use:

main.obj : error LNK2019: unresolved external symbol "struct QStaticPlugin const __cdecl qt_static_plugin_qt5gui(void)" (?qt_static_plugin_qt5gui@@YA?BUQStaticPlugin@@XZ)
 referenced in function "public: __cdecl Staticqt5guiPluginInstance::Staticqt5guiPluginInstance(void)" (??0Staticqt5guiPluginInstance@@QEAA@XZ)

main.obj : error LNK2019: unresolved external symbol "struct QStaticPlugin const __cdecl qt_static_plugin_Qt5Widgets(void)" (?qt_static_plugin_Qt5Widgets@@YA?BUQStaticPlugin@@XZ)
 referenced in function "public: __cdecl StaticQt5WidgetsPluginInstance::StaticQt5WidgetsPluginInstance(void)" (??0StaticQt5WidgetsPluginInstance@@QEAA@XZ)

main.obj : error LNK2019: unresolved external symbol "struct QStaticPlugin const __cdecl qt_static_plugin_Qt5ExtSerialPort1(void)" (?qt_static_plugin_Qt5ExtSerialPort1@@YA?BUQStaticPlugin@@XZ) 
 referenced in function "public: __cdecl StaticQt5ExtSerialPort1PluginInstance::StaticQt5ExtSerialPort1PluginInstance(void)" (??0StaticQt5ExtSerialPort1PluginInstance@@QEAA@XZ)

release\gui_project.exe : fatal error LNK1120: 3 unresolved externals
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\amd64\link.EXE"' : return code '0x460'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\amd64\nmake.exe"' : return code '0x2'
Stop.

Looking at the first of those 3 linker errors, I think it's a problem of pairing/substituting(?) Qt5Gui.dll and/with Qt5Gui.lib.

Examining my system, the absolute path for each is:

U:\Qt\5.4\Src\qtbase\lib\Qt5Gui.lib
U:\Qt\5.4\msvc2013_64\bin\Qt5Gui.dll

But somehow, I fall short somewhere?

------ Update3 - Minor ------

I realised I had typoed Qt5ExtSerialPort1, forgetting the 1 at the end. Linker errors unchanged though.

Many thanks for your assistance and patience in helping me.

PhilPhil
  • 173
  • 4
  • 18
  • I don't have any answers for you, only a lame anecdote. A couple of years ago, I tried to build Qt 5.2.1 statically for Windows, and link it with my application. I was mainly using QtQuick and networking libraries. I spent a few hours on it before deciding it wasn't worth my time. If you are using the open source version of Qt and you have not done so already, I do recommend reviewing the license (LGPL, I believe?) - I recall there being several "gotchas" regarding static linkage. – Barrett Adair Mar 14 '16 at 15:54
  • Apologies, I forgot to include: We began using QT Open Source but began paying for a commercial license to enable generating a statically linked, standalone executable (as opposed to distributing the executable along with a small host of DLLs). Now onto digesting AlexanderVX's answer. – PhilPhil Mar 15 '16 at 08:57
  • See [this answer](http://stackoverflow.com/a/32613840/1329652). I'm shipping a bunch of statically linked stuff using both Qt 4 and Qt 5. No problems. – Kuba hasn't forgotten Monica Mar 15 '16 at 14:37
  • @KubaOber Thank you, missed that post somehow. Is `-target xp` still the only valid option? (It's Win7 only here, so that's ok?) I've only had a quick look at that answer, I'm just hoping I can avoid MS Studio as trying to import my code this morning only resulted in headbanging against a wall. Quickly reminded me why I try to stay clear of it :-p – PhilPhil Mar 15 '16 at 15:16
  • The key word in my answer was *orthogonal*. All these options are separate from each other, and you should use them individually as necessary. Any combination of them can be present, including all, none, etc. – Kuba hasn't forgotten Monica Mar 15 '16 at 16:07
  • @KudaOber Thanks for the update. -static-runtime should make things a bit easier, maybe no need to force -MT option explicitly. – Alexander V Mar 15 '16 at 18:15
  • Is the -static-runtime a flag that was introduced in QT 5.5? Because I cannot see it looking at `configure -help`, nor is it accepted when I try `configure -static-runtime` -> `+ U:\Qt\5.4\Src\qtbase\configure.bat -top-level -static-runtime ` (Followed by on the next-line) `Unknown option -static-runtime`. I am reading my way through the rest of information on that previous question's answers. – PhilPhil Mar 16 '16 at 11:00
  • What a mess... Congratulations Qt for making their framework so easy to use... – Konrad Jun 25 '17 at 04:45

1 Answers1

0

How can I build static Windows Qt executable without Qt DLL dependencies?

There is small wiki on it: Build Standalone Qt Application for Windows

I would add that depending on your app a few more things may need to be configured. We also don't want to drag Visual C++ Redistributable and thus we compile the whole Qt and the app with -MT -MTd options (not -MD -MDs) as default. UPDATE #1:

  • for Qt 5.3 and earlier: C:\Qt\5.3\Src.64\qtbase\mkspecs\win32-msvc2013\qmake.conf -- replace MD with MT so both MD and MDd get transformed to MT and MTd (case sensitive).
  • for Qt 5.5 and later: C:\Qt\5.5\QtSourceCode\qtbase\mkspecs\common\msvc-desktop.conf -- replace MD with MT so both MD and MDd get transformed to MT and MTd (case sensitive).

I did not check with Qt 5.4 (one of above?).

Mind the compiler you use so that an appropriate file/setting applied to get the runtime statically linked with your executable.

And yes, distributing QML / QtQuick with statically built Qt executable is a pain but still manageable. Basically, you copy the whole directory of QtQuick scripts altogether with your executable.

Mind that it is easier to build statically linked executable with command line tools: qmake and jom. But there is a way to set up both Qt Creator and Visual Studio for that same configuration. With Qt Creator you need to set up Qt Version and its dependent Compiler Kit and then switch your project to that specific Compiler Kit.

So, static build is manageable but depends on specific application needs. I would agree with the comment above that not everything is straightforward but from experience of couple years ago the information on the Internet helped to degree plus a bit more of own effort. And to be even more successful with that purchasing commercial Qt license helps better: you get Qt Company support, certain kinds of license (I guess with 'Silver' support level and above) imply they support custom Qt builds from the source code.

Alexander V
  • 8,351
  • 4
  • 38
  • 47
  • The small wiki ("**Build Standalone .. Windows**") looks at seductively easy. But I'm failing in that I cannot create the manifest file that appears to be mandatory by the heading "Using Microsoft Tools". Can I get QT creator to produce the manifest file? I've tried importing my QT project into Visual Studio 2013 but I'm getting 111 errors, complaining that "fatal error C1083: Cannot open include file: XX" where XX is common files such as QString, Qdialog, etc. The Fatal Error should be sorted by updating the relevant Include path, but I'm stumped at the moment. – PhilPhil Mar 15 '16 at 11:56
  • PS, Looks like other(s) have tried (and failed?) to produce the manifest file through QT? See: ([link]https://forum.qt.io/topic/13962/qt-not-passing-details-to-visual-studio-linker-to-generate-manifest-file/4) – PhilPhil Mar 15 '16 at 11:59
  • Hmmm... no manifest file I explicitly specified with Qt project ever. Have a look on Qt examples. The big project started with borrowing from one of widget projects and since never experienced manifest problem. I will have a look on more context in your question. Should you post it as UPDATE that'd be easier. – Alexander V Mar 15 '16 at 18:12
  • Because it will take awhile (re-configuring QT, reading the answer(s) pointed out by @Kuba), I modified `U:\Qt\5.4\Src\qtbase\mkspecs\win32-msvc2013\qmake.conf` my system as instructed (substituting -MT instead of -MD). – PhilPhil Mar 16 '16 at 11:22
  • Just for reference, the 3 fatal Linker errors persist - even if I reinstall QT from source and amend qmake.conf to use -MT instead of -MD. My hunch is though, I have made a mistake somewhere regarding library linking? – PhilPhil Mar 18 '16 at 08:47
  • @PhilPhil When you change anything in Qt own framework folders, you need to completely rebuild it. And the only way to reconfigure and rebuild is to start with clean Qt source code directory. Absolutely no leftovers from previous attempts. – Alexander V Mar 18 '16 at 18:13
  • AlexanderVX: I completely removed QT through the uninstall wizard (and doublecheck, having just the empty QT folder left), installed from source and made the changes to the `...\mkspecs\win32-msvc2013\qmake.conf` before running the configure command I still end up with the 3 fatal linker errors when I try to nmake my project. – PhilPhil Mar 22 '16 at 09:20
  • I only erase and put back in Src folder before running configure / jom again. It is understandable how many obstacles you hit. If that is not for hobby but business you probably need to obtain Qt license Silver support level or higher. I can do a contract for that, btw (not Qt company but I can build it). – Alexander V Mar 22 '16 at 19:35