Results 1 to 5 of 5

Thread: Porting code to Windows and getting "error LNK2019: unresolved external symbol ...."

  1. #1
    Join Date
    Dec 2010
    Posts
    35
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Porting code to Windows and getting "error LNK2019: unresolved external symbol ...."

    I have a small project running on Linux and Mac and I'm now porting it to Windows (Vista). Qt version is 4.7. I'm using VSE 2008 for an IDE.

    I did have one small sample working a couple of months ago so I know my environment is set up correctly.

    I've been able to easily/quickly resolve most of the issues with just some .pro file tweaking, but I can't resolve this last one (last problem, ha!).

    The program structure consists of multiple subdirectories and each subdir creates a shared library of the associated object files (e.g., .so on linux, .dylib on mac, .dll on Win32).

    However, when I link a subdirectory of object files into a DLL on windows and code in that directory references classes/functions in another (unbuilt) library, I get 'error LNK2019: unresolved external symbol...'

    The .pro file in each subdirectory basically has 'CONFIG += shared' in it (included in a common file, actually).

    Each subdirectory also defines their own namespace.

    The link line generated to link a DLL looks like:

    Qt Code:
    1. link /LIBPATH:"c:\Programs\Qt\4.7.0\lib" /NOLOGO /DEBUG /DLL /MANIFEST /MANIFESTFILE:"../../build/element\element.intermediate.manifest" /OUT:..\..\lib\element.dll @C:\XXXXX\AppData\Local\Temp\nmDF6C.tmp
    To copy to clipboard, switch view to plain text mode 

    The 'nmDF6C.tmp' file is deleted at the end of the build command so I can't see what it contains.

    The errors:

    Qt Code:
    1. Element.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall exceptions::DuplicateException::~DuplicateException(void)" (??1DuplicateException@exceptions@@UAE@XZ) referenced in function "protected: void __thiscall element::Element::add(class core::DataChannel *)" (?add@Element@element@@IAEXPAVDataChannel@core@3456@@Z)
    2. Element.obj : error LNK2019: unresolved external symbol "public: __thiscall exceptions::DuplicateException::DuplicateException(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??0DuplicateException@exceptions@@QAE@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "protected: void __thiscall element::Element::add(class core::DataChannel *)" (?add@Element@element@@IAEXPAVDataChannel@core@3456@@Z)
    To copy to clipboard, switch view to plain text mode 

    I'm a rather newbie on developing C++ apps on Windows (I spend most of my time on Linux/Mac)... Do I need some sort of '__declspec()' foo on the function definitions or declarations or?

    Thanks.

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Porting code to Windows and getting "error LNK2019: unresolved external symbol ..

    However, when I link a subdirectory of object files into a DLL on windows and code in that directory references classes/functions in another (unbuilt) library, I get 'error LNK2019: unresolved external symbol...'
    You need to make sure that libraries are built the correct order to ensure this doesn't happen. Look at the:
    Qt Code:
    1. TEMPLATE = subdirs
    2. CONFIG += ordered
    3. SUBDIRS = g a b c d e f
    To copy to clipboard, switch view to plain text mode 

    Similar problems arise if the library search path is wrong and the library, which exists, cannot be found.

  3. #3
    Join Date
    Dec 2010
    Posts
    35
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Porting code to Windows and getting "error LNK2019: unresolved external symbol ..

    Quote Originally Posted by ChrisW67 View Post
    You need to make sure that libraries are built the correct order to ensure this doesn't happen.

    Similar problems arise if the library search path is wrong and the library, which exists, cannot be found.
    I do have the 'TEMPLATE = subdirs' and 'CONFIG += ordered' in my project-level .pro file and then the list of subdirs to make.

    I also have the common (and self-contained) directories built first. I still have the problem with 'unresolved external symbol' when building the shared libraries of sub-directories that reference these common directories.

    Do I need to specify the common libs in each of the sub-dir .pro files (as in 'LIBS += ../../core ../../exceptions')? That seems strange as I don't need to do this for either Linux or Mac builds.

    Also, I have some classes that have a bi-directional relationship that span sub-directories. One contains a container of pointers to another (e.g., 'map<string, Element *> elements;') and the constructor of the Element class includes a point to the container class (e.g., 'new Element (Container *)'). The Element and Container classes are in separate sub-directories.

    Sooo, I really couldn't build one before the other.

    Still searching....

  4. #4
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Porting code to Windows and getting "error LNK2019: unresolved external symbol ..

    I also have the common (and self-contained) directories built first. I still have the problem with 'unresolved external symbol' when building the shared libraries of sub-directories that reference these common directories.

    Do I need to specify the common libs in each of the sub-dir .pro files (as in 'LIBS += ../../core ../../exceptions')? That seems strange as I don't need to do this for either Linux or Mac builds.
    Yes. In order to link anything, whether an application, shared, or static library, the linker must be able to find the necessary libraries. It does this by looking for each named library in the current directory and then along a library search path until it is found (or not as in your case). This search behaviour is more-or-less universal. Each linker has a a default search path that can be supplemented. In Qt PRO files you add to the search path with -L options in LIBS. You also name the libraries to search for in LIBS with -l (lower case L) options:
    Qt Code:
    1. LIBS += -L../../common/lib -lcool -lfroody -ldude
    To copy to clipboard, switch view to plain text mode 
    as an alternative you can explicitly provide the full path to each library file:
    Qt Code:
    1. LIBS += ../../common/lib/libcool.a ../../common/lib/libfroody.a ../../common/lib/libdude.a
    To copy to clipboard, switch view to plain text mode 
    but this approach has the disadvantage of needing adjustment by platform/linker for different library file naming systems. It may have worked on Linux/Mac because the common library directory was on the default search path for the linker (/usr/local/lib perhaps).

    Also, I have some classes that have a bi-directional relationship that span sub-directories. One contains a container of pointers to another (e.g., 'map<string, Element *> elements;') and the constructor of the Element class includes a point to the container class (e.g., 'new Element (Container *)'). The Element and Container classes are in separate sub-directories.

    Sooo, I really couldn't build one before the other.
    There is no facility to automatically break the circular dependencies you have built. One approach is to avoid separating dependent items between libraries. Another is to avoid doing things with B in A that require knowing more than that B exists (i.e. more than storing a pointer to a B instance). Exactly how you fix this is specific to your code and not really Qt specific.

  5. #5
    Join Date
    Dec 2010
    Posts
    35
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Porting code to Windows and getting "error LNK2019: unresolved external symbol ..

    Quote Originally Posted by ChrisW67 View Post
    In Qt PRO files you add to the search path with -L options in LIBS. You also name the libraries to search for in LIBS with -l (lower case L) options:
    Yep. I was typing tooo fast (too much coffee?) in my earlier post and mistyped what I specified for the LIBS variable.

    It may have worked on Linux/Mac because the common library directory was on the default search path for the linker (/usr/local/lib perhaps).
    While anything is possible, I'm not so sure about that on *nix-based systems. For example, here's my compile and link lines of one of the directories into a shared object library. The code in here references another (not yet built) library. Note I use other 3rd-party packages, which I refer to at compile time with the '-I' compiler option (for the include files). Also note the link only refers to Qt libraries (which are in the default search path of /usr/lib).

    I also made sure my system had no files named 'libelement.so' or 'libcore.so' before starting, including the Trash, before I started this compile.
    Qt Code:
    1. cd src/element/ && make -f Makefile.linux all
    2. make[1]: Entering directory `/home/project/src/element'
    3. g++ -c -pipe -g -Wall -W -D_REENTRANT -fPIC -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include -I.. -I/usr/share/xsd-3.3.0/libxsd -Imocs -o ../../build/element/Element.o Element.cpp
    4. . . .
    5. /usr/lib/qt4/bin/moc -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include -I.. -I/usr/share/xsd-3.3.0/libxsd -Imocs Element.h -o mocs/moc_Element.cpp
    6.  
    7. g++ -c -pipe -g -Wall -W -D_REENTRANT -fPIC -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include -I.. -I/usr/share/xsd-3.3.0/libxsd -Imocs -o ../../build/element/moc_Element.o mocs/moc_Element.cpp
    8.  
    9. g++ -shared -Wl,-soname,libelement.so.1 -o libelement.so.1.0.0 ../../build/element/Element.o ../../build/element/moc_Element.o -lQtGui -lQtCore -lpthread
    10.  
    11. mv -f libelement.so.1.0.0 libelement.so libelement.so.1 libelement.so.1.0 ../../lib/
    To copy to clipboard, switch view to plain text mode 
    Then, the 'core' directory includes a class that holds a container of pointers to 'Elements' (map<string, Element *>):
    Qt Code:
    1. make[1]: Leaving directory `/home/project/src/element'
    2. cd src/core/ && make -f Makefile.linux all
    3. make[1]: Entering directory `/home/project/src/core'
    4. g++ -c -pipe -g -Wall -W -D_REENTRANT -fPIC -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include -I.. -I/usr/share/xsd-3.3.0/libxsd -Imocs -o ../../build/core/Engine.o Engine.cpp
    5.  
    6. . . .
    7.  
    8. g++ -shared -Wl,-soname,libcore.so.1 -o libcore.so.1.0.0 ../../build/core/Engine.o -lQtGui -lQtCore -lpthread
    9. mv -f libcore.so.1.0.0 libcore.so libcore.so.1 libcore.so.1.0 ../../lib/
    To copy to clipboard, switch view to plain text mode 
    And the link of the application. Note the 3rd-party libraries are in the normal search path (/usr/lib):
    Qt Code:
    1. g++ -o ../../bin/instrumentPanel.debug ../../build/main/main.o ../../build/main/qrc_InstrumentPanel.o -llog4cxx -laprutil-1 -lapr-1 -lxerces-c -L../../lib -lelement -ldisplay -lcore -lxsd -lexceptions -lmodel -lQtGui -lQtCore -lpthread
    2. make[1]: Leaving directory `/home/project/src/main'
    To copy to clipboard, switch view to plain text mode 
    Then to run this application, I set an environment variable to point to the directories that include the shared libraries needed to run the application:
    Qt Code:
    1. LD_LIBRARY_PATH=lib
    2. ./bin/instrumentPanel.debug
    To copy to clipboard, switch view to plain text mode 
    There is no facility to automatically break the circular dependencies you have built. One approach is to avoid separating dependent items between libraries. Another is to avoid doing things with B in A that require knowing more than that B exists (i.e. more than storing a pointer to a B instance). Exactly how you fix this is specific to your code and not really Qt specific.
    Bummer. Fortunately, there are ways around this. I can think of two:
    1) Change the code directory structure (not my first choice but definitely doable)
    2) Change the build structure to not build separate DLLs of each directory but maybe just one (e.g., libcore.dll) and have the main application just reference that library.

    Anyway, I've got other problems of trying to get the other 3rd-party packages to work on Windows. Gonna be a loooong day..

    Thanks for your help.

Similar Threads

  1. Replies: 4
    Last Post: 9th May 2016, 13:30
  2. Replies: 4
    Last Post: 11th August 2011, 09:02
  3. Unresolved external symbol "staticMetaObject"
    By sr71 in forum Qt Programming
    Replies: 5
    Last Post: 30th June 2010, 00:26
  4. Replies: 1
    Last Post: 10th April 2009, 19:07
  5. Replies: 16
    Last Post: 23rd May 2008, 11:12

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.