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

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.

Related

libstdc++.so.6: error adding symbols: DSO missing from command line

I have started learning C++ on Ubuntu. I am only a few months into using Linux as well.
I am attempting to port over a 2D Ball Collision Script from Javascript to C++ for learning purposes.
I am using simple2D for the drawing in C++: https://github.com/simple2d/simple2d
I go to run this command:
simple2d build c-code-test.cpp
I receive this response:
cc1plus: warning: command line option ‘-std=c11’ is valid for C/ObjC but not for C++
/usr/bin/ld: /tmp/ccl07DBG.o: undefined reference to symbol '_ZNSt8ios_base4InitD1Ev##GLIBCXX_3.4'
//usr/lib/x86_64-linux-gnu/libstdc++.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
Due to how fresh I am with Linux and C++ I am unable to make the correct inferences to solve this based on previous questions on stack overflow. I have installed libstdc++6 so I would have though it would be linked correctly.
Can someone walk me through in steps 1, 2, 3 ... Please? Thank you kindly!
The errors you see look to be from trying to compile C++ as C. The command line option is selecting the C11 standard, which is for C, not C++. The missing symbol is because the C++ library isn't being linked in, which also happens when linking a program as C.
I haven't used simple2d, but my guess here is that the compile script they wrote does not support C++ or there is some option you need to use C++. If we look at docs:
The simple2d build command is a helpful shortcut for compiling a
single source file. Of course, you can also use a compiler directly,
for example on Unix-like systems:
cc triangle.c `simple2d --libs` -o triangle
Why don't you try something like their example that invokes the compiler directly. But you would need to use g++ instead of cc. Something like: g++ c-code-test.cpp `simple2d --libs` -o c-code-test
This is a bug with the simple2d script.
They're basically using the wrong build command for C++.
You could work around it by patching in the fix I've linked to, or using the manual build step shown by TrentP.
Or wait for the next version after v1.1.0.

Unable to link CCfits example program

This is probably related to
c++ reading fits file using ccfits
which was never answered.
Anyway, I hope my question is easier to reproduce. There is an example program for CCfits at:
http://heasarc.gsfc.nasa.gov/fitsio/CCfits/html/cookbook.html
I am attempting to compile this using:
g++ cookbook.cpp -o cookbook -lCCfits -lcfitsio
The link fails for every CCfits function in the file:
/tmp/cc7hVaju.o: In function main':
cookbook.cpp:(.text+0x14): undefined reference towriteImage()'
cookbook.cpp:(.text+0x31): undefined reference to writeAscii()'
cookbook.cpp:(.text+0x4e): undefined reference towriteBinary()'
cookbook.cpp:(.text+0x6b): undefined reference to copyHDU()'
cookbook.cpp:(.text+0x88): undefined reference toreadHeader()'
cookbook.cpp:(.text+0xa5): undefined reference to readImage()'
cookbook.cpp:(.text+0xc2): undefined reference toreadTable()'
cookbook.cpp:(.text+0xdf): undefined reference to readExtendedSyntax()'
cookbook.cpp:(.text+0xfc): undefined reference toselectRows()'
collect2: error: ld returned 1 exit status
I have tried this with the CCfits package that comes with Ubuntu. I have also tried installing the package myself. Same error.
Strangely, I get similar messages if I do not include the libraries on the command line (i.e., "g++ cookbook.cpp -o cookbook"). The one difference is that I also get this error:
/tmp/ccMVMkSB.o: In function CCfits::FITS::setVerboseMode(bool)':
cookbook.cpp:(.text._ZN6CCfits4FITS14setVerboseModeEb[_ZN6CCfits4FITS14setVerboseModeEb]+0xf): undefined reference toCCfits::FITS::s_verboseMode'
This must be a clue, right? Seems to say that the libraries I have named, although they exist, do not contain all the functions I need.
Thanks for any help,
Charles
Not sure if you got a suitable answer to this question but as far as I can tell the main issue is that you are not including the definitions to the function signatures. These are usually defined in the header files of c++ libraries.
For example, if your library is installed in "/usr/local" on a UNIX system then the header files will be installed in the location "/usr/local/include/CCfits". The corresponding lib files will be installed at "/usr/local/lib". The important thing is that the compiler does not know this and you need to inform it of these locations.
g++ cookbook.cpp -o cookbook -I /usr/local/include/CCfits -L /usr/local/lib -lCCfits -lcfitsio
The "-I /usr/local/include/CCfits" flag and the given parameter inform g++ of the location of the header files that it is looking for. The "-L /usr/local/lib" flag and the given parameter inform g++ of the location of the library files. It is important to note that g++ will search in the standard location for libraries on in your environment as well this is just giving it more locations to search. There are in fact rules for what it should do if it finds multiple libraries which are the same in different locations but I don't explicitly remember those.
Also to be safe, ensure that the libraries are loaded into memory by the OS. These are shared libraries not static so they are not stored into the executable file. This won't make a difference when compiling the source but will prevent the successful execution of the executable. To ensure that the OS has loaded the library into memory run the following command:
sudo ldconfig
Yours Aye,
Omar EQ

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.

What's -fPIC compile option?

Today, When trying to build my so lib project with mongodb c++ client, I got the error:
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../libmongoclient.a(connection_factory.o): relocation R_X86_64_32S against `_ZTVN5mongo17AScopedConnectionE' can not be used when making a shared object; recompile with -fPIC
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../libmongoclient.a: error adding symbols: Bad value
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I googled -fPIC, but got nothing. Where can I find the doc about this? What's this? I am using clang++ for building.
PIC stands for Position Independent Code. Quoting from man gcc:
If supported for the target machine, emit position-independent code,
suitable for dynamic linking and avoiding any limit on the size of the
global offset table.
You compiled shared library without having relocatable code turned on at compile time. It is strongly suggested to use position independent code (PIC or PIE) when building shared libraries.
Please refer http://en.wikipedia.org/wiki/Position-independent_code for more details.
There is a bug in this system,you can not use .o or .a compiled intermediate file to generate dynamic lib(xx.so file),you may try to directly use the .cpp or .c file to generate a dynamic lib,also you may see this link to fix this bug (link site)

OpenCV 2.4.1 static linking with Qt

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.