Using Qt lib macros with static libs and apps
-
Hi, I've run into a situation that I'm not quite sure how to resolve. Here is the scenario:
I have a static lib, let's call it glib.
In glib I have 2 files called app.hpp and app.cpp.
Inside of these files are subclasses of QApplication and QCoreApplication.
I want to be able to use the subclasses of QCoreApplication inside of apps that do not have the Qt GUI framework ( QT -= gui), i.e command line apps.I now have a cmd line app called capp.
Inside of capp, I want to use my custom subclasses of QCoreApplication.
So I #include <app.hpp> and add the necessary lib to my cmd line app's project file.However, because this is a cmd line app ( QT -= gui), it of course complains that <QApplication> does not exist.
So in an attempt to resolve this, I wrapped all of the "GUI" related code in app.hpp and app.cpp with a QT_GUI_LIB macro ifdef.Keep in mind that app.hpp and app.cpp is compiled as a static lib. That means that the generated static lib still contains all the symbols for the subclasses of both QApplication and QCoreApplication, since the lib itself is compiled with QT += gui widgets
I can of course split up the GUI and non-gui code into 2 separate files, but wanted to know if my current approach should work and if I'm just doing something incorrectly.
Thanks for any help
-
Hi,
Can you show your header content ?
Note that it's indeed better to have these two classes in separate headers. That will makes things way clearer when using your library.
-
So the static lib builds perfectly fine. I've also tried using the QT_GUI_LIB macro instead but same result. I get these compile errors when trying to use the static lib in a non-gui app. Perhaps the easiest solution is to just spit up the GUI and non-GUI code into separate files.
This is what my app's project file looks like:
LIBS_DEPTH = ../.. LIB_DEPENDENCIES = \ momalib \ gedilib \ gselib \ tools \ gse_streams include(../../custom.pri) # Input HEADERS += mainclass.hpp SOURCES += main.cpp mainclass.cpp CONFIG += qt console CONFIG -= app_bundle QT -= gui QT += network
Generated compile error:
Undefined symbols for architecture x86_64: "QApplication::qt_metacall(QMetaObject::Call, int, void**)", referenced from: vtable for ExceptionSafeApplication in libgselib.a(apputil.o) NasaApp::qt_metacall(QMetaObject::Call, int, void**) in libgselib.a(moc_apputil.o) "QApplication::qt_metacast(char const*)", referenced from: vtable for ExceptionSafeApplication in libgselib.a(apputil.o) NasaApp::qt_metacast(char const*) in libgselib.a(moc_apputil.o) "QApplication::compressEvent(QEvent*, QObject*, QPostEventList*)", referenced from: vtable for ExceptionSafeApplication in libgselib.a(apputil.o) vtable for NasaApp in libgselib.a(moc_apputil.o) "QApplication::staticMetaObject", referenced from: NasaApp::staticMetaObject in libgselib.a(moc_apputil.o) "QApplication::event(QEvent*)", referenced from: vtable for ExceptionSafeApplication in libgselib.a(apputil.o) vtable for NasaApp in libgselib.a(moc_apputil.o) "QApplication::notify(QObject*, QEvent*)", referenced from: ExceptionSafeApplication::notify(QObject*, QEvent*) in libgselib.a(apputil.o) vtable for NasaApp in libgselib.a(moc_apputil.o) "QApplication::QApplication(int&, char**, int)", referenced from: NasaApp::NasaApp(int&, char**, int, int, int, QString) in libgselib.a(apputil.o) ExceptionSafeApplication::ExceptionSafeApplication(int&, char**) in libgselib.a(apputil.o) "QApplication::~QApplication()", referenced from: NasaApp::NasaApp(int&, char**, int, int, int, QString) in libgselib.a(apputil.o) ExceptionSafeApplication::~ExceptionSafeApplication() in libgselib.a(apputil.o) NasaApp::~NasaApp() in libgselib.a(moc_apputil.o) "QApplication::metaObject() const", referenced from: vtable for ExceptionSafeApplication in libgselib.a(apputil.o) "typeinfo for QApplication", referenced from: typeinfo for ExceptionSafeApplication in libgselib.a(apputil.o) typeinfo for NasaApp in libgselib.a(moc_apputil.o) ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
And the static lib's header file:
/** * @file */ #ifndef APPUTIL_HPP #define APPUTIL_HPP #include <logger/logger.hpp> #include <util/pluginmanager.hpp> #ifdef QT_WIDGETS_LIB #include <QApplication> #else #include <QCoreApplication> #endif #include <QPointer> bool disableAppNap(const QString &appDomainName); /******************************************************************************* * Almost all projects should use one of the below app subclasses. They enforce * routine initialization and conventions. ******************************************************************************/ /** * Use for non-GUI apps. */ class NasaCoreApp : public QCoreApplication { Q_OBJECT public: explicit NasaCoreApp(int & ac, char **av, int majorVer, int minorVer, int patchVer, QString svnRevision); void initializeLogger(bool stdErrEnabled = false); private: Q_DISABLE_COPY(NasaCoreApp) }; #ifdef QT_WIDGETS_LIB /** * Use for GUI apps. */ class NasaApp : public QApplication { Q_OBJECT public: explicit NasaApp(int & ac, char **av, int majorVer, int minorVer, int patchVer, QString svnRevision); void initializeLogger(bool stdErrEnabled = false); void initializeConfig699(const QString & group = ""); void loadPlugins(const QStringList & pluginPaths = QStringList()); PluginManager *pluginManager() { return pluginManager_; } private: Q_DISABLE_COPY(NasaApp) QPointer<PluginManager> pluginManager_; }; /** * Provides a QApplication that catches any exceptions that are thrown during * handling of any events. The intention is to prevent the application from * crashing due to an exception. */ class ExceptionSafeApplication : public QApplication { public: explicit ExceptionSafeApplication(int & ac, char **av); virtual bool notify (QObject *r, QEvent *e ); private: Q_DISABLE_COPY(ExceptionSafeApplication) }; #endif // QT_WIDGETS_LIB #endif // APPUTIL_HPP
-
Wouldn't it be easier to simply create two separate classes/libraries instead?
-
Yes and that's what I've already done. I was really more curious if my original approach should have worked, but apparently there's holes in my understanding of how header and lib files interact.
-
You have to make sure QT_WIDGETS_LIB is (not) defined when using the header. So I assume QT_WIDGETS_LIB was defined when you wanted to use it in non-gui mode.
-
@Christian-Ehrlicher Well I've explicitly added "QT -= gui widgets" to my non-gui app's project file but it still complains about missing symbols. Is that not enough?
-
@Christian-Ehrlicher said in Using Qt lib macros with static libs and apps:
QT_WIDGETS_LIB
I would check it with a short '#error QT_WIDGETS_LIB defined' within the #ifdef QT_WIDGETS_LIB branch while compiling to non-gui app just to be sure :)