0

I'm studying linking shared libraries in QT, tried tutorials but nothing works. Can somebody help me to find a mistake?

I have an error "Undefined reference to test" when I'm compiling my test project.

Project where i'm trying to link my lib: loadTestLib.pro:

#-------------------------------------------------
#
# Project created by QtCreator 2013-04-22T15:32:30
#
#-------------------------------------------------

QT       += core

QT       -= gui

TARGET = loadTestLib
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE = app


SOURCES += main.cpp
LIBS+=-L../libtest.so.1.0.0

HEADERS += \
    test_global.h \
    test.h

main.cpp:

#include <QCoreApplication>
#include "test.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Test test;
    return a.exec();
}

test_global.h:

#ifndef TEST_GLOBAL_H
#define TEST_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(TEST_LIBRARY)
#  define TESTSHARED_EXPORT Q_DECL_EXPORT
#else
#  define TESTSHARED_EXPORT Q_DECL_IMPORT
#endif

#endif // TEST_GLOBAL_H

test.h:

#ifndef TEST_H
#define TEST_H

#include "test_global.h"

class TESTSHARED_EXPORT Test
{
public:
    Test();
};

#endif // TEST_H

Library:

test_global.h:

#ifndef TEST_GLOBAL_H
#define TEST_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(TEST_LIBRARY)
#  define TESTSHARED_EXPORT Q_DECL_EXPORT
#else
#  define TESTSHARED_EXPORT Q_DECL_IMPORT
#endif

#endif // TEST_GLOBAL_H

test.cpp:

#include "test.h"


Test::Test()
{
}

test.h:

#ifndef TEST_H
#define TEST_H

#include "test_global.h"

class TESTSHARED_EXPORT Test
{
public:
    Test();
};

#endif // TEST_H

test.pro:

#-------------------------------------------------
#
# Project created by QtCreator 2013-04-22T15:31:04
#
#-------------------------------------------------

QT       -= gui

TARGET = test
TEMPLATE = lib

DEFINES += TEST_LIBRARY

SOURCES += test.cpp

HEADERS += test.h\
        test_global.h

unix:!symbian {
    maemo5 {
        target.path = /opt/usr/lib
    } else {
        target.path = /usr/lib
    }
    INSTALLS += target
}

Compile output:

13:49:12: Running steps for project loadTestLib...
13:49:12: Configuration unchanged, skipping qmake step.
13:49:12: Starting: "/usr/bin/make" -w
make: Entering directory `/home/bonart/Workspace/test/loadTestLib-build-Desktop_Qt_5_0_1_GCC_64bit-_______'
/home/bonart/Qt5.0.1/5.0.1/gcc_64/bin/qmake -spec linux-g++-64 CONFIG+=debug CONFIG+=declarative_debug CONFIG+=qml_debug -o Makefile ../loadTestLib/loadTestLib.pro
make: Leaving directory `/home/bonart/Workspace/test/loadTestLib-build-Desktop_Qt_5_0_1_GCC_64bit-_______'
make: Entering directory `/home/bonart/Workspace/test/loadTestLib-build-Desktop_Qt_5_0_1_GCC_64bit-_______'
g++ -m64 -Wl,-rpath,/home/bonart/Qt5.0.1/5.0.1/gcc_64 -Wl,-rpath,/home/bonart/Qt5.0.1/5.0.1/gcc_64/lib -o loadTestLib main.o   -L./libs -L../libs/-ltest -L/home/bonart/Qt5.0.1/5.0.1/gcc_64/lib -lQt5Core -lpthread 
main.o: In function `main':
/home/bonart/Workspace/test/loadTestLib-build-Desktop_Qt_5_0_1_GCC_64bit-_______/../loadTestLib/main.cpp:7: undefined reference to `Test::Test()'
make: Leaving directory `/home/bonart/Workspace/test/loadTestLib-build-Desktop_Qt_5_0_1_GCC_64bit-_______'
collect2: ld returned 1 exit status
make: *** [loadTestLib] Error 1
13:49:12: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project loadTestLib (kit: Desktop Qt 5.0.1 GCC 64bit)
When executing step 'Сборка'

$ nm -D for my library gives me:

w _Jv_RegisterClasses
                 U _Unwind_Resume
                 U _Z17qt_message_output9QtMsgTypeRK18QMessageLogContextRK7QString
                 U _ZN10QArrayData10deallocateEPS_mm
                 U _ZN11QTextStreamD1Ev
                 U _ZN11QTextStreamlsERK7QString
                 U _ZN11QTextStreamlsEc
0000000000000bb0 T _ZN4TestC1Ev
0000000000000bb0 T _ZN4TestC2Ev
0000000000000d90 W _ZN6QDebugD1Ev
0000000000000d90 W _ZN6QDebugD2Ev
                 U _ZN7QString15fromUtf8_helperEPKci
                 U _ZNK14QMessageLogger5debugEv
                 U _ZTISt9bad_alloc
                 U _ZdlPv
0000000000202080 A __bss_start
                 U __cxa_begin_catch
                 U __cxa_end_catch
                 w __cxa_finalize
                 w __gmon_start__
                 U __gxx_personality_v0
0000000000202080 A _edata
0000000000202090 A _end
0000000000000ec8 T _fini
00000000000009e8 T _init
madmaker
  • 9
  • 1
  • 1
  • 5
  • Shouldn't this be tagged as QMake instead of CMake? – drescherjm Apr 22 '13 at 15:11
  • do you have your library built successfully? and if yes, then is output location correct (relative to main application)? – evilruff Apr 22 '13 at 18:46
  • Yes, it's built successfully – madmaker Apr 23 '13 at 07:58
  • For future vistors: `LIBS+=-L../libtest.so.1.0.0` is a simple blunder which causes `libtest.so.1.0.0` not to be input to the linkage. Having corrected it in response to @Troubadour's answer, the OP found the app could not load `libtest.so.1` at runtime unless copied to `/usr/lib`, one of the loader's trusted directories. Of course it couldn't, without use of either `LD_LIBRARY_PATH` or `ldconfig`. Nothing to see here. – Mike Kinghan Nov 07 '18 at 10:59

3 Answers3

1

Your LIBS line in In loadTestLib.pro is wrong. It should be

LIBS+=-L.. -ltest

Alternatively you can put this on two lines (and use spaces too) for clarity

LIBS += -L..
LIBS += -ltest

Note that this will link against ../libtest.so. Generally you link against the file without a version suffix at build time and a file with a version number at runtime.

Troubadour
  • 13,334
  • 2
  • 38
  • 57
  • Now I get this error: /usr/bin/ld: cannot find -ltest make: Leaving directory `/home/bonart/Workspace/test/loadTestLib-build-Desktop_Qt_5_0_1_GCC_64bit-_______' collect2: ld returned 1 exit status make: *** [loadTestLib] Error 1 – madmaker Apr 23 '13 at 07:57
  • Ok, I've wrote LIBS+= "absolute path to lib/libtest.so.1.0.0" Now it compiles successfully. But when I run app, console says that it can't find "libtest.so.1". When I put libtest.so, libtest.so.1, libtest.so.1.0, libtest.so.1.0.0 to /usr/lib - everything works. Do you know why app can't see lib in it's folder? I use Ubuntu. – madmaker Apr 24 '13 at 17:01
  • @madmaker: A couple of points first. 1. Looking at the build output you added to your question it looks as if you are missing the space before `-ltest`. 2. If you pass a relative path to `-L` then make sure it's correct relative to where `g++` is invoked. Now to your question about running the application. Runtime linking is different to build time linking. The former is done by `ld.so` on Linux and you will want to consult the `man` page for that on your system. Usually the easiest way to get going is add the correct path to your `LD_LIBRARY_PATH` environment variable. – Troubadour Apr 24 '13 at 21:23
0

In addition to what Troubadour said, you should tell linker where it can find the lib. You can set QMAKE_LIBDIR in .pro file, or add directory that contain your library to /etc/ld.so.conf and use ldconfig command.

SpongeBobFan
  • 964
  • 5
  • 13
  • Now again I get an error "Undefined reference to Test::test()". Nothing changed. And I noticed if I write "LIBS+=-L../-ltest" - without whitespace - it's "undefined reference". If i write "LIBS+=-L../ -ltest" - with whitespace I get an error "cannot find -ltest". What's wrong? – madmaker Apr 23 '13 at 09:08
  • I've added compile output to my question on top – madmaker Apr 23 '13 at 09:53
  • Everything looks right, try to use `nm` util to watch if your library export function. [Here is the link about using nm.](http://stackoverflow.com/questions/4514745/how-do-i-view-the-list-of-functions-a-linux-shared-library-is-exporting) Also you can try to rebuild your project using `qmake && make clean && make`. – SpongeBobFan Apr 23 '13 at 10:20
  • Ok, I've wrote LIBS+= "absolute path to lib/libtest.so.1.0.0" Now it compiles successfully. But when I run app, console says that it can't find "libtest.so.1". When I put libtest.so, libtest.so.1, libtest.so.1.0, libtest.so.1.0.0 to /usr/lib - everything works. Do you know why app can't see lib in it's folder? I use Ubuntu. – madmaker Apr 24 '13 at 17:02
  • You can add lib folder to `/etc/ld.so.conf` (or wherever `ld.so.conf` placed, I don't remember it clearly). Then you should run `ldconfig`. But for clear answer about app's lib folder better to google or ask someone who more familliar with linux programming than me, I'm not sure someone else will see your comment here. And try to avoid absolute paths in `.pro` file, did you tried `QMAKE_LIBDIR = your_relative_path_to_lib`? – SpongeBobFan Apr 25 '13 at 07:58
0

In Windows absolute path to library and it's name with .dll worked for me. In Ubuntu it's also compiled successfully with same way but application finds library only if you put it to /usr/lib

madmaker
  • 9
  • 1
  • 1
  • 5