Как создать многоразовые библиотеки на основе 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 создателе
  • Код Library1 доступен в создателе Qt
  • Компиляция Application1 автоматически компилирует Library1 и помещает выходной файл .dll / .so в тот же каталог, что и Application1 .exe.

Это в основном то, что Visual Studio может делать годами, и для меня это такая базовая вещь, что я не понимаю, что я единственный, у кого есть эта проблема.

Есть ли у вас какие-либо подсказки, как это сделать? Я пробовал разные решения, основанные на SUBDIRS, но я никогда не доходил до всех 3 пунктов выше.

РЕДАКТИРОВАТЬ: Чтобы уточнить немного, я хотел бы иметь возможность сделать что-то вроде:

Application1.pro

include("Library1")

Application2.pro

include("Library1")
include("Library2")

И все работает автоматически. Я нашел решение, которое требует, чтобы файлы в библиотеках знали, что «родитель» делает, включая некоторые, что для меня не имеет смысла, библиотека не должна знать о программе, использующей ее.

2

Решение

Вы можете сделать проект, как это:
Мой проект:

  • 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 = appSOURCES += 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
1

Другие решения

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

Это должно быть сделано по-другому:

  1. Вы могли бы установить DESTDIR из Library<i> в зависимости от какой-то переменной.
  2. Вы можете добавить команду copy-lib в App<i> профиль.
1

Добавление к Том ответ, полезно иметь возможность ссылаться на заголовки библиотеки, используя квалифицированные префиксы — #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"...
1
По вопросам рекламы [email protected]