2

I have multiple applications that will use one or more common libraries. Even my libraries could depend on each other.

Here is the files tree:

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

App1 depends on Library1. App2 depends on Library1 and Library2.

I'd like to be able to develop in Qt creator in an easy way, when I open Application1 I have the following behavior:

  • Application1 code available in Qt creator
  • Library1 code available in Qt creator
  • Compiling Application1 automatically compiles Library1 and puts the output .dll/.so file in the same directory than Application1 .exe.

This is basically what Visual Studio is able to do for years and seems such a basic thing to me that I don't understand I'm the only one having this problem.

Do you have any clue on how to do this ? I tried different solutions based on SUBDIRS, but I never reach all the 3 points above.

EDIT:To clarify a little, I would like to be able to do something like:

Application1.pro

include("Library1")

Application2.pro

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

And having all working automatically. I found solution which requires files in libraries to know what is the "parent" doing some includes, which is a non-sense to me, a library should not be aware of the program using it.

Thibaut D.
  • 2,521
  • 5
  • 22
  • 33

3 Answers3

1

App1Solution.pro:

TEMPLATE = subdirs
CONFIG += ordered

SUBDIRS += \
    ../../Libaries/Library1 \
    ../App1

Place near App1.pro

App2Solution.pro:

TEMPLATE = subdirs
CONFIG += ordered

SUBDIRS += \
    ../../Libaries/Library1 \
    ../../Libaries/Library2 \
    ../App2

Place near App2.pro

and puts the output .dll/.so file in the same directory than Application1 .exe

This should be made differently:

  1. You could set DESTDIR of Library<i> depending on some variable.
  2. You could add copy-lib command to App<i> pro-file.
Amartel
  • 4,248
  • 2
  • 15
  • 21
  • This will work but does not fit all requirements : libraries will be built in their own directories and not in App1 directory (near App1.exe). – Thibaut D. Jul 22 '15 at 13:44
  • 1
    You can [copy](http://stackoverflow.com/questions/3984104/qmake-how-to-copy-a-file-to-the-output) needed files [before building app](http://stackoverflow.com/questions/5083441/how-to-add-pre-build-step-in-qmake-qtcreator). – Amartel Jul 22 '15 at 13:58
  • You could set DESTDIR of Library depending on some variable.<= How do you do that ? I think is is the proper way of doing it but you can't share variables between subdirs projects. – Thibaut D. Jul 22 '15 at 14:07
1

You can do a project like this : MyProject:

  • project.pro
    • App
      • 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
Thom Armax
  • 147
  • 1
  • 11
  • 1
    `DEPENDPATH` should also be added, and must contain everything in `INCLUDEPATH`. Otherwise, you get brittle builds.\ – Kuba hasn't forgotten Monica Jul 22 '15 at 20:13
  • And instead of using a relative DESTDIR I could use an environement variable, which makes the build output configurable by application. – Thibaut D. Jul 22 '15 at 20:22
  • @KubaOber Are you sure ? I read on stackoverflow that its not needed anymore with qt5. – Thibaut D. Jul 22 '15 at 20:28
  • 1
    @ThibautD. Maybe, but both are still supported and in widespread use, so, as general advice, `DEPENDPATH` is required. In any case, it's best to move to `qbs`... – Kuba hasn't forgotten Monica Jul 22 '15 at 20:31
  • @KubaOber If Qbs replaces qmake & make, why is not used by default on latest Qt 5.5 & Qt creator ? I can only create "Non-qt" C++ project to use with Qbs. – Thibaut D. Jul 22 '15 at 20:49
  • @ThibautD. Feel free to contribute a template to Qt Creator to enable it. Nobody got to it at this point, more or less. Qt doesn't force you to use qmake, it simply uses it to build the toolkit, but it's entirely your choice otherwise. Qt Creator doesn't force it either, it simply comes with some default templates, and you can rather easily add whatever else you desire to Creator for your own use. – Kuba hasn't forgotten Monica Jul 22 '15 at 21:03
1

Adding to Thom's answer, it is advantageous to be able to refer to library headers using qualified prefixes - #include "lib1/lib1.h" instead of #include "lib1.h". Otherwise, it's almost impossible to use libraries developed independently, you'll always get header clashes.

There are two ways of accomplishing that.

First, you could add a common variable to every top level project file that indicates its depth in the project tree by referring to the tree root. You then add the tree root to the include and depend paths.

App.pro

ROOT = ..
include($$ROOT/lib1/lib1.pri)
include($$ROOT/lib2/lib2.pri)

INCLUDEPATH += $$ROOT
DEPENDPATH += $$ROOT

...

This way, the individual library project includes don't have to specify their includes at all.

Alternatively, the INCLUDEPATH in each library should point one folder up - don't forget DEPENDPATH!

lib1.pri

ROOT = ..
INCLUDEPATH += $$PWD/$$ROOT
DEPENDPATH += $$PWD/$$ROOT

...

Then, within main.cpp, you can have sensibly prefixed includes that won't clash even if lib1 and lib2 both provide the same file:

main.cpp

#include "lib1/easy.h"
#include "lib2/easy.h"
...
Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313