hashDefine
hashDefine

Reputation: 1491

Qt creator: c++: undefined reference to Class::Function

I am creating two c++ projects in my Qt creator. The first is an Application project and the other is unit-test project. the two projects, separately, work fine. However, when linking the two together I face a little problem.

I am including #INCLUDEPATH applicationProjectPath in .pro file in the unit-test project. then #include myClass from the application project in the main.cpp of the unit-test project. then, creating a myObject from myClass and calling a function within that object.

when compiling, this error appears:

undefined reference to `myObject::function' 

however, when adding #SOURCES applicationProjectPath/myClass.cpp to the .pro file of the unit-test project (while keeping the #INCLUDEPATH applicationProjectPath), everything is working (i.e.: the test units are executed)

again when removing the #INCLUDEPATH from the .pro, it again crashes .

I thought if I included #SOURCES, then I don't need to include the #INCLUDEPATH. and if I included the #INCLUDEPATH, I should not include #SOURCES (at least not with the full path, just the .cpp file and then the compiler should look for both directories, the default one and the added one).

so, my question is: why is this happening

Upvotes: 6

Views: 47283

Answers (3)

Sometimes Qt displays this error when you are using inline in a wrong way, so check your inline'd functions.

Upvotes: 0

Uflex
Uflex

Reputation: 1426

Your unit tests will need to compile the classes in your project that you want to unit-test. So you need to add the include in both project (otherwise the test project will not know the classes you are trying to test). And the linker needs to link to the project's code as well, as your tests will use the classes.

One way is to add the classes you want to test in your test project as well and compile them again when you compile your unit test project but this is tedious and not really handy as every time you want to add a class, you need to add it to both .pro files (hint, you can use wildcards in the .pro files, like *.cpp to add all source files in a folder to a project).

A better approach in my opinion is to setup the project you want to test as a static library, separating it from the application: you have another project which is an application, containing only the main.cpp linking to that static library.

Here is a representation of the folder containing the project:

Project.pro #subdir project
UIProject/ #static lib
    UIProject.pro
    #all your classes here
MainProject/ #application
    MainProject.pro
    main.cpp
UITestProject/ #unit tests of UIProject (linking to it)
    UITestProject.pro
    #all your UI test classes here

Project.pro:

TEMPLATE = subdirs
SUBDIRS += UIProject
SUBDIRS += MainProject
SUBDIRS += UITestProject

UIProject.pro:

# project type
TEMPLATE = lib

# library type
CONFIG += staticlib

HEADERS += *.h
SOURCES += *.cpp

MainProject.pro:

#[...]
TEMPLATE = app
SOURCES += main.cpp
INCLUDEPATH += ../UIProject/
DEPENDPATH += $${INCLUDEPATH} # force rebuild if the headers change

# link against UILib
_UI_LIB = ../UIProject/
CONFIG(debug, debug|release) {
    win32: _UI_LIB = $$join(_UI_LIB,,,debug/UIProject.lib)
} else {
    win32: _UI_LIB = $$join(_UI_LIB,,,release/UIProject.lib)
}
LIBS += $${_UI_LIB}
PRE_TARGETDEPS += $${_UI_LIB}

UITestProject.pro:

#[...]
TEMPLATE = app
HEADERS += *.h
SOURCES += *.cpp

INCLUDEPATH += ../UIProject/
DEPENDPATH += $${INCLUDEPATH} # force rebuild if the headers change

# link against UILib
_UI_LIB = ../UIProject/
CONFIG(debug, debug|release) {
    win32: _UI_LIB = $$join(_UI_LIB,,,debug/UIProject.lib)
} else {
    win32: _UI_LIB = $$join(_UI_LIB,,,release/UIProject.lib)
}
LIBS += $${_UI_LIB}
PRE_TARGETDEPS += $${_UI_LIB}

You would have to edit that to match your project but the main things are here. It should work as I copied it from one of my project, providing I didn't add any errors.

Upvotes: 4

Lol4t0
Lol4t0

Reputation: 12547

you should include your cpp file to the project to tell build system (qmake) to compile the given file.

When you add myClass.cpp to test project, it gets compiled, otherwise does not.

So, when you will not add cpp file to the project, you'll get linker error.

Includes are just handled separately

When you add new path to INCLUDEPATH, compiler will add that pass to headers search list

When you add applicationProjectPath to the include path, compiler will search headers there. It is important, as allows compiler to find myClass.h

If you will not add path to headers search list, compiler will not be able to compile your main.cpp and you'll get compilation error.

You, however, can just specify (relative) path to your myClass.h in your test-project's main:

#include "../applicationProjectPath/myClass.h"

Summing up

You need add your source files to test project and add your headers path to test project's include search list.

Further reading

What is an undefined reference/unresolved external symbol error and how do I fix it?

Upvotes: 2

Related Questions