OpenCV 2.4.1 static linking with Qt - c++

I have compile OpenCV 2.4.1 statically without error using MinGW and CMake. I checked With_QT
I just unchecked BUILD_SHARED_LIBS and proceed with mingw32-make and mingw32-make install.
It was built without error and eventually I have bunch of .a file in the lib folder of opencv.
But after setting LIBS and INCLUDEPATH parameters of .pro file and running a simple application in Qt I have got errors.
I also add the following line to .pro file:
CONFIG += -static -static-libgcc
I provided last line error:
F:\OpenCV2.4.1\opencv-static\install\lib\libopencv_highgui241.a(grfmt_jpeg2000.cpp.obj):grfmt_jpeg2000.cpp:(.text$_ZN2cv13Jpeg2KDecoder10readHeaderEv+0x4f):
undefined reference to `jas_image_decode' collect2: ld returned 1
exit status mingw32-make[1]: ***
[release\test.exe] Error 1
mingw32-make: *** [release] Error 2 The process "C:/ming44/bin/mingw32-make.exe" exited with code %2. Error while building project test (target: Desktop) When executing build step 'Make'
Update
I figured out that the error is just when I call highgui.hpp methods. like the following error when I use cv::imshow():
F:\OpenCV2.4.1\opencv-static2\install\lib\libopencv_highgui241.a(window_w32.cpp.obj):window_w32.cpp:(.text$_ZL17icvCreateTrackbarPKcS0_PiiPFviEPFviPvES4_+0x5e1): undefined reference to `CreateToolbarEx#52' collect2: ld returned 1
exit status mingw32-make[1]: *** [release\test.exe] Error 1
mingw32-make: *** [release] Error 2
Can anybody help me solve this problem.
Thanks

There were many questions as we proceeded through the fix process, so I'll try to summarize the answers to all of them here.
Unresolved Symbols
undefined reference to `jas_image_decode'
The jas_image_decode symbol is defined in libjasper (which is a 3rd party dependency of OpenCV). To resolve it, link against libjasper.a.
undefined reference to `CreateToolbarEx#52'
The CreateToolbarEx symbol is part of Windows API, and is therefore defined in system libraries (which are always supplied with a toolchain, MinGW in your case). You can always find against which library you should link to resolve such symbols by looking in MSDN (scroll down and see Library and DLL cells). In this case, you can see Comctl32.lib, however MSDN of course posts names of libraries in the format that Microsoft Visual C toolchain defines them. Since you are using MinGW toolchain, you'd have to convert (mentally) this name into the Unix naming convention of libraries, and in this case that would be libcomctl32.a.
undefined reference to `AVIStreamRelease#4'
Similarly to the previous case we find it here, and infer that we have to link against libvfw32.a.
NOTE: The paths to such system libraries (containing Windows API) are always searched automatically by the toolchain. Therefore, you shouldn't supply -L option during compilation/linkage, but only the library itself, i.e. -lcomctl32.
undefined reference to `cv::dft'
Well, that's again some component from OpenCV (cv namespace obviously suggests that). A bit of searching reveals that it is defined in the Core component. Accordingly, to resolve that symbol, link against libopencv_core.a.
The Approach
How do I find out which library to link against to resolve the missing symbol?
There is no rule of thumb or any direct recipe here, but rather a number of tricks and educated guesses which primarily come from experience. Here are a few examples:
For instance, in case of CreateToolbarEx, it was quite easy for me
to guess that it belongs to Windows API as long as I recognize the
Windows API naming convention of the function name. Consequently,
what I do next is type CreateToolbarEx into Google, jump to the
corresponding page on MSDN, scroll down, see what the library name
is, convert (mentally) to the Unix naming convention of libraries (see above),
and voila!
The case of OpenCV is more tricky. OpenCV is a 3rd party library and
the question whether it'll be painful to find out the library where
certain symbol is defined solely depends on the quality of the
documentation provided. Although, I can see that the OpenCV
documentation is pretty good, it is still missing these important
hints for every symbol, and that's a pity. However, we (developers)
have to be able to cope with problems like that regardless of how
crappy the documentation of a 3rd party library is, and get the job done.
That's why it is always a good idea to use file content searching utility
such as grep (popular on Unix OS family, but available for Windows
too in MSYS distribution). This way, for example in case of
cv::dft, you could run grep -r "void.*dft(" . in the root of
OpenCV source tree, and track down where that symbol is defined in
no time. After that you'd have to infer to which component the file
containing cv::dft belongs, but that should be straightforward, just look
around and see in which directory the file resides.
Conclusion
I swear that I've never used OpenCV in my life, but as you can see I was still able to locate all these missing symbols for you. As a result, we can conclude that the proposed techniques of searching for unresolved symbols are sort of reliable.
Finally, nothing of this is specific to OpenCV or Qt. You're dealing with basic programmer craftsmanship skills here. If you want to be productive software developer capable of solving such day-to-day routines rapidly, then grep is just one of many essential utilities which should undoubtedly be the part of your tooling arsenal.

Related

Gurobi and C++- How it works together using Clion

First of all I am complete new to C++, so if you know the answer please be patient with me ;). Here my problem:
I wanna solve an IP with Gurobi in a C++ Code. The Code itself seems fine since there are no expression marked as errors. However when I run the Code I get the following error report:
Undefined symbols for architecture x86_64:
and many lines like that:
"GRBLinExpr::GRBLinExpr(GRBVar, double)", referenced from:
bridge_problem::max_flow_lp(time_expanded_network&, lemon::ListDigraph&, lemon::DigraphExtender<lemon::ListDigraphBase>::ArcMap<int>&, lemon::DigraphExtender<lemon::ListDigraphBase>::ArcMap<int>&, lemon::DigraphExtender<lemon::ListDigraphBase>::NodeMap<int>&) in bridge_problem.cpp.o
I suppose that the mistake is in my CMakeList.txt file. This file was automatically created since I am using Clion and for including gurobi I entered those additional lines:
include_directories(/Library/gurobi604/mac64/include)
link_directories(/Library/gurobi604/mac64/lib/libgurobi_c++.a)
link_directories(/Library/gurobi604/mac64/lib/libgurobi60.so)
Any help is greatly appreciated and if you need any more information just let me know. (In case it is important I using a mac).
EDIT: I changed my make code since I found this one:
https://github.com/joschu/trajopt/blob/master/cmake/modules/FindGUROBI.cmake
I changed the version since I have gurobi604 but it still does not work. My new error message is:
fatal error: 'gurobi_c++.h' file not found #include "gurobi_c++.h"
I don't get it since I thought by
find_path(GUROBI_INCLUDE_DIR
NAMES gurobi_c++.h
PATHS "$ENV{GUROBI_HOME}/include"
"/Library/gurobi604/mac64/include"
"C:\\libs\\gurobi604\\include"
)
that should be easy to find. Any suggestion?
From the small excerpt of your CMakeLists.txt, I expect you should be using target_link_libraries rather than link_directories.
I'd normally recommend linking to the static version of any library rather than the shared if possible (i.e. in this case prefer "libgurobi_c++.a" over "libgurobi60.so" assuming they're the same library, just compiled differently).
So, if your exe is called MyExe, you could do:
target_link_libraries(MyExe /Library/gurobi604/mac64/lib/libgurobi_c++.a)
Also, it's almost always best to avoid specifying hard-coded paths in your CMakeLists.txt. Although your copy of "libgurobi_c++.a" lives in "/Library/gurobi604/mac64/lib/", that won't be the case for other users, or on different platforms.
You can avoid this by having CMake "find" the library, for example by calling find_library:
find_library(Gurobi NAMES gurobi_c++)
if(NOT Gurobi)
message(FATAL_ERROR "Failed to find Gurobi lib. Try setting CMAKE_PREFIX_PATH")
endif()
target_link_libraries(MyExe ${Gurobi})
Then, when you run CMake, you just need to tell it where the Gurobi library is. I'm not sure how you do that in CLion, but for example if you were running CMake from the command line, you'd do:
cmake . -DCMAKE_PREFIX_PATH=/Library/gurobi604/mac64

How to solve C++ conflicts between system and library dependencies

My problem is rather specific, but bear with me.
This in the end is kinda reverse engineering, but this problem in particular seems to fit more this board.
So, I have a shared object compiled for MIPS written in C++. I don't have the source code of the lib. The lib is compiled using GCC 4.3.3. I want to use functions present in this shared object in my amd64 computer running elementary OS. To do this, I used the sourcery cross compiler to cross compile some C++ code to MIPS, that would use this object.
So far I managed this except for this one compile error, which I cannot figure out. The lib is called libdvl.so, and uses as dependency libc.so.0 (and both are in the same folder as the cpp code).
mips-linux-gnu-g++ -g -L/path/to/lib -Wl,-rpath,/path/to/lib -o verifier verifier.cpp -ldvl
which gives me
(...)/mgc/embedded/codebench/bin/../lib/gcc/mips-linux-gnu/4.9.1/../../../../mips-linux-gnu/bin/ld: warning: libc.so.0, needed by /path/to/lib/libdvl.so, may conflict with libc.so.6
(...)/mgc/embedded/codebench/bin/../lib/gcc/mips-linux-gnu/4.9.1/../../../../mips-linux-gnu/bin/ld: errno##GLIBC_PRIVATE: TLS definition in (...)/mgc/embedded/codebench/bin/../mips-linux-gnu/libc/lib/libc.so.6 section .tbss mismatches non-TLS definition in /path/to/lib/libc.so.0 section .bss
/path/to/lib/libc.so.0: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
So I added "-l:libc.so.0" and got this
(...)/mgc/embedded/codebench/bin/../lib/gcc/mips-linux-gnu/4.9.1/../../../../mips-linux-gnu/bin/ld: errno: TLS definition in (...)/mgc/embedded/codebench/bin/../mips-linux-gnu/libc/lib/libc.so.6 section .tbss mismatches non-TLS definition in libc.so.0 section .bss
(...)/mgc/embedded/codebench/bin/../mips-linux-gnu/libc/lib/libc.so.6: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
Any idea how to solve this? I know I am using GCC 4.9.1, but I already downloaded the older code sourcery version which uses GCC 4.3.154 and got the exact same error.
EDIT 1: Exactly as Lol4t0 said, filtered using c++filt it gives an actual function name from stdc++. Using
mips-linux-gnu-g++ -g -L/path/to/lib -Wl,-rpath,/path/to/lib -I/path/to/lib -o verifier verifier.cpp -ldvl -l:libuClibc++.so.0 -l:libutil.so.0 -l:libc.so.0 -l:ld-uClibc.so.0 -nodefaultlibs
to give to libdvl its depencies (as I will not rewrite stdc++ :p), I get the following compile error:
(...)/mgc/embedded/codebench/bin/../lib/gcc/mips-linux-gnu/4.9.1/../../../../mips-linux-gnu/bin/ld: /tmp/cc66DLda.o: undefined reference to symbol '_Unwind_Resume##GCC_3.0'
(...)/mgc/embedded/codebench/bin/../mips-linux-gnu/libc/lib/libgcc_s.so.1: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
I already confirmed lib dependencies and the order in which they appear.
Any thoughts on this?
Thanks for all the help.
Using -nodefaultlibs solves the first problem though.
You are linking against GLIBC (libc.so.6) and some other libc (libc.so.0).
That could never work: you have to have everything compiled and linked against a single, consistent libc.
Since your libdvl.so uses as dependency libc.so.0, and assuming you can't rebuild libdvl.so, you have to use crosscompiler that targets libc.so.0 (which is possibly dietlibc, or uClibc), and compile and link everything else using that toolchain. Your crosscompiler on the other hand appears to target GLIBC, and will not do you any good.
After a lot of trial and error, you may be able to link the final binary using inconsistent builds, and your binary may even get to main (that is very unlikely). But chances of such binary actually working correctly are minuscule.

Including expect/tcl library for C/C++

Recently I found an example of how to use the expect library in C++. I tried to compile it, but the compiler (g++) said, that tcl8.5/expect.h doesn't exists. So I tried to include tcl8.6/expect.h - still the same error. I checked the /usr/include/ directory and I wasn't surprised when I've noticed, that there is no tcl8.x directory.
I've searched for files with "expect" in their name. Here's what I found:
/usr/include/expect_tcl.h
/usr/include/expect_comm.h
/usr/include/expect.h
Unfortunately when I tried to include any of these I got the following list of errors during compilation:
> g++ test.cpp -Wall -std=c++0x -ltcl8.6 -lglog -o test
/tmp/cce8k1BA.o: In function `task(std::string const&, std::string const&, std::string const&)':
test.cpp:(.text+0x16): undefined reference to `exp_is_debugging'
test.cpp:(.text+0x20): undefined reference to `exp_timeout'
test.cpp:(.text+0x38): undefined reference to `exp_popen'
etc...
How can I solve this problem?
[EDIT]
When I tried to link it with the expect lib (-lexpect) I got the following error:
/usr/bin/ld: cannot find -lexpect
collect2: error: ld returned 1 exit status
I'm sure that both - tcl8.6 and expect 5.45-4 are installed.
The usual way of distributing Expect these days puts the shared library in a non-standard location and loads it dynamically by full pathname. This works well and is minimal fuss for most people, but does make it rather hard to use Expect's C interface in your own code.
The easiest way is going to be to build your own copy from source, especially as that will give you control over how exactly it was built. This can particularly include keeping the majority of symbols in the library instead of stripping them on install, which will help a lot with debugging. You probably ought to use the current supported version. (Yes, it's a release from several years ago. It doesn't need a lot of support effort most of the time.)
You haven't linked to the expect library during your build. Add -lexpect to your g++ command.

XCode 4.2 static libraries linking issue

I have Core static library, a few Component static libraries that relays on the Core one, and then there is an App that links against both Core and Component libraries. My App can link both against Core and Component as long as Component don't uses classes from Core (App uses classes from Core).
I got the following error in both armv6 and armv7 versions. So my problem is not the very popular linking issue that everyone has.
ld: symbol(s) not found for architecture armv6
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I added reference to Core in Component and even added it in "Link Binary With Libraries" which shouldn't be necessary for static lib.
Since I start having this issue I start doubting my design... It probably makes more sense in dynamically linking environment but still it should be doable in static one, especially since this already works under Windows with MSVC compilers.
Edit:
I made some progress! Although I still don't know where to go with it.
Here is my setup:
Core has a class cResourceManager that has a templated method GetResource<T>(int id)
Core also has class cResource
Component has class cMesh that inherits cResource
Here are some tests:
If I try from App to call rm->GetResource<cMesh>(...) I get the linking error
If I try from App to construct cMesh I get linking the linking error
If I try from App to call static method that will return new instance of cMesh I get the linking error
If I comment out the construction of cMesh but leave other member cMesh function calls the App links fine. I can even call delete mesh.
I have never seen anything like it!
If you remove the cMesh constructor, then you are then using the default (no argument, no body) cMesh constructor that is given to you. It almost sounds like there's a build error or missing code as a result of some code in your cMesh constructor and so the library isn't actually getting generated, and perhaps Xcode isn't reporting the error. Xcode is no good at reporting linker errors.
I would suggest looking at what symbols the linker says are missing and double-check that they are actually defined in your code. My guess is that you're using one of those symbols in your cMesh constructor. A lot of times with virtual base classes, you may forget to define and implement a method or two in a child class. Could be a result of missing a method based on your template, or your template isn't #included correctly. This could compile fine but result in linker errors like you're seeing.
If Xcode isn't showing you the full linker error, show the Log Navigator (Command ⌘+7), double-click the last "Build " entry, select the error, and then press the button on the far-right of the row that appears when selected. The symbols should be listed there. If not, it's time for xcodebuild in the Terminal.
If it's not that case, I'd be interested in seeing the results of whether or not the library is being built for the appropriate architecture, or maybe this can spur some progress:
In the Xcode Organizer Shift ⇧+Command ⌘+2, click Projects and find the path to the DerivedData for your project.
In the Terminal, navigate to that directory (cd ~/Library/Developer/Xcode/DerivedData/proj-<random value>/)
Remove (or move aside) the Build directory (rm -r Build)
In Xcode, try to build with the cMesh constructor present.
Find the Library product file (cd Build/Products/<scheme>-iphoneos)
Your compiled static libraries (<libname>.a) should be in this directory. If they're not there, they didn't build (unless you put your products elsewhere). If your libraries are there, let's confirm that they actually are getting built for the appropriate architecture. Run otool -vh <library>.a. You should see something like:
$ otool -vh libtesting.a
Archive : libtesting.a
libtesting.a(testing.o):
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC ARM V7 0x00 OBJECT 3 1928 SUBSECTIONS_VIA_SYMBOLS
As you can see, my test library was built for ARMv7.
Make sure you are linking them in the correct order.
If Component depends on symbols in Core, then Component needs to be first in the link order, so the linker knows which symbols to look for in Core.
In MSVC the order doesn't matter, but in most other compiler suites it does.
I don't think Clang generates code for armv6, if you're targeting devices that old you still need to use GCC.

Undefined symbol _main when trying to build logstalgia on mac

I have been trying to build the logstalgia project (http://code.google.com/p/logstalgia/) on my Mac (10.5). Rather than having to link it to the system libraries correctly, I have built and added all of the dependencies to the project. I am new at this, but I do think I have done this correctly, mostly because I have had two of my friends who are much more experienced say so.
Adding the frameworks removed all of the compile errors, but I still get a linker error. It seems to not be able to find the main() function. I have verified I included main.cpp in the sources to be compiled (using XCode) and that there are no accidental double declarations. I have also verified that the main function is correctly declared (no missing brackets, etc).
It is as though XCode does not link in the correct order. Any help would be really appreciated, I am really excited to be down to a single error! (Hope fixing this does not open a floodgate).
Thanks,
Hamilton
PS - I can definitely provide a zip of the Xcode project if anyone is willing to look!
Checking Dependencies
Ld "/Users/hamiltont/Downloads/logstalgia-0.9.2 2/Untitled/build/Debug/Untitled" normal i386
cd "/Users/hamiltont/Downloads/logstalgia-0.9.2 2/Untitled"
setenv MACOSX_DEPLOYMENT_TARGET 10.5
/developer/usr/bin/g++-4.0 -arch i386 -isysroot /developer/SDKs/MacOSX10.5.sdk "-L/Users/hamiltont/Downloads/logstalgia-0.9.2 2/Untitled/build/Debug" -L/sw/lib "-L/Users/hamiltont/Downloads/logstalgia-0.9.2 2/Untitled/../../pcre-7.9/.libs" -L/opt/local/lib -L/sw/lib "-F/Users/hamiltont/Downloads/logstalgia-0.9.2 2/Untitled/build/Debug" -F/Users/hamiltont/Downloads/logstalgia-0.9.2 -F2/src/SDL.framework "-F/Users/hamiltont/Downloads/logstalgia-0.9.2 2/Untitled" -filelist "/Users/hamiltont/Downloads/logstalgia-0.9.2 2/Untitled/build/Untitled.build/Debug/Untitled.build/Objects-normal/i386/Untitled.LinkFileList" -mmacosx-version-min=10.5 -framework OpenGL -lpcre -lSDL -lSDL_image-1.2.0 -prebind -o "/Users/hamiltont/Downloads/logstalgia-0.9.2 2/Untitled/build/Debug/Untitled"
Undefined symbols:
"_main", referenced from:
start in crt1.10.5.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
I got this error to go away. If I understand, essentially SDL re-names the main function, so that it can do some stuff, then run your application, then clean up. Turns out that if you are building in Xcode, you must use ObjectiveC to compile your application.
In Xcode, telling the linker to try and use SDL_main(), rather than just main() does not work (for some technical reasons that are a bit beyond me). So, you include a few Objective C files. In Oc, you get the benefit of being able to say explicitely what the name of your main class is. Hence, the Objective C files you include seem to do nothing more than let Xcode know to look for SDL_main().
In summary, this really had nothing to do with Logstalgia, but was entirely a problem with getting SDL to link correctly in Xcode. This link is talking about this problem exactly. The SDLMain.h and SDLMain.m are Objective C files. If you can't find them, try googleing "Setting up SDL templates in Xcode." I installed the templates in Xcode, used one of them to create an empty project that would compile, link, and run (and promptly do nothing!) and then I added the project files I wanted to the pre-configured project.
Thanks!
Double-check the link file list to make sure main.cpp's object file is present there:
/Users/hamiltont/Downloads/logstalgia-0.9.2 2/Untitled/build/Untitled.build/Debug/Untitled.build/Objects-normal/i386/Untitled.LinkFileList
You might also want to preprocess the main.cpp to make sure main isn't getting inadvertently renamed (via a rogue macro) or omitted (via a rogue #if).