PDA

View Full Version : Tons of unresolved externals when building a dll and statically built Qt 4.7.0



kvb
6th November 2010, 19:07
I am attempting to build a simple dll hello world example. I have build qt 4.7.0 for static linking by doing this on the command line:


C:\Qt\4.7.0> configure -static -release -no-exceptions -nomake examples -nomake demos
C:\Qt\4.7.0> make sub-src


Here is my sample .pro file




TEMPLATE = lib
TARGET = helloworld
DEPENDPATH += .
INCLUDEPATH += .

CONFIG += dll

# Input
HEADERS += helloworld.h
SOURCES += helloworld.cpp


here is my example helloworld.cpp



#include "helloworld.h"
#include <stdio.h>

HelloWorld::HelloWorld(QObject *parent) :
QObject(parent)
{
}

void HelloWorld::sayHello() {
printf("Hello World!\n");
done();
}


and the header...



#ifndef HELLOWORLD_H
#define HELLOWORLD_H

#include <QObject>

class HelloWorld : public QObject
{
Q_OBJECT
public:
explicit HelloWorld(QObject *parent = 0);

signals:
void done();

public slots:
void sayHello();

};

#endif // HELLOWORLD_H


when I try to compile as dll, I get the errors shown below. Any Ideas?




C:\projects\qt\helloworld>qmake
C:\projects\qt\helloworld>make release
mingw32-make -f Makefile.Release
mingw32-make[1]: Entering directory `C:/projects/qt/helloworld'
g++ -static -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -Wl,-s -shared -Wl,--out-implib,release\libh
elloworld.a -o release\helloworld.dll release/helloworld.o release/moc_helloworld.o -L"c:\Qt\4.7.0\lib" -lQtGui -lgdi32 -lcomdlg32 -lo
leaut32 -limm32 -lwinmm -lwinspool -lmsimg32 -lQtCore -lkernel32 -luser32 -lshell32 -luuid -lole32 -ladvapi32 -lws2_32
Creating library file: release\libhelloworld.a
release/helloworld.o:helloworld.cpp:(.text+0x16): undefined reference to `_imp___ZN7QObjectC2EPS_'
release/moc_helloworld.o:moc_helloworld.cpp:(.text+0x4d): undefined reference to `_imp___ZN7QObject11qt_metacastEPKc'
release/moc_helloworld.o:moc_helloworld.cpp:(.text+0x8e): undefined reference to `_imp___ZN11QMetaObject8activateEP7QObjectPKS_iPPv '
release/moc_helloworld.o:moc_helloworld.cpp:(.text+0xb9): undefined reference to `_imp___ZN7QObject11qt_metacallEN11QMetaObject4Cal lEiP
Pv'
release/moc_helloworld.o:moc_helloworld.cpp:(.text+0x100): undefined reference to `_imp___ZN7QObject16staticMetaObjectE'
release/moc_helloworld.o:moc_helloworld.cpp:(.text$_ZN10He lloWorldD1Ev[HelloWorld::~HelloWorld()]+0x10): undefined reference to `_imp__
_ZN7QObjectD2Ev'
release/moc_helloworld.o:moc_helloworld.cpp:(.text$_ZN10He lloWorldD0Ev[HelloWorld::~HelloWorld()]+0x15): undefined reference to `_imp__
_ZN7QObjectD2Ev'
collect2: ld returned 1 exit status
mingw32-make[1]: *** [release\helloworld.dll] Error 1
mingw32-make[1]: Leaving directory `C:/projects/qt/helloworld'
mingw32-make: *** [release] Error 2

tbscope
6th November 2010, 19:31
C:\projects\qt\helloworld>qmake

That's the qmake from the static library?

kvb
6th November 2010, 20:04
That's the qmake I did from the test projects main directory.

wysota
6th November 2010, 20:16
Did you run it before or after you added the Q_OBJECT macro to your class?

kvb
6th November 2010, 20:30
The QObject Macro was added before I ran qmake. Does it make a difference?

wysota
6th November 2010, 20:52
Did you remove the dynamic version of Qt before building the static one?

kvb
6th November 2010, 21:25
I guess I can't be certain that I did. How do you remove the dynamic libs? Is there any easy way to do it now that I've built the static libs?

wysota
6th November 2010, 22:19
You delete them or build the static version in a different directory. Otherwise your projects might pick up the dynamic libraries instead of the static ones.

kvb
6th November 2010, 22:47
I guess I was under the impression that the static build would be built in a different directory than the dynamic libraries. Could you point me at the dynamic libs? I'm not even sure where the static libs were put...I didn't pay too much attention to the paths during the build unfortunately.

wysota
6th November 2010, 23:02
Then it will probably be a good lesson for you to try and find the libraries yourself. You'll learn something about Qt's directory layout.

kvb
6th November 2010, 23:26
yeah okay, so in the root there is a bin directory with dll's in them and it looks like the static libs are in the lib/ directory. So they are in different directories.

wysota
6th November 2010, 23:36
dll files are not used during the compilation. The lib files are. Now imagine you have a mix of lib files from a static and dynamic build, draw the conclusions yourself :)

By the way, I fail to see a practical use of a Qt-based dll compiled with static Qt libs. Would you enlighten me about your ultimate goal?

kvb
6th November 2010, 23:46
In looking at the lib files, it looks like they all have modified dates of around the 2 hrs or so when I was building the static libs so I doubt that there is a mix.

The idea for the Qt-based dll is to have to reduce the number of dlls that I have to distribute to co-workers. I created a dll that does some image manipulation that interfaces to some scripts I have written in Ruby. Qt was used because the image processing is much faster in Qt than in other ruby libs that we could find. Maybe it's simpler if I just distribute the QtCore4.dll (and any other dlls needed) with my custom dll. I was hoping to only have to distribute only one file (and by distribute I mean check in to the project on svn). Not everyone has Qt installed on their machine so that is another reason I was hoping to use a static build.

wysota
6th November 2010, 23:54
I don't know what you intend to do later but so far you are exposing Qt interface to the outside world so programs that want to use your library would have to link against Qt as well. There are ruby bindings for Qt (or is it Qt bindings for Ruby? Whatever...) available, maybe that will be a more suitable solution for you - you wouldn't have to touch any C++ code at all.

kvb
7th November 2010, 00:07
Well it turns out that adding the line DEFINES += QT_NODLL to my .pro file got rid of all my issues...I swear I tried that before and it didn't work.


exposing Qt interface to the outside world so programs that want to use your library would have to link against Qt as well

I'm afraid I don't understand this statement, isn't the purpose of doing the static build suppose to get you away from having to link against qt in other applications? Maybe I'm just too confused to be helped... ;)

I will look into the ruby bindings, they could be really usefull. Thanks for pointing those out!

wysota
7th November 2010, 00:28
I'm afraid I don't understand this statement, isn't the purpose of doing the static build suppose to get you away from having to link against qt in other applications? Maybe I'm just too confused to be helped... ;)
If you expose things such as "QObject" then code that is to use it has to know about QObject as well. It's not enough to link to code that knows QObject. If you only expose functions with an interface that has no relation to Qt (so you don't deliver any header files containing QString, QObject or QWhatEverElseGoesHere) then you are fine.

kvb
7th November 2010, 00:41
Thanks for clarification...I am exposing the dll with C style functions (no relation to Qt).

I looked quickly at the ruby bindings and it looks like its using Qt 4.3 and ruby 1.8.6 and I'm using ruby 1.9.2...bummer.

Thanks for your help!

wysota
7th November 2010, 00:51
I looked quickly at the ruby bindings and it looks like its using Qt 4.3 and ruby 1.8.6 and I'm using ruby 1.9.2...bummer.
You can probably build the bindings for newer Qt and newer Ruby as well.