Qmake project dependencies (linked libraries) - qt

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.

Related

how to unit test a Qt application with QtTest using subdirs

I found a few other hits when searching for this particular problem, but i cant get my setup to work with my unit test project(s).
project info: ( optional reading)
I am in the beginning of my final undergraduate project, where I am to
create an IDE for the language Promula and the the
verification tool Spin. The professor I am doing this with expects to
use it in his classes and for future undergraduates to keep improving. It is also meant to be a open source project everyone can contribute to.
Spin tool
my folder struture:
QSpin
-QSpin.pro
-QSpinApplication
--QSpinapplication.pro
--QSpinApplication.pri
--include
---Workspace
----*.h
--src
---Workspace
----*.cpp
-QSpinApplicationTests
--QSpinApplicationTests.pro
--WorkspaceGroupTests
---WorkspaceGroupTests.pro
----some cpp testfile
My QSpinApplication compiles and runs without any problems. The import of what i have so can be imported.
#include <Workspace/(file_name).h>
However in my test project WorkspaceGroupTests i want to include headers in the same way, but i cant get it to work. Beside that i assume the test project need to know where the cpp files are. If i dont use any of the application headers the test project compiles and runs with the default test case.
at the moment i am using a default shadow build with its root folder in the QSpin folder.
Any idea of how i get my test project working correctly, to actual be able to test my application classes?
QSpin.pro:
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += \
QSpinApplication\QSpinApplication.pro \
QSpinApplicationTests
QSpinApplication.pro:
QT += quick qml gui
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES +=src/main.cpp
include(QSpinApplication.pri)
RESOURCES += qml.qrc
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
QSpinApplication.pri:
#//DEPENDPATH += $$PWD
INCLUDEPATH += ./include
SOURCES +=src/workspace/workspaceview.cpp \
src/workspace/groupitem.cpp \
src/workspace/groupitemsplitter.cpp \
src/workspace/workspacegroup.cpp \
src/workspace/workspaceviewattached.cpp \
src/workspace/workspaceviewiteminfo.cpp \
src/workspace/workspacegrouplinknode.cpp
HEADERS += \
include/workspace/workspaceview.h \
include/workspace/groupitem.h \
include/workspace/groupitemsplitter.h \
include/workspace/workspacegroup.h \
include/workspace/workspaceviewattached.h \
include/workspace/workspace.h \
include/workspace/workspaceviewiteminfo.h \
include/workspace/workspacegrouplinknode.h
QSpinApplicationTests.pro:
TEMPLATE = subdirs
SUBDIRS += \
WorkspaceGroupTests
WorkspaceGroupTests.pro:
QT += testlib
QT -= gui
DEPENDPATH+=./../../QSpinApplication
include(./../../QSpinApplication/QSpinApplication.pri)
CONFIG += qt console warn_on depend_includepath testcase
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += tst_workspacegrouptests.cpp
Not sure if I understood well but in general, what I would advise is to create a separate structure for "lib" where you put logic code that can be tested, so default structure would look like that:
Structure:
├───app.pro
├───lib.pro
└───tests.pro
Then you put in your lib.pro:
TARGET = NameOfTarget
TEMPLATE = lib
CONFIG += staticlib
and add in your tests.pro, and in app.pro:
LIBS += -L../lib -lNameOfTarget
At end it should be possible without problems to include in app directory and in test:
#include "anyHeaderFromLib.h" .
As an extra addition for Michal Kalinowski answer:
Looks like this will work only for Linux/Mac, in case of Windows you should handle it on that way:
win32:CONFIG(release, debug|release): LIBS += -L../lib/debug -lNameOfTarget
else:win32:CONFIG(debug, debug|release): LIBS += --L../lib/release -lNameOfTarget
else:unix: LIBS += -L../lib -lNameOfTarget
Some more context can be get here: https://doc.qt.io/qtcreator/creator-project-qmake-libraries.html

qtcreator project file depndancies and build order

I am using qtcreator with subdir project structure. The case is that:
I have 2 projects. Project A and B. After A compiles, then B, but in B, I must use the headers of A (classes, functions, etc.). I`ve found in wiki the depends and subdir project setup, but when I try to include class A from project A into class B into project B ( these names are for convininece ) it gives me undefined referencies. Here is my .pro file from main project (and subprojects respectively ):
#base pro file
TEMPLATE = subdirs
SUBDIRS += \
message \
daemon \
receiver
daemon.subdir = daemon
message.subdir = message
daemon.depends = message
subproject A:
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += main.cpp \
daemon.cpp \
logwriter.cpp
HEADERS += \
daemon.h \
logwriter.h \
defs.h
LIBS += -lpthread
subproject B:
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += \
message.cpp \
main.cpp
HEADERS += \
message.h
So I need the project B classes into project A and further on when I extend the project.
Regards.
EDIT: A .pri example would be appreciated, if I'm going to set project A to be a library (-lclssA )
"undefined references" are generally link problems, not header include problems. You may have to link your project A with B if you need to use it.
e.g in A :
LIBS += ../path/to/libB.so
The simplest way is to include it as a lib, the easiest way was from qtcreator, rightclick on the dependee and "Add library" -> "Existing library from build tree". This will generate the following in the .pro:
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../message/release/ -lmessage
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../message/debug/ -lmessage
else:unix: LIBS += -L$$OUT_PWD/../message/ -lmessage
INCLUDEPATH += $$PWD/../message
DEPENDPATH += $$PWD/../message
However I am losing the ability to make tests for my message class in it's main class. So if there is a better way, I'd accept it.

Run time error for a missing DLL which exists

I am writing a tool with Qt Creator which builds but immediately crashes with the message:
"The program can't start because pthreadVC2.dll is missing from your
computer. Try reinstalling the program to fix this problem".
Of course, the "pthreadVC2.dll" library is not missing (and is not corrupted, since it works with other projects), and it is located in the path specified in the Qt pro file:
# DeltaPlots.pro
TARGET = DeltaPlots
QT += core gui
CONFIG += console
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TEMPLATE = app
win32 {
INCLUDEPATH += S:\\3rdparty\\DFS.Infrastructure.ThreadingW \
S:\\3rdparty\\DFS.Infrastructure.File \
"C:\\path\\to\\boost\\boost_1_51_0"
win32-g++:LIBS += -L"S:\\lib\\" -lMyLib
win32-g++:LIBS += -L"S:\\3rdparty\\DFS.Infrastructure.File\\" -lDFS.Infrastructure.FileSystem
win32-g++:LIBS += -L"S:\\3rdparty\\DFS.Infrastructure.ThreadingW\\" -lDFS.Infrastructure.Threading -lpthreadVC2
}
SOURCES += MainWindow.cpp \
entrypoint.cpp
HEADERS += MainWindow.h
FORMS += MainWindow.ui
OTHER_FILES += ProjectList.txt \
ImageList.txt
Platform:
Windows 7
MinGW
Qt 4.8.3
Qt Creator 2.6.0
[Edit: This answer refers to the original question]
Usually you would add
LIBS += -LS:/3rdparty/DFS.Infrastructure.ThreadingW \
-lpthreadVC2
This adds your library's folder as a library search path (Note the capital -L) and pthreadVC2.lib as a library to link against (lower case -l).
You do not need to add the .dll to the LIBS path, as the .dll is loaded at runtime.
But: This approach only works when the .lib is in the same folder as the .dll. I'm a bit surprised you have yours in different locations.
Maybe adding
LIBS += -LS:/3rdparty
would work, but I'm not sure about that.
In any event, you need to deploy the .dll with your .exe for releases.

Subdirectory in a Qt Project

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. I have tried to do something like this. Can anyone please just tell me that I am correct or not.
edit: I have read the following thread How to use QMake's subdirs template? but I am still stuck
My project structure is as follows:
MultiFuncTester.pro
- DMM
(DMM.cpp, DMM.h and Multifunctester.pri)
-Safety
(Safety.cpp, Safety.h and Multifunctester.pri)
-Solar
(Solar.cpp, Solar.h and Multifunctester.pri)
Main
(Main.pro, Main.cpp and Multifunctester.pri)
Here Multifunctester.pri file has common stuff for all the sub directories.
I am pasting the MultiFuncTester.pro and .pri file and also the main.pro file
I have made project's pro file as MultiFuncTester.pro :
# build all components recursive
TEMPLATE = subdirs
######## normal build process ########
#
# Make sure your Main.pro is in the last line to ensure correct linking!
#
SUBDIRS = ../../MultiFuncTester/Components/Solar/Build/Solar.pro \
../../MultiFuncTester/Components/DMM/Build/DMM.pro \
../../MultiFuncTester/Components/Safety/Build/Safety.pro \
../../MultiFuncTester/Components/Setup/Build/Setup.pro \
../../MultiFuncTester/Components/Start/Build/Start.pro \
../../MultiFuncTester/Components/Main/Build/Main.pro \
CONFIG += ordered
MultiFunctester.pri file:
######################
# common stuff for all components
######################
TEMPLATE = lib
CONFIG += static \
warn_on \
qt \
thread \
rtti
QT += core \
gui
INCLUDEPATH +=/..\
../../MultiFuncTester/Components \
DEPENDPATH +=/..\
../../MultiFuncTester/Components \
CONFIG += debug_and_release
CONFIG += build_all
QMAKE_CXXFLAGS += -Wall
CONFIG(debug, debug|release) {
CONFIG_SUFFIX = dbg
} else {
CONFIG_SUFFIX = rel
DEFINES += QT_NO_DEBUG \
QT_NO_DEBUG_OUTPUT \
DBT_TRACE_DISCARD \
NDEBUG
CONFIG(gcov) {
QMAKE_CXXFLAGS_RELEASE += -fprofile-arcs -ftest-coverage
QMAKE_LFLAGS_RELEASE += -fprofile-arcs
QMAKE_CXXFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE += -O0
}
}
CONFIG(crosstgt) {
### To be able to build Target run qmake as follows:
#qmake CONFIG+=crosstgt
CONFIG_SUFFIX = $${CONFIG_SUFFIX}_tgt
DEFINES += TARGET_BUILD
}
OBJECTS_DIR = obj_$${CONFIG_SUFFIX}
MOC_DIR = moc_$${CONFIG_SUFFIX}
DESTDIR = lib_$${CONFIG_SUFFIX}
Main.pro file:
################# include pri file #################
!include("Main.pri") {
error("Main.pri not found")
}
####################################################
################# override some pri settings #################
TEMPLATE = app
TARGET = MultiFuncTester
CONFIG -= static
QT += core \
gui
##############################################################
################# list used MultiFuncTester libraries #################
MultiFuncTester_COMPONENTS_DIR =../../MultiFuncTester/Components
################################################################
################# list MultiFunTester libraries #################
MultiFunTester_COMPONENTS_DIR =../../MultiFuncTester/Components
MultiFunTester_COMPONENTS = DMM \
SOLAR\
Safety\
Setup
################# own sources #################
INCLUDEPATH += ../../MultiFuncTester/Components \
SOURCES +=../Source/Main.cpp
################# set destination path
DESTDIR = bin_$$CONFIG_SUFFIX
################# edit include path
INCLUDEPATH += $$MultiFunctester_COMPONENTS_DIR \
################# start group
LIBS += -Wl,--start-group \
################# include MultiFunctester libraries and set dependencies
for(TheComponent, MultiFunctester_COMPONENTS) {
THELIBPATH = $$MultiFunctester_DIR/$${TheComponent}/Build/lib_$$CONFIG_SUFFIX
PRE_TARGETDEPS += $$THELIBPATH/lib$${TheComponent}.a
LIBS += $$THELIBPATH/lib$${TheComponent}.a
}
################# end group
LIBS += -Wl,--end-group
Each subdirectory has a .pro file which have headers and sources defined and also the common multifunctester.pri file
Please let me know that putting a common static library (MultiFunctester.pri file) is a right approach and what shall it do in the code.....and if not please help me in correcting me wherever I am wrong.
Thanks
There are some mistake :
TEMPLATE = lib in MultiFunctester.pri. .pri files are like header files, this will be added in every pro files which include it. It can be confusing, so avoid using the TEMPLATE variable in .pri
if I understand well your first point you have copies of Multifunctester.pri in each directory. This is also really confusing, you should only have one (or different pri files).
Overriding previous setting is not as a good idea as it seems. When you will have to debug to see which configuration is used in each pro file you will feel the pain. Rather declare all common settings in one place, and for variable settings declare them when they
apply.
I don't see Multifunctester.pri included anywhere...
You use the subdirs template when you want each sub-directory to be built separately (they can be interdependent). It is useful for instance when you have a framework with many executable. look at qwt source directory
In this case, you use
TEMPLATE = subdirs
CONFIG += ordered
### They MUST be subdirectories, no ../, and no .pro
SUBDIRS += dir1\
dir2\
...
dirn
for each level aside of the last one (where you have TEMPLATE = lib or app).
Now if you have directory structure but you want to build all together you can create a
pri file for each subdirectory where you include the source files. For example :
in the main src.pro file you have
include(MultiFunctester.pri) ## for the configurations
include($PATHTOSOLAR/Solar.pri)
include($PATHTODMM/dmm.pri)
include($PATHTOSAFETY/safety.pri)
include($PATHTOSETUP/setup.pri)
include($PATHTOSTART/start.pri)
include($PATHTOMAIN/main.pri)
where $PATHTO... is the relative path from thesrc.pro directory.
Now in each subdirectory you include the source files.
onesubdir.pri :
headers += /PATHTOTHISSUBDIR/file1.h ## again same relative path as above
....
source +=....

compiling maya (3d application ) with qt

including the maya ( 3d application ) classes in qt program gives lot of errors..... i have added all required include paths and libs...the same problem persists ....
this is pro file for my qt project
TARGET = FileCon
TEMPLATE = app
SOURCES += main.cpp \
dialog.cpp
HEADERS += dialog.h \
ConvertFunction.h
FORMS += dialog.ui
LIBS += "C:/Program Files/Autodesk/Maya2008/lib" \
-lOpenMaya.lib \
-lFoundation.lib \
-lOpenMayalib
INCLUDEPATH += "C:/Program Files/Autodesk/Maya2008/include"
DEFINES = _BOOL \
WIN32 \
REQUIRE_IOSTREAM
///////////////////////////////////////////
How is it possible to use maya classes with qt.
Try something like this
LIBS += $$quote(-LC:/Program Files/Autodesk/Maya2008/lib) \
-lOpenMaya \
-lFoundation
qmake LIBS variable
If you are using QtCreator with the included compiler on Windows, it expects ".a" style libraries, rather than Visual Studio ".lib" style libraries.
You still haven't given enough infromation about eaxctly what you are doing. (How are you building, what compiler, etc.) or what is going wrong (exact error messages) to know for sure if that's the issue. But, if my crystal ball is working well today, I'd recommend checking the library format.

Resources