Including a library when compiling - c++

First, Background info: Ubuntu 10.10, gcc 4.4.5, C++, Qt Creator 2.3.1, FLANN.
Problem: Every time I compile my code I get an error saying 'undefined reference to [function from FLANN]'.
Explanation: I've been working on a GUI in Qt Creator that will utilize a few classes I built that include references to the FLANN library (not necessarily that important to know). Everything was going smoothly until I incorporated these classes and their header files, of course. I added the library to the .pro file just in case, but that didn't solve my problem. I narrowed down the situation to how Qt is making the files as compared to how I was making the files when I was testing my classes with a Makefile:
My Makefile: g++ -g process_stuff.o driver.o -o test.exe /usr/local/lib/libflann_s.a
I'm appending this library to the end of the gcc command, and it works perfectly. Further, if I remove the /usr/local/lib/libflann_s.a I get the same error making it myself that I got out of Qt.
Question: What exactly am I doing by including the library at the end of my gcc calls, and what can I do to have this happen in Qt Creator? All help is appreciated, and thanks in advance.

The short answer to what you're doing by adding the library at the end of the gcc command is telling the build system where it can find the library and what library you want to link into your code. The -L part indicates the path to libraries and the -l is the name of the library you wish to link against. Both of which I suspect are not being included in your Qt Project file, which is why it isn't building when you're running it normally. You can add the two in the project as:
INCLUDEPATH += $$quote(/usr/local/include)
LIBS += $$quote(-lflann_cpp_s) \
$$quote(-L/usr/local/lib/)

External libraries are usually provided in two forms: static libraries and shared libraries. Static libraries are the ‘.a’ files . When a program is linked against a static library, the machine code from the object files for any external functions used by the program is copied from the library into the final executable.

But moments later.... unix:!macx:!symbian: LIBS += -L$$PWD/../../../../usr/local/lib/ -lflann_cpp_s Upon fixing that to: unix:!macx:!symbian: LIBS += -L$$PWD/../../../../usr/local/lib/ -lflann_s
The Qt library wizard decided to include the wrong file as the library. After changing the file, everything works.

Related

Adding static library link line to my Qt project file makes no difference

I've read a lot of "duplicate" posts on the subject of statically linking your Qt project on windows to statically built Qt core libs. However, I was left very confused when I compared it to what I am seeing. What I gathered from all the posts is if you already have the statically built Qt libs (which I seem to have here C:\Qt\5.4\mingw491_32\lib) all you need to do is to include a line like so
LIBS += -LC:/Qt/5.4/mingw491_32/lib -lQt5Core -lQtGui
in your .pro file without having to specify -static anywhere. However, this line seems to do exactly ZERO. When I comment it out my project builds exactly the same way without it. The exe is the same size and when I try to run it from command prompt a runtime error appears in a dialog box saying it can't find Qt5Core.dll. Its clearly still linking dynamically. What am I doing wrong? Here is the whole .pro file.
#QT +=
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = testproj
TEMPLATE = app
SOURCES += main.cpp mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
QMAKE_CXXFLAGS +=-std=c++11
#LIBS += -LC:/Qt/5.4/mingw491_32/lib -lQt5Core
I clearly have major holes in my understanding of how Qt linking works on windows. Any help on this topic is highly appreciated.
Qt does not distribute static builds.
It seems you only have a dynamic build and got confused by the .lib/.a files. On Windows, there are 3 types of library:
Dynamic libraries (.dll)
Static libraries (.a or .lib depending on the toolchain)
Import libraries (.a or .lib depending on the toolchain)
Import libraries are only used with dynamic libraries. The import libraries are used by the linker when generating the exe, while the dynamic libraries are used at run time.
So if you have Qt5Core.lib or Qt5Core.a does not mean you have a static build of Qt.
To build your own static version of Qt, I suggest your read Building a static Qt for Windows using MinGW on Qt's wiki.
The major hint is: no matter how Qt is built, you shouldn't need to change anything in the project that uses Qt. Qmake and the configuration files in a given Qt install govern how the applications that use Qt are linked against Qt.
Another hint: a given Qt installation can be either configured for static or dynamic linking, not both. Thus any sort of configuration on the project end is superfluous: a given Qt install already "knows" how to link Qt correctly.
Any given .pro file should work whether Qt is linked statically or dynamically. You should not have any static-linking-specific entries. Remove the LIBS line from the project.
If your executable is dynamically linked, the only reason is that you're using a dynamically linked build of Qt. You should make a static build yourself first, and then use it with your project, and your executable will be statically linked against Qt. It's that simple.
Qt Creator doesn't care about these details either. All it does is invoke qmake and then the make tool. But each qmake is specific to a particular installation of Qt, and that qmake is configured to access that installation's configuration files, and those files contain the data needed to select the proper linking etc. So all of the information is specific to a particular kit one is using, and specifically to the Qt "version" that kit is using (really, a Qt installation because there can be multiple installs of the same version, configured differently).

Error compiling C++ program against GeoIP library

I'm trying to compile a simple program using the GeoIP2 lite API. I've compiled the GeoIP Lite program and it created the library files. The .la file is in /mydir/libmaxminddb-0.5.3/src
I modified my .pro file to include:
LIBS += /mydir/libmaxminddb-0.5.3 -lmaxminddb
but when I compile my project errors with "Cannot find -lmaxminddb"
Can someone tell me what's wrong? I've tried changing directories, adding a "lib" prefix to the maxminddb, and more, but I can't figure it out.
(I'm trying to link against libmaxminddb.a which is pointed to by libmaxminddb.la)
I believe in autoconf and friends the -l flags go in the LDFLAGS variabe, not LIBS.
I found elsewhere that with Qt Creator you can right click the project and add an external library. When I do so, I see the .pro file adds:
LIBS
INCLUDEPATH
DEPENDPATH
So that's what you need to add!
That should be LIBS += -L/mydir/libmaxminddb-0.5.3 -lmaxminddb. Note the extra -L in front of the directory name.

Qt 3rd Party Library Static Linking (QtSerialPort)

Turns out static linking was working, but only for Qt libraries. My 3rd party library QtSerialPort is not linking statically. After some reasearch, I've found that I either have to build this library statically or I have to link directly to a .pri file in my .pro file.
I'm not sure how to do either since it seems QtSerialPort has not been designed for static linking.
The .pri method I really don't understand and has been vaguely described in these two links:
http://qt-project.org/forums/viewthread/15223
http://www.qtcentre.org/archive/index.php/t-54505.html
Does anyone have any adivce on how to get either of these methods to work? Or possibly another method?
Also, MSVCP100.dll is not linking statically if anyone could give me any advice on that.
==================================================================================
I am trying to get Qt to statically link libraries so that I can make a standalone application. I have followed various tutorials on how to build Qt statically then building a static application but I am not having much luck. I believe I have succesfully built Qt with static linking because the application has grown in size from 79KB to 7+MB but I am still getting errors saying QtCore4.dll and QtSerialPort.dll are missing. Also, another issue I'm having when using this static configuration, which isn't too serious, is that when I close my program Windows thinks it has crashed and gives me a window saying MyProgram.exe has stopped working...
I am on a Windows machine using MSVC 2010 with Qt 4.8.5 and am using the third party library QtSerialPort.
What I've done accoring to the guides I've been reading is:
Download and extract qt-everywhere-opensource-src-4.8.5.zip
Open /mkspec/mwin32-msvc2010/qmake.conf and change the follwing lines to
CONFIG += qt warn_on release incremental flat link_prl precompile_header autogen_precompile_source copy_dir_files debug_and_release debug_and_release_target
and
QMAKE_CLFAGS_RELEASE = -O2 -MT
I then open the MSVC2010 command prompt and cd to this . I then enter the commands
configure -static -release -platform win32-msvc2010
nmake sub-src
After this is done I open my project and add
CONFIG += static
to the .pro file. In QtCreator I then go into Projects, Manage Kits then to Qt Versions and browse to the qMake I just generated. I add a new Kit with this version of qMake. I then clean all and switch to this new kit and run qmake from QtCreator. I then use msvc2010 command prompt to go to the directory where the files are generated and then
nmake release
This generates a rather large .exe but like I said, it's still depending on a couple .dll's.
For static linking of external library one have a couple options, both have their pros and cons.
I. Compile the library for static linking yourself. Link to it.
Look for possible existing configuration switches for static linking. There can be something like QTSERIALPORT_STATIC = no, etc. in the library's .pro/.pri files. Just say yes for the library to compile for static linking and go to the step 4!
In .pro/.pri file replace CONFIG += dll with CONFIG += static.
Remove export declarations from the library. Typically Qt library symbols are declared with some definition like QTSERIALPORT_EXPORT which expands to Q_DECL_EXPORT/Q_DECL_IMPORT in shared library build / its header files usage when linking. You'll need to find where this QTSERIALPORT_EXPORT is defined and replace it with empty definition:
#define QTSERIALPORT_EXPORT // in source file
or
DEFINES += QTSERIALPORT_EXPORT # in .pro/.pri file
Build the library.
Link to the library .lib/.a file, use the library header files for symbol declarations in your project.
II. Include the library source files into your project and compile them within it (no linking at all).
Include all the source files of the library into your project (add to SOURCES in qmake project file)
Determine all the stuff the library depends on (other libraries, Qt options, etc.) and include it also into your .pro file.
OR
Include the proper .pri file into your .pro if the library author provides it for in-project compilation (i.e. include(QtSerialPort.pri) or something.)
Remove export/import declarations from the library source code — as described in the item 3 of part I.
Build your project.

C++ Qt: Static builds and external dylibs

I've been doing some funny stuff in personal projects with Qt. I'm not an expert in this so if it's a dumb question (guess not I couldn't find anything useful) feel free to kill me.
Anyway, I'm in OSX and usually I compile the final versions against a static version of Qt using a shell script with this commands:
cd "project folder...";
PATH=/Users/TCB13/(...)/qt-source/bin:$PATH; --> Path to my static QT.
export PATH;
qmake -config release;
make;
make clean;
So far if I move the compiled binary to another computer without Qt installed everything works just fine! ;)
Yesterday I start to play around with a dynamic library provided by a company and I've included the dylib in my .pro file like this: (I've a copy of the dylib in the project folder)
#macx: LIBS += -L$$PWD/ -lwpsapi
#INCLUDEPATH += $$PWD/
#DEPENDPATH += $$PWD/
And when I compile it "statically" (using the commands above) and run it on the other computer I get:
dyld: Library not loaded: #executable_path/libwpsapi.dylib
Referenced from: /Users/TCB13/Desktop/dude111
Reason: image not found
Trace/BPT trap: 5
I noticed that the size of my compiled binary is the same with or without including the dylib so, I googled how to include and external lib and some people are saying that I need to add "CONFIG += static" to my .pro file. I did it and the size of the file increased but I still got the same error.
Hope someone can help me.
The error message is pretty clear, you need to distribute libwpsapi.dylib with your application. If you want to avoid that, consult the documentation of this third-party library to make it use the statically linked code. Note that the fact that you are telling the linker to link a static library, does not mean that the code is referenced. I suspect that there is some kind of preprocessor #define in the code (or defaulted) to use the dynamically loaded library.

Compiling my Boost/NTL program with c++ on Linux

I wrote a client program and a server program, that uses the NTL library and Boost::Asio, to do client/server communication for an integer factorization application, in C++.
Both sides consist of several headers and cpp files. Both project compile fine individually on Windows in Visual Studio. All I did, was add the include path of NTL and Boost to both projects:
Additional include paths: "D:\Downloads\WinNTL-5_5_2\include";D:\boost_1_42_0
Furthermore, for both projects, I added the two library paths to both projects in VS:
Additional library directories: D:\boost_1_42_0\stage\lib;"D:\Documents\Visual Studio 2008\Projects\ntl\Debug"
And added under Additional dependencies:
ntl.lib
As said, it compiles fine on Windows. But when I put the code on a Linux machine provided by university, I try to compile with the following statement
c++ -I/appl/htopopt/Linux_x86_64/NTL-5.4.2/include -I/appl/htopopt/Linux_x86_64/boost_1_43_0/include client_protocol.cpp mpqs_client.cpp mpqs_sieve.cpp mpqs_helper.cpp -o mpqs_helper -L/appl/htopopt/Linux_x86_64/NTL-5.4.2/lib -lntl -L/appl/htopopt/Linux_x86_64/gmp-4.2.1/lib -lgmp -lm -L/appl/htopopt/Linux_x86_64/boost_1_43_0/lib -lboost_system -static
Upon doing this, I get a huuuge error, which I posted here. Any idea how to fix this, please??
You are getting lots of errors to do with missing pthread symbols. Try adding
-lpthread
to your link line.
I'm not sure, but I suspect you can't do multi-threading in a staticly linked binary.