I have a QT project with 4 subprojects with the following names: exec (executable), sharedlib (dynamic library), sharedlib2 (other one dynamic library) and staticlib. All this is linked consequently as follows:
exec->sharedlib2->sharedlib->staticlib
In the static library is defined Staticlib class.
Now, when compiling all of this, I'm getting undefined reference error when trying to use that class (in exec project, main.cpp):
/home/user/temp/libproj/libproj/exec/main.cpp:9: error: undefined reference to `Staticlib::Staticlib()'
What am I doing wrong?
staticlib.h:
#ifndef STATICLIB_H
#define STATICLIB_H
#include <QDebug>
class Staticlib
{
public:
Staticlib();
void debugprint();
};
#endif // STATICLIB_H
sharedlib.pro:
QMAKE_LFLAGS += -Wl,--whole-archive,--allow-multiple-definition
LIBS += -L$$OUT_PWD/../staticlib/
LIBS += -lstaticlib
sharedlib2.pro:
LIBS += -L$$OUT_PWD/../sharedlib/
LIBS += -lsharedlib
exec.pro:
INCLUDEPATH += $$PWD/../staticlib
#doesnt work
LIBS += -L$$OUT_PWD/../sharedlib2
LIBS += -lsharedlib2
#works well
#//LIBS += -L$$OUT_PWD/../sharedlib/
#//LIBS += -lsharedlib
exec, main.cpp:
#include <QCoreApplication>
#include "staticlib.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Staticlib statlib;
statlib.debugprint();
return a.exec();
}
staticlib.pro
QT -= gui
TEMPLATE = lib
CONFIG += staticlib
CONFIG += c++17
SOURCES += \
staticlib.cpp
HEADERS += \
staticlib.h
staticlib.cpp
#include "staticlib.h"
#include <QDebug>
Staticlib::Staticlib()
{
}
void Staticlib::debugprint()
{
qDebug() << "Staticlib::debugprint()";
}
Related
I have a very very simple C++ class and tool is QT Creator.
I created a Non-QT project.
Have the SimpleClass class as given below
simpleclass.h
#ifndef SIMPLECLASS_H
#define SIMPLECLASS_H
class SimpleClass
{
public:
SimpleClass();
void printLine();
};
#endif // SIMPLECLASS_H
simpleclass.cpp
#include "simpleclass.h"
#include <iostream>
SimpleClass::SimpleClass()
{
printf("Hello , This is SimpleClass constructor\n");
}
void SimpleClass::printLine()
{
printf(" Printing a Line\n");
}
main.cpp
#include <iostream>
#include "simpleclass.h"
using namespace std;
int main()
{
cout << "Hello World!" << endl;
SimpleClass sc;
sc.printLine();
return 0;
}
All good till here!
The problem and confusion starts now!
Now my aim is to create a simple library testlibrary.lib and .dll and use it in another project.
I create a C++ library project called TestLibrary and try to build a library containing that one simple class(SimpleClass).
The files look as given below
TestLibrary.pro
QT += widgets
TARGET = TestLibrary
TEMPLATE = lib
DEFINES += TESTLIBRARY_LIBRARY
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
simpleclass.cpp
HEADERS += \
testlibrary_global.h \
simpleclass.h
unix {
target.path = /usr/lib
INSTALLS += target
}
testlibrary_global.h
#ifndef TESTLIBRARY_GLOBAL_H
#define TESTLIBRARY_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(TESTLIBRARY_LIBRARY)
# define TESTLIBRARYSHARED_EXPORT Q_DECL_EXPORT
#else
# define TESTLIBRARYSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // TESTLIBRARY_GLOBAL_H
simpleclass.h
#ifndef TESTLIBRARY_H
#define TESTLIBRARY_H
#include "testlibrary_global.h"
class TESTLIBRARYSHARED_EXPORT SimpleClass
{
public:
SimpleClass();
void printLine();
};
#endif // TESTLIBRARY_H
similarly, I have the simpleclass.cpp .
On building, The libraries TestLibrary.lib and TestLibrary.dll do get created but I am not able to use it in another project named UseLibrary.
I created a directory libs under a new project UseLibrary and copied TestLibrary.lib and TestLibrary.dll there.
UseLibrary.pro file looks as given below
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += \
main.cpp \
main.cpp
win32: LIBS += -L$$PWD/libs/ -lTestLibrary
INCLUDEPATH += $$PWD/libs
DEPENDPATH += $$PWD/libs
main.cpp(in the project UseLibrary)
#include <iostream>
#include "simpleclass.h" ---> error C1083: Cannot open include file :'simpleclass.h' :no such file or directory.
using namespace std;
int main()
{
cout << "Hello World!" << endl;
SimpleClass sc; --> Unknown Type name 'Simpleclass', # include header itself giving error so obvious issue
sc.printLine();
return 0;
}
#include "simpleclass.h" ---> error C1083: Cannot open include file :'simpleclass.h' :no such file or directory.
Why am I getting this error?? I read many library creation related posts and I am perplexed as to why most of the posts have
#include <QWidget> or #include <QtGlobal>. Why do we need these??
At least I never used these framework classes in my code! Are these really required in library creation? Why?
From what I understand, my project is a Non-QT project, so I do not need these. Can anyone point out if my understanding is correct?
What am I missing? and Finally, why is the simpleclass.h header file not getting included??
Cause
Your include path is set to $$PWD/libs:
INCLUDEPATH += $$PWD/libs
but the screenshot does not show simpleclass.h in that location.
Solution
Delete from UseLibrary.pro:
win32: LIBS += -L$$PWD/libs/ -lTestLibrary
INCLUDEPATH += $$PWD/libs
DEPENDPATH += $$PWD/libs
Right click the UseLibrary project in the project browser in QtCreator and select Add library
Select External library
Important: First click on browse on the "Include path" row and select the path, where the simpleclass.h is
Now, click browse on the "Library file" row and select the path, where the TestLibrary.lib is
Note: If you first select a library file path, QtCreator misleadingly fills out the include path box with the same path. Following the above steps should help you overcome this issue.
Using Qt (5.12, with r18b, clang), I create a shared library exporting some classes. Then I create a program doing some dynamic_cast between those classes. Under Windows with VS 2015, it works perfectly (with __declspec not posted below). Under Android with clang, dynamic_cast fails. I could read lots of topics like:
dynamic_cast an interface from a shared library which was loaded by lt_dlopen(libtool) doesn't work
So I tried to add some flags to my library project, tried many things (not sure which one is upposed to work):
QMAKE_LFLAGS += -Wl,--export-dynamic
QMAKE_LFLAGS += -Wl,-E
QMAKE_LFLAGS += -Bsymbolic
However, even if I see those flags are used upon link, it still fails.
Here is my MCVE:
dynamiccast_lib.pro:
TARGET = dynamiccast_lib
QT -= core
QT -= gui
QMAKE_LFLAGS += -Wl,--export-dynamic
QMAKE_LFLAGS += -Wl,-E
QMAKE_LFLAGS += -Bsymbolic
TEMPLATE = lib
CONFIG += shared
SOURCES += \
C:/dev/vobs_sde/public/lib/dynamiccast_lib/src/dynamiccast_lib.cpp
HEADERS += \
C:/dev/vobs_sde/public/lib/dynamiccast_lib/ifc/dynamiccast_lib.h
INCLUDEPATH += \
C:/dev/vobs_sde/public/lib/dynamiccast_lib/ifc
dynamiccast_prg.pro:
TARGET = dynamiccast_prg
QT -= core
QT -= gui
QMAKE_LFLAGS += -Wl,--export-dynamic
QMAKE_LFLAGS += -Wl,-E
QMAKE_LFLAGS += -Bsymbolic
TEMPLATE = app
SOURCES += \
C:/dev/vobs_sde/public/prg/dynamiccast_prg/src/main.cpp
INCLUDEPATH += \
C:/dev/vobs_sde/public/prg/dynamiccast_prg/inc \
C:/dev/vobs_sde/public/lib/dynamiccast_lib/ifc
LIBS += -l$$OUT_PWD/../../lib/dynamiccast_lib/libdynamiccast_lib.so
PRE_TARGETDEPS += $$OUT_PWD/../../lib/dynamiccast_lib/libdynamiccast_lib.so
dynamiccast_lib.h:
#pragma once
#include <iostream>
class BaseClass
{
public:
BaseClass()
{
}
virtual void show() = 0;
};
class DerivedClass : public BaseClass
{
public:
DerivedClass( int attr ) : attr( attr )
{
}
void show() override
{
std::cout << attr << std::endl;
}
private:
int attr;
};
class DYNAMICCAST_LIB_API Helper
{
public:
static BaseClass* CreateIntObject( int attr );
};
dynamiccast_lib.cpp:
#include "dynamiccast_lib.h"
BaseClass* Helper::CreateIntObject( int attr )
{
return new DerivedClass( attr );
}
main.cpp:
#include "dynamiccast_lib.h"
#include <iostream>
int main( int argc, char* argv[] )
{
BaseClass* ptr = Helper::CreateIntObject(3);
DerivedClass* casted = dynamic_cast< DerivedClass* >( ptr );
casted->show();
return 0;
}
This code crashs because casted is NULL. How can I make this simple code work under Android?
After some investigation, I could fix this issue myself. There is no need to add any link flag at all. I could get this fix (have dynamic_cast work) simply by adding a virtual method in BaseClass and implementing it in dynamiccast_lib.cpp.
Added in dynamiccast_lib.h:
virtual ~BaseClass;
Added in dynamiccast_lib.cpp:
BaseClass::~BaseClass
{
}
This makes dynamic_cast work just right from the program. Any virtual function will fix this (not only destructor), but the implementation MUST be in the source file, not in the header file (otherwise dynamic_cast still fails). That's surprising, but that's what I observed by testing.
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 7 months ago.
I've been banging my head against the wall on this one for the past few days. I am trying to incorporate googletest's gmock library into my Qt Autotest subdir project, but have been receiving the following linker error and I am unsure on how to resolve this. The main application compiles and runs perfectly fine.
tst_reptileprofile.obj : error LNK2019: unresolved external symbol "public: __thiscall DashboardWidget::DashboardWidget(void)" (??0DashboardWidget##QAE#XZ) referenced in function "private: void __thiscall TestReptileProfile::init(void)" (?init#TestReptileProfile##AAEXXZ)
Here is the test code:
#include <QtTest/QtTest>
#include <QCoreApplication>
#include <QObject>
#include "gmock/gmock.h"
#include "../Application/dashboardwidget.h"
class TestReptileProfile : public QObject
{
Q_OBJECT
public:
TestReptileProfile() {}
~TestReptileProfile() {}
private slots:
void initTestCase()
{
}
void cleanupTestCase()
{
}
void init()
{
dashboard_ = new DashboardWidget();
}
void cleanup()
{
delete dashboard_;
}
private:
DashboardWidget* dashboard_;
};
#include "tst_reptileprofile.moc"
QTEST_MAIN(TestReptileProfile)
DashboardWidget.h/.cpp
#pragma once
#include <QtWidgets/QWidget>
#include <QtWidgets/QAbstractButton>
namespace Ui {
class DashboardWidget;
}
class DashboardWidget : public QWidget
{
Q_OBJECT
public:
explicit DashboardWidget();
~DashboardWidget();
QAbstractButton* openProfileButton();
private:
Ui::DashboardWidget *ui;
QAbstractButton* openProfileButton_;
};
#include "dashboardwidget.h"
#include "ui_dashboardwidget.h"
DashboardWidget::DashboardWidget() :
ui(new Ui::DashboardWidget)
{
ui->setupUi(this);
openProfileButton_ = ui->openReptileProfilePageButton;
}
DashboardWidget::~DashboardWidget()
{
delete ui;
}
QAbstractButton* DashboardWidget::openProfileButton()
{
return openProfileButton_;
}
Subdirs Project .pro
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += \
Application \
AutoTests
AutoTests.depends = Application
Application.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = Application
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
mainview.cpp \
. . .
mainpresenter.cpp \
dashboardwidget.cpp \
FORMS += \
mainview.ui \
i_mainpresenter.h \
dashboardwidget.ui \
HEADERS += \
mainview.h \
dashboardwidget.h \
AutoTests.pro
QT += testlib
QT += gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += qt warn_on depend_includepath testcase
TEMPLATE = app
SOURCES += \
tst_reptileprofile.cpp
unix|win32: LIBS += -L$$PWD/../../../googletest/googlemock/msvc/2015/Win32-Release/ -lgmock
INCLUDEPATH += $$PWD/../../../googletest/googlemock/msvc/2015/Win32-Release
DEPENDPATH += $$PWD/../../../googletest/googlemock/msvc/2015/Win32-Release
INCLUDEPATH += D:\googletest\googlemock\include\
INCLUDEPATH += D:\googletest\googletest\include\
I also tried converting the project into a Visual Studio project which causes a compilation error instead.
Error C2059 syntax error: '.' AutoTests ProjectDir\tst_reptileprofile.cpp 63
Thanks
There are two points. The first thing: you are creating two executables (application and AutoTest). To test your production code you have to build it into a library.
TEMPLATE = lib
That means, one should create two executables, for testing and for the application. The executables need to be linked against the new library.
e.g:
LIBS += -L../lib/debug -llib
At the end you have three subdirectories and .pro-files.
The second thing: The symbols in the library has to be exported if the library is created and imported when you are linking against the library. This can be done with the preprocessor definition: TEST_COMMON_DLLSPEC.
You find the complete how to in the following link:
https://wiki.qt.io/How_to_create_a_library_with_Qt_and_use_it_in_an_application
This tutorial isn't with googletest but you can use it similar.
I am trying to use Octave with Qt creator on Windows but I don't no why i can't succeed to link this library on this OS. I already tried on Ubuntu and everything works so i am a little bit lost...
I have octave3.6.4 (gcc 4.6.2) and i use the compiler gcc4.6.2 with Qt Creator.
my .pro file:
#-------------------------------------------------
#
# Project created by QtCreator 2015-01-26T11:35:00
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = untitled
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
LIBS += -L$$PWD/../../../../Octave/Octave3.6.4_gcc4.6.2/lib/octave/3.6.4/ -loctave -loctinterp -lcruft
INCLUDEPATH += $$PWD/../../../../Octave/Octave3.6.4_gcc4.6.2/include
DEPENDPATH += $$PWD/../../../../Octave/Octave3.6.4_gcc4.6.2/include
PRE_TARGETDEPS += $$PWD/../../../../Octave/Octave3.6.4_gcc4.6.2/lib/octave/3.6.4/libcruft.dll.a
PRE_TARGETDEPS += $$PWD/../../../../Octave/Octave3.6.4_gcc4.6.2/lib/octave/3.6.4/liboctave.dll.a
PRE_TARGETDEPS += $$PWD/../../../../Octave/Octave3.6.4_gcc4.6.2/lib/octave/3.6.4/liboctinterp.dll.a
my .h file:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <octave-3.6.4/octave/oct.h>
#include <octave-3.6.4/octave/octave.h>
#include <octave-3.6.4/octave/parse.h>
#include <octave-3.6.4/octave/toplev.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
And i have many link errors such as C2144 syntax error ...
I have been migrating from Qt 4.8.5 to Qt 5.3.0 recently, and these are the related information:
Windows 7 32 bit
Qt 3.1.1
MSVC 2010 compiler (Both my Qt versions are pre-compiled package of MSVC2010 edition)
debugger from Win7 SDK
Now I've been trapped by a problem that I keep getting compilation errors:
fatal error C1083: Cannot open include file
from those header files inside subdirectories, for example, #include "FooFolder/bar.h".
The compiler is unable to locate all this kind of headers and I am totally befuddled since:
The Intellisense works well.
If I change back to old kit Qt 4.8.5, it compiles fine
Both kits use the same MSVC compiler.
Here is my .pro file:
QT += core gui script
QT += printsupport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = MyApp
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
qcustomplot.cpp \
dialogs/filterdialog.cpp \
databox/databox.cpp \
databox/datom.cpp \
#... and more FooFolder/bar.cpp
HEADERS += mainwindow.h \
qcustomplot.h \
dialogs/filterdialog.h \
databox/databox.h \
databox/datom.h \
#... and more FooFolder/bar.h
RESOURCES += \
resources.qrc
win32: LIBS += -LC:/ADLINK/UDASK/lib/ -lusb-dask \
INCLUDEPATH += C:/ADLINK/UDASK/include \
DEPENDPATH += C:/ADLINK/UDASK/include \
include(qext/qextserialport.pri)
and here is one of the .h file that files to include other subdirectoried headers
#ifndef SETWINDOW_H
#define SETWINDOW_H
#include <QObject>
#include "databox/databox.h" // <---fatal error C1083: Cannot open include file
class SetWindow: public QObject
{
Q_OBJECT
public:
SetWindow();
public Q_SLOTS:
void setPointNum(int n);
void setStepSize(int s);
int getPointNum();
int getStepSize();
void requestSignal();
Q_SIGNALS:
void sendParameters(int p, int s);
private:
QString DynamicString;
DataBox *presentData;
int m_PointNum;
int m_StepSize;
};
#endif // SETWINDOW_H
and the header file failed to be included:
#ifndef DATABOX_H
#define DATABOX_H
#include <QVector>
#include <QFile>
#include <QMap>
#include <QString>
#include "datom.h"
class Measurement
{
public:
Measurement();
void setNumChan(int n);
void setADRange(QString &s);
void setSamplingRate(int n);
void setTimeBase(double d);
int NumChan;
QString ADRange;
int SamplingRate;
double TimeBase;
};
class DataBox
{
public:
DataBox();
void setCurrentFile(QString path);
void loadData();
void cleanAll();
QVector<double>* py_0;
QVector<double>* py_1;
QVector<double>* ptimeStamp;
QVector<double>* pi_M;
QVector<double>* py_M;
QVector<double>* py_W;
QMap<double, double> AI_0;
QMap<double, double> AI_1;
QMap<int, double> AI0;
QMap<int, double> AI1;
double timeBase;
Measurement parameters;
QVector<Datom> *dataPoints;
private:
QString currentFile;
};
#endif // DATABOX_H
These seem to be incorrect:
win32: LIBS += -LC:/ADLINK/UDASK/lib/ -lusb-dask \
INCLUDEPATH += C:/ADLINK/UDASK/include \
DEPENDPATH += C:/ADLINK/UDASK/include \
1) \ means it joins the next line which is not what you wish. It is not an issue for the lines with followed empty line, but it is not good for the INCLUDEPATH in here, and if you replace the empty lines with some containment, you could run into issues with the other lines, too.
2) You will also need to put $$PWD into the includepath to get the project root "registered" since your include should start from there, not the current working directory of the source since that is not the right route as you can assume.
Therefore, you would be writing something like this:
win32: LIBS += -LC:/ADLINK/UDASK/lib/ -lusb-dask
INCLUDEPATH += $$PWD C:/ADLINK/UDASK/include
DEPENDPATH += C:/ADLINK/UDASK/include