Qt subprojects and TDD - qt

I am building a Qt application which consists of several components (including plugins). Each sub project contains several classes.
I want to use the "normal" TDD workflow in my development process - namely;
I write a new function/method of a class in a module as a test
Compile the test (which should fail) for that module
Modify the source to correct the error (by adding the func/method etc)
Write test cases for the new function/method
Modify the src code to fix tests that fail
Each sub project will contain a src/ and test/ folders which will hold the source files and unittests respectively
This is what the project directory structure looks like:
myapp
|
|-myapp.pro
|
|--module1/
| |-src/
| |-test/
|
|--module2/
| |-src/
| |-test/
|
.
.
|--moduleN/
| |-src/
| |-test/
How can I setup QCreator so that I can build a subproject or its unittest from the QCreator GUI?

You can make a subdirs project and add the subprojects to its .pro file :
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += \
module1 \
module2 \
...
moduleN \
myapp
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 module1, module2 ... moduleN could be libraries which have TEMPLATE = lib in their .pro file and myapp should be app containing TEMPLATE = app in the .pro file.
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/../module1/release/ -lmodule1
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../module1/debug/ -lmodule1
else:unix: LIBS += -L$$OUT_PWD/../Base/ -lmodule1
INCLUDEPATH += $$PWD/../module1
DEPENDPATH += $$PWD/../module1

You should use subdirs template in .pro file.
I believe, you can start from following link (at the bottom of linked page).

Related

Including QML plugin into project

I have a QML plugin project and my application project plus subdirs project organized like that:
project.pro
plugin/
plugin.pro
Plugin.cpp
Plugin.h
qmldir
app/
app.pro
main.cpp
main.qml
qml.qrc
project.pro:
TEMPLATE = subdirs
SUBDIRS = app plugin
app.depends = plugin
plugin.pro:
TEMPLATE = lib
QT += qml quick
CONFIG += plugin c++11
TARGET = $$qtLibraryTarget(plugin)
PLUGIN_URI = com.test.plugin
SOURCES += Plugin.cpp
HEADERS += Plugin.h
app.pro:
QT += qml quick
SOURCES += main.cpp
RESOURCES += qml.qrc
It builds as expected and now I need to pass path to compiled libplugin.dylib/.so/.dll and qmldir to my application. I see two ways:
Copy plugin files into /path/to/qt/5.10.1/clang_64/qml/com/test/plugin/ using INSTALL qmake variable.
Copy plugin files near the application executable and add this path as relative to the executable using QQmlEngine::addImportPath().
What approach will be better? How to do it?

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.
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

QtCreator tricky project

I have a project in Qt Creator which has several shared library projects and the main project which also contains the main function. What I want is to add a new project which shouldn't be a shared library but just a project with some header files where I keep definitions and error codes. What I wish is to be able to add the path of this project to other projects INCLUDEPATH in order to use those files in other projects.
To do so I created an empty project which .pro file looks like this:
HEADERS += \
myHeader.h
but when I build the whole project it complains that it doesn't find the main in this project with only one header.
Is it possible in QtCreator to achieve this?
Create a .pri file which has your INCLUDEPATH, etc; and then refer to it in your other projects' .pro files:
# Common.pri
INCLUDEPATH += ../myPath
INCLUDE += myHeader.h
# OtherProject.pro
!include( ./Common.pri ) {
error( Could not find the Common.pri file. )
}
INCLUDEPATH += ../myOtherPath
Remember to use the += operator in your .pro files otherwise they will overwrite the .pri file variables.

Qmake project dependencies (linked libraries)

I have a project that links to a number of shared libraries.
Lets say project A depends on projects B and C
Ideally, I want to impose the following dependencies in my project file:
Rebuild project A if either B or C has been rebuilt since last time project A was built
Use the output for the relevant configuration (i.e. if building project A in debug mode, then use the debug versions of the libs for project B and C)
Does anyone know how I may explicitly express such dependencies in my project file?
After quite a bit of frustration with qmake, I have found what I think is the answer to your question. If not, then I have learned the way that I will use qmake until I find something better, because this is still a little bit ugly. I set up a demo project, this is my directory structure (files have extensions, folders do not):
MyProj
MyProj.pro
myproj-core
myproj-core.pro
globals.h
MyProjCore.h
MyProjCore.cpp
myproj-app
myproj-app.pro
main.cpp
We start with MyProj.pro as a subdirs project, which is the key to doing what you ask. Basically, instead of depending on other projects to specify debug/release and all sorts of other junk, you just set it on the one qmake file. It doesn't let you make only what you need, but it's the best solution I could come up with. Here are the contents:
TEMPLATE = subdirs
# Needed to ensure that things are built right, which you have to do yourself :(
CONFIG += ordered
# All the projects in your application are sub-projects of your solution
SUBDIRS = myproj-core \
myproj-app
# Use .depends to specify that a project depends on another.
myproj-app.depends = myproj-core
myproj-core.pro is your typical shared object library:
QT -= gui
TARGET = myproj-core
TEMPLATE = lib
DEFINES += MYPROJCORE_LIBRARY
SOURCES += MyProjCore.cpp
HEADERS += MyProjCore.h \
globals.h
myproj-app.pro is consumer application, where the little rebuild-when-needed trick is:
QT -= gui
TARGET = myproj-app
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
# Specify that we're lookin in myproj-core. Realistically, this should be put
# in some configuration file
INCLUDEPATH += ../myproj-core
# Link to the library generated by the project. Could use variables or
# something here to make it more bulletproof
LIBS += ../myproj-core/libmyproj-core.so
# Specify that we depend on the library (which, logically would be implicit from
# the fact that we are linking to it)
PRE_TARGETDEPS += ../myproj-core/libmyproj-core.so
SOURCES += main.cpp
I hope this solves your problem, as I know it solved mine!
EDIT: I made a file specifically for building the dependencies for me, I store it in a sibling folder of each of my projects (child of the MyProj in the directory structure specified above) called dependencies.pri:
# On windows, a shared object is a .dll
win32: SONAME=dll
else: SONAME=so
# This function sets up the dependencies for libraries that are built with
# this project. Specify the libraries you need to depend on in the variable
# DEPENDENCY_LIBRARIES and this will add
for(dep, DEPENDENCY_LIBRARIES) {
#message($$TARGET depends on $$dep ($${DESTDIR}/$${dep}.$${SONAME}))
LIBS += $${DESTDIR}/lib$${dep}.$${SONAME}
PRE_TARGETDEPS += $${DESTDIR}/lib$${dep}.$${SONAME}
}
So at the bottom of all the consuming applications, I can add the lines:
DEPENDENCY_LIBRARIES = myproj-core
include(../config/dependencies.pri)
This assumes that you are copying the libraries to some shared location and/or moving them around as needed, so my function might not work for you, but I figured I would add it to the solution.
I use the solution below. This works without the usage of an extra .pro file with subdir template.
TEMPLATE = app
TARGET = MyApp
PRE_TARGETDEPS = ../../libs/MyLib/MyLib.a
INCLUDEPATH += ../../libs/MyLib/include
HEADERS += src/MyApp.h \
../../libs/MyLib/incude/MyLib.h
SOURCES += src/MyApp.cpp
LIBS += ../../libs/MyLib/MyLib.a
MyLib.target = ../../libs/MyLib/MyLib.a
MyLib.commands = cd ../../libs/MyLib && make
MyLib.depends = ../../libs/MyLib/Makefile
QMAKE_EXTRA_TARGETS += MyLib
Check out this question: Force relink when building in QT Creator
Try adding something similar to this code to your pro file:
CONFIG(debug, debug|release) {
DESTDIR = ../../../bin/debug
OBJECTS_DIR = ./debug
}
else {
DESTDIR = ../../../bin/release
OBJECTS_DIR = ./release
}
Then you will have to specify the dependencies for each configuration:
CONFIG(debug, debug|release) {
LIBS += -L../../../lib/debug \
-L../../../bin/debug \
-llib1 \
-llib2
PRE_TARGETDEPS += ../../../lib/debug/liblib1.a \
../../../lib/debug/liblib2.a
else {
LIBS += -L../../../lib/release \
-L../../../bin/release \
-llib1 \
-llib2
PRE_TARGETDEPS += ../../../lib/release/liblib1.a \
../../../lib/release/liblib2.a
}
I had this problem when refactoring my project, after I moved in a new DLL (pqXDot) a reusable class (from pqGraphviz).
After adding a new DLL to my project, and adding the new DLL reference to others DLL and applications that needed it, I had in main .pro:
TEMPLATE = subdirs
SUBDIRS += \
pqConsole \
pqConsoleTest \
pqSource \
pqSourceTest \
fdqueens \
pqGraphviz \
pqGraphvizTest \
pqXDot
and the rebuild caused a linker error, because pqGraphviz, the DLL being restructured, can't find pqXDot, the new DLL.
It turns out it's sufficient to reorder the SUBDIRS list, moving the required DLL before the dependent one:
SUBDIRS += \
pqConsole \
pqConsoleTest \
pqSource \
pqSourceTest \
fdqueens \
pqXDot \
pqGraphviz \
pqGraphvizTest
For those that are interested into a template for your Qt/QML project, I have published one template on GitHub QmlAppTemplate.

How to use QMake's subdirs template?

I'm starting to learn Qt. I'm moving from the Visual Studio world and I am looking for a way to organize my project's structure using QMake. I've found the 'subdirs' template but I have quite a hard time understanding it.
My project structure looks like this:
project_dir/
main.cpp
project.pro
logic/
logic.pro
some logic files
gui/
gui.pro
gui files
My project.pro looks like this
TEMPLATE = subdirs
SUBDIRS = logic \
gui
SOURCES += main.cpp
In the .pro files for the subdirectories I have appropriate SOURCES, HEADERS and RESOURCES variables set.
Please tell me what TARGET, TEMPLATE and other necessary values I should set in the .pro files.
Also, is there some good QMake tutorial other than the official one?
In addition to Troubadour's comment, I would note that the SUBDIRS target is only good for specifying subdirectories. Therefore, your extra line of
SOURCES += main.cpp
in your project.pro file is incorrect, and will likely fail to build your main.cpp file, at worst. At best, qmake will refuse to parse the file, since it has conflicting specifications in it.
I've used the SUBDIRS template a few times, and it does well if you can build parts into more-or-less independent libraries, apparently like you have with the logic and the gui separate. Here is one way to do this:
project_dir/
-project.pro
-common.pri
-logic/
----logic.pro
----some logic files
-gui/
----gui.pro
----gui files
-build/
----build.pro
----main.cpp
project.pro:
TEMPLATE = subdirs
SUBDIRS = logic \
gui
# build must be last:
CONFIG += ordered
SUBDIRS += build
common.pri:
#Includes common configuration for all subdirectory .pro files.
INCLUDEPATH += . ..
WARNINGS += -Wall
TEMPLATE = lib
# The following keeps the generated files at least somewhat separate
# from the source files.
UI_DIR = uics
MOC_DIR = mocs
OBJECTS_DIR = objs
logic/logic.pro:
# Check if the config file exists
! include( ../common.pri ) {
error( "Couldn't find the common.pri file!" )
}
HEADERS += logic.h
SOURCES += logic.cpp
# By default, TARGET is the same as the directory, so it will make
# liblogic.a (in linux). Uncomment to override.
# TARGET = target
gui/gui.pro:
! include( ../common.pri ) {
error( "Couldn't find the common.pri file!" )
}
FORMS += gui.ui
HEADERS += gui.h
SOURCES += gui.cpp
# By default, TARGET is the same as the directory, so it will make
# libgui.a (in linux). Uncomment to override.
# TARGET = target
build/build.pro:
TEMPLATE = app
SOURCES += main.cpp
LIBS += -L../logic -L../gui -llogic -lgui
# Will build the final executable in the main project directory.
TARGET = ../project
You use subdirs if the logic and gui folders actually repesent some sort of target, eg. a library, that can be built independently of anything else. If that's the case then just use
TEMPLATE = lib
TARGET = logic
CONFIG += dll
in logic.pro.
If they are not independent targets but are just folders that exist to organise the sources files then you can just use a .pri file in each instead and include them within the .pro using
include(logic/logic.pri)
include(gui/gui.pri)
Just remember that the file paths in the .pri files are relative to the .pro file and not the .pri. BTW, the use of a .pri file is optional as you can still list the files in those folders directly in the .pro file. The .pri file just makes it that bit neater and helps keep the .pro file shorter.

Resources