Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Undefined reference, altough references in library exists



  • Hello,

    i have some strange reoccouring linker error which i can't track down. The last time i had this error it somehow disappeared after deleting the *.pro.user file, but this time, it just keeps reappearing.

    My subdirs pro file:

    TEMPLATE = subdirs
    
    common.subdir = src/common
    common.target = sub-src-common
    
    atctrl.subdir = src/atctrl
    atctrl.target = sub-src-atctrl
    atctrl.depends = common
    
    app.subdir = src/app
    app.target = sub-src-app
    app.depends = common atctrl
    
    SUBDIRS = common atctrl app
    

    The pro file for the app project:

    QT += quick
    
    CONFIG += c++17 static
    
    DEFINES += QT_DEPRECATED_WARNINGS
    DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000
    DEFINES += QT_MESSAGELOGCONTEXT
    
    QT += serialport
    
    INCLUDEPATH += $$PWD/src
    
    SOURCES += \
            src/main.cpp
    
    #HEADERS += 
    
    TARGET = app
    
    # common
    win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../common/release/ -lcommon
    else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../common/debug/ -lcommon
    else:unix:!macx: LIBS += -L$$OUT_PWD/../common/ -lcommon
    
    INCLUDEPATH += $$PWD/../common
    DEPENDPATH += $$PWD/../common
    
    win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../common/release/libcommon.a
    else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../common/debug/libcommon.a
    else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../common/release/common.lib
    else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../common/debug/common.lib
    else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../common/libcommon.a
    
    # atctrl
    win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../atctrl/release/ -latctrl
    else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../atctrl/debug/ -latctrl
    else:unix:!macx: LIBS += -L$$OUT_PWD/../atctrl/ -latctrl
    INCLUDEPATH += $$PWD/../atctrl
    DEPENDPATH += $$PWD/../atctrl
    win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../atctrl/release/libatctrl.a
    else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../atctrl/debug/libatctrl.a
    else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../atctrl/release/atctrl.lib
    else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../atctrl/debug/atctrl.lib
    else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../atctrl/libatctrl.a
    

    The pro file for the atctrl library:

    QT -= gui
    
    TEMPLATE = lib
    CONFIG += c++17 staticlib
    
    DEFINES += QT_DEPRECATED_WARNINGS
    DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000
    DEFINES += QT_MESSAGELOGCONTEXT
    
    SOURCES += \
        atctrl/atctrl.cpp
    
    HEADERS += \
        atctrl/atctrl.h
        
    QT += serialport
    
    # common
    win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../common/release/ -lcommon
    else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../common/debug/ -lcommon
    else:unix:!macx: LIBS += -L$$OUT_PWD/../common/ -lcommon
    
    INCLUDEPATH += $$PWD/../common
    DEPENDPATH += $$PWD/../common
    
    win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../common/release/libcommon.a
    else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../common/debug/libcommon.a
    else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../common/release/common.lib
    else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../common/debug/common.lib
    else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../common/libcommon.a
    

    The pro file for the common library:

    QT -= gui
    
    TEMPLATE = lib
    CONFIG += c++17 staticlib
    
    DEFINES += QT_DEPRECATED_WARNINGS
    DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000
    DEFINES += QT_MESSAGELOGCONTEXT
    
    SOURCES += \
        common/serial_base/serial_base.cpp
    
    HEADERS += \
        common/serial_base/serial_base.h 
    
    QT += serialport
    
    !isEmpty(target.path): INSTALLS += target
    

    In the atctrl library there is the class ATCtrl::cATCtrl which derives from SerialBase::cSerialBase from the common library.

    In the app project i'm using the ATCtrl::cATCtrl class. So the dependency goes like app (project) -> atrctrl (staticlib) -> common (staticlib).

    When i'm building the app project, i get this linker error:
    cfe610bd-d9b5-4cfd-b85b-369dc6f6fb8d-grafik.png

    The complete error log:

    <build_debug>/src/atctrl/debug/libatctrl.a(atctrl.o): In function `ATCtrl::cATCtrl::~cATCtrl()':
    <build_debug>\src\atctrl/../../../keyboard/src/atctrl/atctrl/atctrl.h:42: undefined reference to `SerialBase::cSerialBase::~cSerialBase()'
    <build_debug>/src/atctrl/debug/libatctrl.a(atctrl.o): In function `ATCtrl::cATCtrl::cATCtrl(QObject*)':
    <build_debug>\src\atctrl/../../../keyboard/src/atctrl/atctrl/atctrl.cpp:48: undefined reference to `SerialBase::cSerialBase::cSerialBase(QObject*)'
    <build_debug>\src\atctrl/../../../keyboard/src/atctrl/atctrl/atctrl.cpp:48: undefined reference to `SerialBase::cSerialBase::~cSerialBase()'
    <build_debug>/src/atctrl/debug/libatctrl.a(atctrl.o): In function `ATCtrl::cATCtrl::init(QString)':
    <build_debug>\src\atctrl/../../../keyboard/src/atctrl/atctrl/atctrl.cpp:64: undefined reference to `SerialBase::cSerialBase::open(QString)'
    <build_debug>/src/atctrl/debug/libatctrl.a(atctrl.o): In function `ATCtrl::cATCtrl::disableLocalEcho()':
    <build_debug>\src\atctrl/../../../keyboard/src/atctrl/atctrl/atctrl.cpp:132: undefined reference to `SerialBase::cSerialBase::handleRequest(QString const&, QString const&, QStringList&)'
    <build_debug>/src/atctrl/debug/libatctrl.a(atctrl.o): In function `ATCtrl::cATCtrl::AT()':
    <build_debug>\src\atctrl/../../../keyboard/src/atctrl/atctrl/atctrl.cpp:148: undefined reference to `SerialBase::cSerialBase::handleRequest(QString const&, QString const&, QStringList&)'
    <build_debug>/src/atctrl/debug/libatctrl.a(atctrl.o): In function `ATCtrl::cATCtrl::enableGPS(bool)':
    <build_debug>\src\atctrl/../../../keyboard/src/atctrl/atctrl/atctrl.cpp:164: undefined reference to `SerialBase::cSerialBase::handleRequest(QString const&, QString const&, QStringList&)'
    <build_debug>/src/atctrl/debug/libatctrl.a(atctrl.o): In function `ATCtrl::cATCtrl::resetGPS(int)':
    <build_debug>\src\atctrl/../../../keyboard/src/atctrl/atctrl/atctrl.cpp:182: undefined reference to `SerialBase::cSerialBase::handleRequest(QString const&, QString const&, QStringList&)'
    <build_debug>/src/atctrl/debug/libatctrl.a(atctrl.o): In function `ATCtrl::cATCtrl::getGPSStatus(int)':
    <build_debug>\src\atctrl/../../../keyboard/src/atctrl/atctrl/atctrl.cpp:199: undefined reference to `SerialBase::cSerialBase::handleRequest(QString const&, QString const&, QStringList&)'
    <build_debug>/src/atctrl/debug/libatctrl.a(atctrl.o):<build_debug>\src\atctrl/../../../keyboard/src/atctrl/atctrl/atctrl.cpp:217: more undefined references to `SerialBase::cSerialBase::handleRequest(QString const&, QString const&, QStringList&)' follow
    <build_debug>/src/atctrl/debug/libatctrl.a(moc_atctrl.o): In function `ATCtrl::cATCtrl::qt_metacast(char const*)':
    <build_debug>\src\atctrl/debug/moc_atctrl.cpp:221: undefined reference to `SerialBase::cSerialBase::qt_metacast(char const*)'
    <build_debug>/src/atctrl/debug/libatctrl.a(moc_atctrl.o): In function `ATCtrl::cATCtrl::qt_metacall(QMetaObject::Call, int, void**)':
    <build_debug>\src\atctrl/debug/moc_atctrl.cpp:226: undefined reference to `SerialBase::cSerialBase::qt_metacall(QMetaObject::Call, int, void**)'
    <build_debug>/src/atctrl/debug/libatctrl.a(moc_atctrl.o):moc_atctrl.cpp:(.rdata+0x620): undefined reference to `SerialBase::cSerialBase::staticMetaObject'
    

    The linker command which fails is the following (i replaced the build dir with <build_debug>):

    g++ -Wl,-subsystem,windows -mthreads -o debug/app.exe debug/main.o debug/backend.o debug/moc_backend.o  -L"<build_debug>/src/common/debug" -lcommon -L"<build_debug>/src/atctrl/debug" -latctrl D:/Qt/5.14.2/mingw73_64/lib/libQt5Quick.a D:/Qt/5.14.2/mingw73_64/lib/libQt5Gui.a D:/Qt/5.14.2/mingw73_64/lib/libQt5QmlModels.a D:/Qt/5.14.2/mingw73_64/lib/libQt5Qml.a D:/Qt/5.14.2/mingw73_64/lib/libQt5Network.a D:/Qt/5.14.2/mingw73_64/lib/libQt5SerialPort.a D:/Qt/5.14.2/mingw73_64/lib/libQt5Core.a  -lmingw32 D:/Qt/5.14.2/mingw73_64/lib/libqtmain.a -LC:/openssl/lib -LC:/Utils/my_sql/mysql-5.7.25-winx64/lib -LC:/Utils/postgresql/pgsql/lib -lshell32 
    

    The two static libraries are included (-lcommon -latctrl) in the linker command.

    Now when i'm looking into libcommon.a with nm (nm -A -C libcommon.a), i can find all the references which the linker says it is not finding it:

    <...>
    libcommon.a:serial_base.o:000000000000014c T SerialBase::cSerialBase::open(QString)
    libcommon.a:serial_base.o:0000000000000f16 T SerialBase::cSerialBase::close()
    <...>
    libcommon.a:serial_base.o:0000000000000088 T SerialBase::cSerialBase::cSerialBase(QObject*)
    libcommon.a:serial_base.o:0000000000000088 T SerialBase::cSerialBase::cSerialBase(QObject*)
    libcommon.a:serial_base.o:000000000000005e T SerialBase::cSerialBase::~cSerialBase()
    libcommon.a:serial_base.o:0000000000000000 T SerialBase::cSerialBase::~cSerialBase()
    libcommon.a:serial_base.o:0000000000000000 T SerialBase::cSerialBase::~cSerialBase()
    

    What am i missing?

    Qt Creator Version 4.12.0
    Qt 5.14.2 (mingw730_64)

    I appreciate any help here, thanks.

    Best regards,
    Kevin


  • Qt Champions 2019

    The link order is wrong, -lactrl must come first,s ee also e.g. here


  • Qt Champions 2019

    @kkettinger said in Undefined reference, altough references in library exists:

    g++ -Wl,-subsystem,windows -mthreads -o debug/app.exe debug/main.o debug/backend.o debug/moc_backend.o -L"<build_debug>/src/common/debug" -lcommon -L"<build_debug>/src/atctrl/debug" -latctrl D:/Qt/5.14.2/mingw73_64/lib/libQt5Quick.a D:/Qt/5.14.2/mingw73_64/lib/libQt5Gui.a D:/Qt/5.14.2/mingw73_64/lib/libQt5QmlModels.a D:/Qt/5.14.2/mingw73_64/lib/libQt5Qml.a D:/Qt/5.14.2/mingw73_64/lib/libQt5Network.a D:/Qt/5.14.2/mingw73_64/lib/libQt5SerialPort.a D:/Qt/5.14.2/mingw73_64/lib/libQt5Core.a -lmingw32 D:/Qt/5.14.2/mingw73_64/lib/libqtmain.a -LC:/openssl/lib -LC:/Utils/my_sql/mysql-5.7.25-winx64/lib -LC:/Utils/postgresql/pgsql/lib -lshell32

    The paths look strange: -L"<build_debug>/src/common/debug" -lcommon -L"<build_debug>/src/atctrl/debug"
    What is <build_debug>?
    Also, if common is a static lib when your pro file is wrong as you are linking dynamically.



  • I have replaced the build-dir with <build_debug>, the original path is:

    D:/Dev/project01/src/build-subdirs-Desktop_Qt_5_14_2_MinGW_64_bit-Debug/
    

    @jsulm said in Undefined reference, altough references in library exists:

    Also, if common is a static lib when your pro file is wrong as you are linking dynamically.

    Why? I added "CONFIG += static" in the project pro-file, isn't that correct?



  • This is getting strange.. when i'm using SerialBase::cSerialBase (from common lib) directly in the app project (instantiating in main.cpp), suddenly the linker finds everything.

    It seems like the linker doesn't find the dependency to SerialBase::cSerialBase (common lib) when only using ATCtrl::cATCtrl (atctrl lib).

    Just for clarification, here the headers for the libraries:

    common.pro:

    class cSerialBase: public QObject
    {
        Q_OBJECT
    }
    

    atctrl.pro:

    class cATCtrl: public SerialBase::cSerialBase
    {
        Q_OBJECT
    }
    

    Usage in app.pro (main.cpp) which doesn't work (linker doesn't find SerialBase::cSerialBase):

    #include <atctrl/atctrl.h>
    
    int main(int argc, char *argv[])
    {
        ATCtrl::cATCtrl atctrl;
        return 0;
    }
    

    Usage in app.pro (main.cpp) which strangly does work:

    #include <atctrl/atctrl.h>
    
    int main(int argc, char *argv[])
    {
        ATCtrl::cATCtrl atctrl;
        SerialBase::cSerialBase serialBase;
        return 0;
    }
    

  • Qt Champions 2019

    The link order is wrong, -lactrl must come first,s ee also e.g. here



  • I switched the order in the app.pro file for the common and atctrl lib and now it works. Thank you very much.


Log in to reply