Как создать многоразовые библиотеки на основе qmake?
У меня есть несколько приложений, которые будут использовать одну или несколько общих библиотек. Даже мои библиотеки могут зависеть друг от друга.
Вот дерево файлов:
Libaries/
Library1/
Library1.pro
Library1.cpp
Library1.h
Library2/
Library2.pro
Library2.cpp
Library2.h
Applications/
App1/
App1.pro
main.cpp
App2/
App2.pro
main.cpp
Приложение 1 зависит от библиотеки 1. Приложение 2 зависит от Library1 и Library2.
Я хотел бы иметь возможность легко разрабатывать в Qt creator, когда я открываю Application1, у меня следующее поведение:
- Код Application1, доступный в Qt creator
- Код Library1 доступен в создателе Qt
- Компиляция Application1 автоматически компилирует Library1 и помещает выходной файл.dll /.so в тот же каталог, что и Application1.exe.
Это в основном то, что Visual Studio может делать годами, и мне кажется, что это такая базовая вещь, что я не понимаю, что у меня одна такая проблема.
Есть ли у вас какие-либо подсказки, как это сделать? Я пробовал разные решения, основанные на SUBDIRS, но я никогда не доходил до всех 3 пунктов выше.
РЕДАКТИРОВАТЬ: Чтобы уточнить немного, я хотел бы иметь возможность сделать что-то вроде:
Application1.pro
include("Library1")
Application2.pro
include("Library1")
include("Library2")
И все работает автоматически. Я нашел решение, которое требует, чтобы файлы в библиотеках знали, что "родитель" делает, включая некоторые, что для меня не имеет смысла, библиотека не должна знать о программе, использующей ее.
3 ответа
Вы можете сделать проект, как это: MyProject:
- project.pro
- Приложение
- App.pro
- main.cpp
- lib1
- lib1.pro
- lib1.pri
- lib1.h
- lib1.cpp
- lib2
- lib2.pro
- lib2.pri
- lib2.h
- lib2.cpp
- Приложение
project.pro
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += \
lib1 \
lib2 \
App
App.pro
QT += core
QT -= gui
include(../lib1/lib1.pri)
include(../lib2/lib2.pri)
TARGET = App
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
main.cpp
#include <QCoreApplication>
#include "lib1.h"
#include "lib2.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Lib1 lib1();
return a.exec();
}
lib1.pro
QT -= gui
TARGET = lib1
TEMPLATE = lib
DEFINES += LIB1_LIBRARY
SOURCES += lib1.cpp
HEADERS += lib1.h\
lib1_global.h
DESTDIR = ../libs
unix {
target.path = /usr/lib
INSTALLS += target
}
OTHER_FILES += \
lib1.pri
lib1.pri
INCLUDEPATH += $$PWD/
LIBS += -L$$OUT_PWD/../libs/ -llib1
lib2.pro
QT -= gui
TARGET = lib2
TEMPLATE = lib
DEFINES += LIB2_LIBRARY
SOURCES += lib2.cpp
HEADERS += lib2.h\
lib1_global.h
DESTDIR = ../libs
unix {
target.path = /usr/lib
INSTALLS += target
}
OTHER_FILES += \
lib2.pri
lib2.pri
INCLUDEPATH += $$PWD/
LIBS += -L$$OUT_PWD/../libs/ -llib2
В дополнение к ответу Тома, полезно иметь возможность ссылаться на заголовки библиотек, используя квалифицированные префиксы - #include "lib1/lib1.h"
вместо #include "lib1.h"
, В противном случае практически невозможно использовать библиотеки, разработанные независимо, вы всегда будете сталкиваться с конфликтами заголовков.
Есть два способа сделать это.
Во-первых, вы можете добавить общую переменную к каждому файлу проекта верхнего уровня, которая указывает его глубину в дереве проекта, ссылаясь на корень дерева. Затем вы добавляете корень дерева в пути включения и зависимости.
App.pro
ROOT = ..
include($$ROOT/lib1/lib1.pri)
include($$ROOT/lib2/lib2.pri)
INCLUDEPATH += $$ROOT
DEPENDPATH += $$ROOT
...
Таким образом, отдельные библиотечные проекты не должны указывать свои включения вообще.
В качестве альтернативы INCLUDEPATH
в каждой библиотеке должна быть указана одна папка вверх - не забудьте DEPENDPATH
!
lib1.pri
ROOT = ..
INCLUDEPATH += $$PWD/$$ROOT
DEPENDPATH += $$PWD/$$ROOT
...
Тогда внутри main.cpp
, вы можете иметь разумные префиксы, которые не будут конфликтовать, даже если lib1
а также lib2
оба предоставляют один и тот же файл:
main.cpp
#include "lib1/easy.h"
#include "lib2/easy.h"
...
App1Solution.pro:
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += \
../../Libaries/Library1 \
../App1
Место рядом App1.pro
App2Solution.pro:
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += \
../../Libaries/Library1 \
../../Libaries/Library2 \
../App2
Место рядом App2.pro
и помещает выходной файл.dll/.so в тот же каталог, что и Application1 .exe
Это должно быть сделано по-другому:
- Вы могли бы установить
DESTDIR
изLibrary<i>
в зависимости от какой-то переменной. - Вы можете добавить команду copy-lib в
App<i>
профиль.