Build a 3rd party library from source within an existing Qt project - c++

My project requires a version of zlib that isn't present on all target machines, so I want to build zlib from source in my project. Then when I make my project, it should first build zlib so it can be linked to when compiling my project.
One complication is that zlib requires configure to be run before make can be run.
I'm not even sure where to start here. Is there functionality built in to Qt Creator for importing 3rd party library source code like this, or do I need to code out a custom .pro file?
I tried the "Add Library..." menu that appears when right-clicking on my project, but it doesn't recognize the library - likely because no .pro file exists. I also tried to create a .pro file by File -> New Project -> Import Existing Project, and it's able to compile zlib once configure has been run, but it still doesn't generate a .pro file.
I thought that maybe the subdirs might be useful, but I'm not sure if that is the right route in this situation, and even if it is I am not sure whether I can auto-create the necessary .pro file, or I have to create it myself.
Given the source code for a 3rd party library like zlib, how do I integrate that into an existing Qt project such that I can compile the library from source, and use it in my project?

Yes, you need to create a project file for it. You can find my version below what I used for several projects.
zlib.pro
QT -= core gui
TARGET = zlib
TEMPLATE = lib
# Use this for static zlib rather than the default dynamic
# CONFIG += staticlib
include(zlib.pri)
zlib.pri
HEADERS += \
$$PWD/crc32.h \
$$PWD/deflate.h \
$$PWD/gzguts.h \
$$PWD/inffast.h \
$$PWD/inffixed.h \
$$PWD/inflate.h \
$$PWD/inftrees.h \
$$PWD/trees.h \
$$PWD/zconf.h \
$$PWD/zlib.h \
$$PWD/zutil.h
SOURCES += \
$$PWD/adler32.c \
$$PWD/compress.c \
$$PWD/crc32.c \
$$PWD/deflate.c \
$$PWD/gzclose.c \
$$PWD/gzlib.c \
$$PWD/gzread.c \
$$PWD/gzwrite.c \
$$PWD/infback.c \
$$PWD/inffast.c \
$$PWD/inflate.c \
$$PWD/inftrees.c \
$$PWD/trees.c \
$$PWD/uncompr.c \
$$PWD/zutil.c
INCLUDEPATH += $$PWD
Then in the project file including this one, you can do something like this:
main.pro
# CONFIG += order # If you wanna make sure about order. This is optional.
SUBDIRS += \
zlib \
...
If you wanna go even a bit more advanced with qmake, you can do something like this:
SUBDIRS += \
src_zlib \
src_mylib \
...
src_zlib.subdir = $$PWD/zlib
src_zlib.target = sub-zlib
src_zlib.depends =
src_mylib.subdir = $$PWD/mylib
src_mylib.target = sub-mylib
src_mylib.depends = src_zlib
As you can see this way, you would have a lot more reasonable control among the dependencies regardless the order set. For instance, you could still keep the entries in alphabetical order which is helpful with proper maintenance in the long run.
Then, you will need a line like this in the project file (.pro) of your subproject, let us say "foo", which depends on zlib.
foo.pro
LIBS += -L$${PROJECTROOT}/$${SUBDIR_TO_ZLIB} -lz
# These lines are only option, and you do not necessarily need them.
# win32:LIBNAME = zlib.dll
# unix:LIBNAME = libzlib.so
# PRE_TARGETDEPS += $${PROJECTROOT}/$${BUILD_SUBDIR_LIBS}/$${LIBNAME}

Following are instructions for adding a 3rd party repository to your Qt project and building it from source.
Some are able to add such libraries via Qt Creator, but I could never get that to work. So these are instructions on how to create the necessary .pro and .pri files instead. In this post, I will use zlib as an example, although other libraries should be similar.
Setup Build Order
Since your application depends on this library, we need to ensure that the library is built first. To do this, the 3rd party library and the source code for your application should be in sibling directories.
~/myApp $ ls myApp
src zlib
You probably already have a myApp.pro file that correctly builds your application. I recommend renaming it to src.pro, and you'll see why in the next step.
mv src/myApp.pro src/src.pro
Now you can create a new myApp.pro in the root directory.
~/myApp $ touch myApp.pro
~/myApp $ ls
myApp.pro src zlib
This is a rather simple .pro file that merely says "build zlib before myApp."
# ~/myApp/myApp.pro
TEMPLATE = subdirs
CONFIG += ordered # This tells Qt to compile the following SUBDIRS in order
SUBDIRS = zlib src
Create Library .pro File
Now we need to tell Qt how to build our 3rd party library. We do this by creating a new .pro file:
# ~/myApp/zlib/zlib.pro
TARGET = z # The name of the output library - can be whatever you want
TEMPLATE = lib # Tells Qt that we are compiling a library so the output will be bundled into a .a or .so file
CONFIG += staticlib # Tells Qt that we want a static library, so a .a file. Remove this and you will get a .so file
QMAKE_CFLAGS_WARN_ON -= -Wall # Optional - disable warnings when compiling this library
QMAKE_CXXFLAGS_WARN_ON -= -Wall # Optional - disable warnings when compiling this library
HEADERS += \
crc32.h \
deflate.h \
gzguts.h \
inffast.h \
inffixed.h \
inflate.h \
inftrees.h \
trees.h \
zconf.h \
zlib.h \
zutil.h
SOURCES += \
adler32.c \
compress.c \
crc32.c \
deflate.c \
gzclose.c \
gzlib.c \
gzread.c \
gzwrite.c \
infback.c \
inffast.c \
inflate.c \
inftrees.c \
trees.c \
uncompr.c \
zutil.c
If you are building something other than zlib, just change TARGET to the name of the library, and replace the contents of HEADERS and SOURCES with the files that need to be compiled for your library.
You can go ahead now and test out this .pro file.
~/myApp/zlib/ $ qmake
~/myApp/zlib/ $ make
...
~/myApp/zlib/ $ ls libz.a
libz.a
Yay!
Link The Library Into Your Application
Finally, we need to update the .pro file of your application to link in the 3rd party library. There are two parts to this:
Add library header files to your include path so the compiler can get the defined symbols from there.
Link the static (or shared) library during compile and linking time so the applicable object code can get linked into your application.
First, we'll add the header files into the include path. Add this line to src.pro.
INCLUDEPATH += zlib
This allows you to reference zlib.h in your code like so:
#include "zlib.h"
Otherwise, you would have to specify the full relative path of the header like this:
#include "zlib/zlib.h"
If you're fine with the second method, then there should be no need to update the INCLUDEPATH variable.
Second, we need to add the arguments the linker needs to find the static (or shared) library itself. Add this line to src.pro.
LIBS += -L$$PWD/../zlib -lz
The first part (-L$$PWD/../zlib) says that the folder containing the library is at ../zlib, which should be correct since zlib is a sibling folder to src. The second part (-lz) says that the name of the library is z. The linker infers from this that the library is actually located in the file libz.a.
Done
At this point, you may have to clean your build by doing a make distclean. But from there you should be able to build your project with the 3rd party library included by going to your base directory and running qmake and make.
cd ~/myApp
qmake -r
make
Note: Big thanks go to #LaszloPapp for getting this process started. Much of the source material for this answer came from his answer.

Alternatively if you are using QT Creator you could try to investigate "Project Settings" -> "Add Build Step" -> "Custom build step" and add script file there.
This could help to build lib before and then you just need to link it to your project.
I'm not sure, but most likelly you could pass the compilers settings like an argument to this script. I'm triing to solve it right now.

Related

Qt Creator (not CMake) how to specify different files for different build configurations?

I have project in QT Creator (as .pro file, not as CMake). Now I want to add tests (gtest) as another build configuration, so I've added build configuration "debug_tests" (Projects -> Add -> Debug with name debug_tests).
Now I want to add specific main file for "debug_tests" and exclude from build my normal main file when the build configuration is choosen.
So I've tried:
test_debug:{
message("Running tests:")
SOURCES += \
tests/MultiCellArticleModelTests.cpp \
tests/main_tests.cpp
LIBS += \
-lgtest
}
But it is not working, it is working when I do like that:
!debug_and_release:{
message("Running tests:")
SOURCES += \
tests/MultiCellArticleModelTests.cpp \
tests/main_tests.cpp
LIBS += \
-lgtest
}
But it is not good solution if I want to add more configurations.
Another solution which I see is to just add defines to compilation and have ifdef in my code.
Usually, tests are in their own sub-projects rather than part of some scope in your main source tree.
This allows you to keep them cleanly separated from your main code and you can run them easily. You can even call make check to run the whole test suite that you created for your library/application.

Qt5 - Windows :Windows cannot find executable

I am trying to build a project using Windows 10 and Qt5.12. The small program is using the smtp protocol available here. I can confirm that on my Windows I have the OpenSSL 1.1.1c 28 May 2019. On my Ubuntu 19.04 the same exact program compiles and run as usual but not on Windows.
I git clone my repository into Windows, followed successfully this post and the program builds correctly.
The problem is that when I run it, it cannot find the executable and is asking for it as it is possible to see from the print screen below:
here is my .pro file:
QT += quick quickcontrols2 concurrent network core gui
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Refer to the documentation for the
# deprecated API to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
TARGET = SMTPEmail
DEFINES += SMTP_BUILD
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
progressbardialog.cpp \
robot.cpp \
robotmanager.cpp \
settings/emailaddress.cpp \
settings/mimeattachment.cpp \
settings/mimecontentformatter.cpp \
settings/mimefile.cpp \
settings/mimehtml.cpp \
settings/mimeinlinefile.cpp \
settings/mimemessage.cpp \
settings/mimemultipart.cpp \
settings/mimepart.cpp \
settings/mimetext.cpp \
settings/quotedprintable.cpp \
settings/smtpclient.cpp \
user.cpp \
usermanager.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
HEADERS += \
progressbardialog.h \
robot.h \
robotmanager.h \
settings/SmtpMime \
settings/emailaddress.h \
settings/mimeattachment.h \
settings/mimecontentformatter.h \
settings/mimefile.h \
settings/mimehtml.h \
settings/mimeinlinefile.h \
settings/mimemessage.h \
settings/mimemultipart.h \
settings/mimepart.h \
settings/mimetext.h \
settings/quotedprintable.h \
settings/smtpclient.h \
settings/smtpexports.h \
user.h \
usermanager.h
On my Desktop it is created automatically the build folder and thought that the executable would have been here. Below I Am also attaching a print screen of what is inside the build folder:
Originally this project was deployed on Ubuntu and that gave me no problem. I git clone that repo into my Windows, added the missing SMTP_BUILD but I can't fine the executable that the window in the print screen is asking. What am I missing for this final step?
Thank you very much for pointing in the right direction.
As shown in the image of your .pro you are using TEMPLATE = lib whose objective is to create a library whose product is a .dll, .so, etc. that is not an .exe.
If you want to generate an executable you must use:
TEMPLATE = app
Plus:
To make it easier to include the library in your project, I have created this project whose objective is to provide a .pri that is easy to link to any project with .pro. To do this you must follow the following steps:
Download the project
Add include(/path/of/SMTPEmail.pri) to your .pro
Includes using #include <SmtpMime>

How to make makefile generated by Qt without qmake dependency

I use Qt creator in linux to make my non-Qt c++ project. I find that Qt creator would make a makefile for me. I want to move all the project into a computer without any qt or qmake, but I cannot really edit the makefile myself. As I google that someone says add a CONFIG -= qt flag can make a pure g++ makefile without any qt component but actually not.
the pro file in my project is like this:
QMAKE_LFLAGS += -no-pie
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt
INCLUDEPATH += /home/MyName/opencvBuild/install/include/opencv4/
LIBS += -L/home/MyName/opencvBuild/install/lib/ \
-lopencv_core \
SOURCES += \
main.cpp \
helloopencv.cpp
HEADERS += \
helloopencv.hpp
and the makefile generate thousands of Qt dependencies like:
.....
###### Files
SOURCES = ../HelloOpenCV/main.cpp \
../HelloOpenCV/helloopencv.cpp
OBJECTS = main.o \
helloopencv.o
DIST = ../Qt/5.12.0/gcc_64/mkspecs/features/spec_pre.prf \
../Qt/5.12.0/gcc_64/mkspecs/common/unix.conf \
../Qt/5.12.0/gcc_64/mkspecs/common/linux.conf \
../Qt/5.12.0/gcc_64/mkspecs/common/sanitize.conf \
../Qt/5.12.0/gcc_64/mkspecs/common/gcc-base.conf \
.....
now when I call make command in terminal it would automatically link to qmake.
I don't want any "Qt" in my makefile. What should I do?
These are not "Qt"-dependencies, but rather "qmake"-dependencies: it's a list of files which qmake had processed in order to generate your Makefile. Stuff like gcc-base.conf is needed for some common gcc options, sanitize.conf for a bunch of -fsanitize= options, and so on.
Thus, it's the list of the files your Makefile itself depends on (used for auto-regeneration and such). Of course, if you don't intend to ever regenerate Makefile with the help of qmake, you can just delete all these lines at once.
You complain that despite of having CONFIG-=qt in your .pro, there is still a bunch of qt_config.prf and other such files mentioned in that list. This is true, however qmake startup scripts designed precisely in this way: first, all Qt-related stuff is unconditionally preconfigured; then the user project is processed; and then, only if CONFIG += qt, the relevant Qt stuff finally becomes enabled.
Just for fun, you can mess with qmake startup code: go to <prefix>/share/qt5/mkspecs/linux-g++-64 (or whatever your QMAKE_SPEC is); open the file qmake.conf; comment out the last string: #load(qt_config). Now your CONFIG -= qt project should be processed okay, but the resulting Makefile will be significantly smaller. But the price is that qmake cannot do Qt-enabled projects anymore (well, in fact, you can add load(qt_config) on top of your .pro file and it may even work - no warranties of any kind, of course ;-).

How to reference 3rd party dlls/libraries in Qt projects

Been trying to figure this out for an hour now. What I have is a simple Qt Project open in Qt Creator. What I would like to do is use the SDL library (dll) with my Qt project.
In visual Studio, what I would normall do is add a reference to this dll using VS tool that provides for that. In Qt creator, I opened the .pro file for my project, and added a LIB entry for the STD dll
# Add more folders to ship with the application, here
folder_01.source = qml/BoxGame
folder_01.target = qml
DEPLOYMENTFOLDERS = folder_01
# Additional import path used to resolve QML modules in Creator's code model
QML_IMPORT_PATH =
symbian:TARGET.UID3 = 0xEED812B5
# Smart Installer package's UID
# This UID is from the protected range and therefore the package will
# fail to install if self-signed. By default qmake uses the unprotected
# range value if unprotected UID is defined for the application and
# 0x2002CCCF value if protected UID is given to the application
#symbian:DEPLOYMENT.installer_header = 0x2002CCCF
# Allow network access on Symbian
symbian:TARGET.CAPABILITY += NetworkServices
# If your application uses the Qt Mobility libraries, uncomment the following
# lines and add the respective components to the MOBILITY variable.
# CONFIG += mobility
# MOBILITY +=
LIBS += C:\Users\vata\Desktop\DskProj\Dsk-build-desktop\debug\SDL.dll
# The .cpp file which was generated for your project. Feel free to hack it.
SOURCES += main.cpp \
blockboxes.cpp \
block.cpp \
boxengine.cpp \
boxgame.cpp \
point.cpp \
gamecontroller.cpp \
gamecontrollermod.cpp
# Please do not modify the following two lines. Required for deployment.
include(qmlapplicationviewer/qmlapplicationviewer.pri)
qtcAddDeployment()
HEADERS += \
blockboxes.h \
block.h \
boxengine.h \
boxgame.h \
Globals.h \
point.h \
gamecontroller.h \
gamecontrollermod.h \
controller.h
However, that does not seem to include the Library in Qt for my use. When I compile, I still get an SDL.h: No such file or directory error message. Would appreciate any help in figuring this out and probably learning for the future as I intend to use Qt more often than not for my development work.
Running build steps for project Tetris...
Starting: "C:\QtSDK\mingw\bin\mingw32-make.exe" clean
C:/QtSDK/mingw/bin/mingw32-make -f Makefile.Debug clean
SDL.h is a C header file, not a library. For the compiler to find it, you need to add its directory to qmake's INCLUDEPATH. For example:
INCLUDEPATH += C:/Dir/Where/SDL/Headers/Are/Found
(Tip: you can use / instead of \ to stay clear of possible interpretations of \ as an escape character.)
Try something like:
LIBS += -LC:\\Users\\vata\\Desktop\\DskProj\\Dsk-build-desktop\\debug -lsdl

QtCreator and OpenCV

I managed to compile successfuly programs that use OpenCV with QtCreator but i have a problem with the dlls when i try to execute my application.
This is the error i get. The wierd thing is that i don't have this dll in my system.
I tried to download it and place it in the same directory with the executable but i get the same error.
here is my .pro file
LIBS += -Lc:/Users/Libraries/OpenCV2.3/build/x86/mingw/bin/
LIBS += -lopencv_calib3d230 \
-lopencv_contrib230\
-lopencv_core230 \
-lopencv_features2d230 \
-lopencv_flann230 \
-lopencv_gpu230 \
-lopencv_highgui230 \
-lopencv_imgproc230 \
-lopencv_legacy230 \
-lopencv_ml230 \
-lopencv_objdetect230 \
-lopencv_video230
INCLUDEPATH += c:/Users/Libraries/OpenCV2.3/build/include/
SOURCES += \
main.cpp
Anyone that knows why this problem occurs?
I found what was going wrong.
I compiled opencv again and changed my .pro file to link from that folder.
Linking with the opencv-superpack package that is provided for windows caused this problem.
I hope this will help others facing the same problem.
Did you try, instead of simply putting the dll in the folder to add it to the path of your system ?
On win XP it's something like:
Configuration Panel > System > Advanced > Paths
Downloading a versioned DLL probably won't work. libstdc++-6.dll should be in the bin directory of your MinGW installation (which was probably included with QtCreator, check there).
You must distribute this dll with your app (or link with -static) or at least add its directory to PATH.