Search code examples
qtqt-creatorqmakeproject-organizationproject-structure

Advices about project organisation


I have several questions about what to do to have the best organization project for my needs.

Context

I'm working on QT5 and I have a project like this:

MyProject /
    MyProject.pro
    src /
    src.pro                     // target = app (include Controller.pro and View.pro)
        Controller /
            Controller.pro      // no target, just add some sources
            Component1 /
            Component2 /
            ...
        View / 
            View.pro            // no target, just add some sources
            Component10 /
            Component11 /
            ...
        main.cpp
    test /
        Controller /
            Component1 /
                Component1.pro     // target = app
                main.cpp
            ...
        View /
            Component10 /
                Component10.pro    // target = app
                main.cpp
            ...

Compilation

At the moment, everything works fine except that, the more my project grows, the more the compilation time is huge. (Around 2mins).

I checked what happened and the problem is, in each test-sub-project-file, I include Controller.pro in order to have all of my sources.

Doing this, I compile N times my sources and that's why it's too long.

(In the generated files/folders, I have something like)

build-MyProject /
    src /
        main.o
        component1.o
        component2.o
        component10.o
        ...
    test /
        Controller /
            Component1 /
                main.o
                component1.o
            ...
        View /
            Component10 /
                main.o
                component10.o
            ...

Component1 and Component10 had been compiled twice.

What I would like

Obviously, I want to generate objects for each file once. Ideally, something like:

MyProject /
    obj /
        src /
            Controller /
                component1.o
                component2.o
            View /
                component10.o
            main.o
        test /
            Controller /
                Component1 / 
                    main.o
            View /
                Component10 /
                    main.o

What I don't know how to do

1- The main problem is, I don't know how to tell QMake i want to link ob/src/Controller/Component1.o with obj/test/Controller/main.o

2- According to your experience, is an organization like this, a good thing or too complicated, too much separated, ... ?

3- With qmake tool, i saw that you can define target = app or target = lib to generate either an executable or a library. Is there a key word to only generate object without performing the linking ? (I can do it taking off main.cpp in key word SOURCES but make tries to link all objects and I have undefined reference to main...)

Thanks in advance.


Solution

  • I think separation of code modules from each other as much as possible is a good idea. This way you can have independent software modules which are reusable and able to be changed easily.

    I personally use Subdirs to separate parts of my code. Using it, the project becomes much cleaner and easier to read. Qt Creator also provides good automation in liking the parts to each other.

    You can make a Subdirs project and add the subprojects to its .pro file :

    TEMPLATE = subdirs
    
    CONFIG += ordered
    
    SUBDIRS += \
        Controller\
        View\
        Component1\
        Component2\
        component10\
        test\
        mainApp
    

    You should bring the subprojects that others depend on, first in the list. Also notice that the name of the .pro file of the subproject should be the same as it's folder name. This way the subprojects are detected and listed in the Projects pane.

    The subprojects like Controller and View could be libraries. Part of .pro file for Controller:

    TARGET = Controller
    TEMPLATE = lib
    
    DEFINES += Controller_LIBRARY
    
    SOURCES += ...
    HEADERS += ...
    

    The subprojects like mainApp and test should be app. Part of .pro file for mainApp :

    TARGET = mainApp
    TEMPLATE = app
    

    You can use the libraries in each subproject by linking it to the subproject. This can be done by right clicking on the subproject and choosing "Add Library" and then "Internal Library". When you select one library from the list of subprojects, the linking configurations are added to the .pro automatically. It will be like :

    win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../Controller/release/ -lController
    else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../Controller/debug/ -lController
    else:unix: LIBS += -L$$OUT_PWD/../Controller/ -lController
    
    INCLUDEPATH += $$PWD/../Controller
    DEPENDPATH += $$PWD/../Controller