I'm trying to move onto Qt to rewrite a win32 project that has a lot of static libraries so as a preliminary test project I tried creating a subdir project following the instructions in https://www.toptal.com/qt/vital-guide-qmake. I've seen plenty of other examples, and similar questions on this site, but none of them are a bare bones example that actually works when I build it so I'm presenting this minimal example in the hope that someone can tell me what it is that I'm missing.
Here's the file structure;
project/
project.pro
app/
app.pro
main.ccp
library/
library.pro
mainwindow.h
library.pri
Both app and library projects are simple Qt Widgets Applications, created with the New Subproject wizard. The app project has main.cpp;
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
The library project has just the header file mainwindow.h defining the MainWindow class;
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {}
~MainWindow() {}
};
#endif // MAINWINDOW_H
Here are the pro. files;
project.pro;
TEMPLATE = subdirs
TARGET = project
SUBDIRS = app library
app.depends = library
app.pro;
TEMPLATE = app
TARGET = app
QT = core gui
greaterThan(QT_MAJOR_VERSION, 4): QT = widgets
CONFIG = c 11
SOURCES = \
main.cpp
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS = target
include(../library/library.pri)
library.pro;
TEMPLATE = lib
TARGET = library
QT = core gui
greaterThan(QT_MAJOR_VERSION, 4): QT = widgets
CONFIG = c 11
HEADERS = \
mainwindow.h
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS = target
DISTFILES = \
library.pri
Lastly, the library.pri file;
LIBTARGET = library
BASEDIR = $${PWD}
INCLUDEPATH *= $${BASEDIR}/include
LIBS = -L$${DESTDIR} -llibrary
The point of this is to check that I can write a project in Qt where a function in one project can reference a class in another. When compiled as a single project, with main.cpp and mainwindow.h in the same project, you get the usual application window on screen with no errors so I know both main.cpp and the MainWindow class are good; compiled as-is, with the two sub-projects, I get "'mainwindow.h' file not found" on line 1, main.cpp, and "unknown type name 'MainWindow'" on line 6, main.cpp, so the library project is obviously not getting referenced properly by the app project. I'm new to Qt and have absolutely no experience with qmake, any help would be appreciated, and as I know I'm not the only person struggling with this if anyone can help get this working I'll put it up on gtihub.
CodePudding user response:
To use library you need to setup two things: append INCLUDEPATH
, and LIBS
, you can do it in pri file, and then include in app
, if error says "file *.h not found" it means INCLUDEPATH
is incomplete.
Here's how you can do it:
Project structure
project/
├── app
│ ├── app.pro
│ └── main.cpp
├── library
│ ├── library.pri
│ ├── library.pro
│ ├── mainwindow.cpp
│ ├── mainwindow.h
│ └── mainwindow.ui
└── project.pro
project.pro
TEMPLATE = subdirs
SUBDIRS = \
app \
library
app.depends = library
library.pri
INCLUDEPATH = $$PWD
win32 {
CONFIG(debug, debug|release) {
LIBS = -L$$PWD/debug
} else {
LIBS = -L$$PWD/release
}
} else {
LIBS = -L$$PWD
}
LIBS = -llibrary
library.pro
QT = gui widgets
TEMPLATE = lib
CONFIG = staticlib
SOURCES = \
mainwindow.cpp
HEADERS = \
mainwindow.h
FORMS = \
mainwindow.ui
app.pro
QT = gui widgets
SOURCES = main.cpp
include($$PWD/../library/library.pri)
QtCreator uses shadow build by default (it can be disabled on projects page), so if you build from QtCreator IDE not from shell (command line), you are likely using shadow build. In this case all build artifacts including static libraries are build outide of source directory in a separate directory named build-${project-name}-${device-type}-${build-config}
(build-project-Desktop-Debug in our case), so -L$$PWD
wont work, there's OUT_PWD
for that, unfortunately for some reason it points not to pri directory but to pro directory (build-project-Desktop-Debug/app in out case) and things get a little hairier. Here's library.pri
that works for both shadow and normal build:
INCLUDEPATH = $$PWD
win32 {
CONFIG(debug, debug|release) {
LIBS = -L$$PWD/debug -L$$OUT_PWD/../library/debug
} else {
LIBS = -L$$PWD/release -L$$OUT_PWD/../library/release
}
} else {
LIBS = -L$$PWD -L$$OUT_PWD/../library
}
LIBS = -llibrary
Full source: https://github.com/mugiseyebrows/app-and-library.git