How can I statically link a C++ library to a C application in OSX? - c++

I've looked through the other similar questions about this topic, and I think there's something OSX-specific I'm missing.
I'm trying to statically link Basho's fork of LevelDB to my C application (since packaged versions of LevelDB will use Google's mainline). Even using the c++ linker and adding -lc++ to the command line, I still get flooded with errors about missing c++ STL symbols such as:
"std::string::_Rep::_M_destroy(std::allocator const&)",
referenced from:
_leveldb_open in libleveldb.a(c.o)
The strange thing is, I know I have the C++ bits enabled right because I'm also linking to libsnappy, and before I added the link directive there was unresolved libsnappy symbols (obviously) that are now cleared up.
As far as I know, I have the latest version of xcode & the rest of the compiler chain. libleveldb is also compiled using the same toolchain as my regular application. Here's the command line I'm trying:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-g -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/get_rid_status.dir/get_rid_status.c.o
-o get_rid_status
/usr/local/lib/libdb.a /usr/lib/libssl.dylib /usr/lib/libcrypto.dylib
/usr/lib/libaprutil-1.dylib /usr/lib/libapr-1.dylib -lpthread -ldl -lm
-lz leveldb/libleveldb.a /usr/local/lib/libsnappy.dylib -lc++
I'm linking with the c++ linker and adding the c++ standard library with -lc++ to no avail.
UPDATE
Found the correct answer, which can be found below. Kudos to the users who told me the right etiquette when I originally answered my own question here.

Turns out, leveldb adds some extra linker flags I didn't notice at first. The culprit is -mmacosx-version-min=10.8. Adding that flag to the link step of my C application got everything to line up.

Related

Linking against a c/c++ library

I have some basic questions regarding linking against a C/C++ library. I am trying to understand the difference in using the two different usages -L/usr/local/lib -lm usage and /usr/local/lib/libm.a usage. E.g., when I compile and link an example from the [SUNDIALS] library, both of the following work
gcc -Wall cvRoberts_dns.c -o cvRoberts_dns.exe -I/usr/local/include -L/usr/local/lib/ -lsundials_cvode -lsundials_nvecserial -lm
OR
gcc -Wall cvRoberts_dns.c -o cvRoberts_dns.exe /usr/local/lib/libsundials_cvode.a /usr/local/lib/libsundials_nvecserial.a
However, to compile and link an example from the library [libsbml], the following works
g++ -Wall readSBML.cpp -o readSBML.exe -I/usr/local/include -L/usr/local/lib -lsbml
but the this does not
g++ -Wall readSBML.cpp -o readSBML.exe /usr/local/lib/libsbml.a
If required, I can post the complete error message I get, but the last line of the message is as follows
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
My questions are as follows:
In the second style of linking (of the first example), there is no information regarding where to find the include files (header files), how does the compiler know the information supplied in -I/usr/local/include which is provided in the first style of the first example?
In the second style of first example there is no /usr/local/lib/libm.a (it actually gives an error message that libm.a cannot be found if I try to include it), then why -lm is required in the first style?
How do I compile the second example in the second style (i.e., using /usr/local/lib/libsbml.a)? I do see that there are files - libsbml.a and libsbml-static.a in the /usr/local/lib folder, but none of them work.
If it helps, I am on an OS X machine.
I would be very thankful if any one could help in this regard.
Just an update - I tried
g++ -Wall readSBML.cpp -o readSBML.exe /usr/local/lib/libsbml.5.dylib
and that compiled and linked just fine.
Thanks
SN
In general
The -L option is meant to find where the libraries themselves are. Each library is a collection of one or more object code (machine language) files. There is no need to find the include files.
The -I option has nothing to with linker, it helps the compiler resolve the header files used in your driver programme( eg Roberts_dns.c). This happens during the pre-processing stage.
In the second style of linking (of the first example), there is no
information regarding where to find the include files (header files),..
If the compilation worked as you expected,it may be because /usr/local/include is in the default include path for gcc. To check the default include path for gcc do gcc -xc -E -v -.
In the second style of first example there is no
/usr/local/lib/libm.a(it actually gives an error message that libm.a
cannot be found if I try to include it), then why -lm is required in
the first style?
In Linux, some libraries like libc.a are directly linked to your execultable by default while libm.a is not. In Mac (your environment), though, libm is directly link to the executable by default. So you don't have to explicitly link it. It is less likely that libm.a is located in /usr/local/lib/. So you got an error. But why link it in the first place?

Need some help figuring out compile-time error: 'Undefined symbols for architecture x86_64: "boost::system::system_category()"' [duplicate]

I'm trying to compile a program on Ubuntu 11.10 that uses the Boost libraries. I have the 1.46-dev Boost libraries from the Ubuntu Repository installed, but I get an error when compiling the program.
undefined reference to boost::system::system_category()
What is it that I do wrong?
The boost library you are using depends on the boost_system library. (Not all of them do.)
Assuming you use gcc, try adding -lboost_system to your compiler command line in order to link against that library.
Linking with a library that defines the missing symbol (-lboost_system) is the obvious solution, but in the particular case of Boost.System, a misfeature in the original design makes it use boost::system::generic_category() and boost::system::system_category() needlessly. Compiling with the flag -DBOOST_SYSTEM_NO_DEPRECATED disables that code and lets a number of programs compile without requiring -lboost_system (that link is of course still needed if you explicitly use some of the library's features).
Starting from Boost 1.66 and this commit, this behavior is now the default, so hopefully fewer and fewer users should need this answer.
As noticed by #AndrewMarshall, an alternative is to define BOOST_ERROR_CODE_HEADER_ONLY which enables a header-only version of the code. This was discouraged by Boost as it can break some functionality. However, since 1.69, header-only seems to have become the default, supposedly making this question obsolete.
Another workaround for those who don't need the entire shebang: use the switch
-DBOOST_ERROR_CODE_HEADER_ONLY.
If you use CMake, it's add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY).
The above error is a linker error... the linker a program that takes one or more objects generated by a compiler and combines them into a single executable program.
You must add -lboost_system to you linker flags which indicates to the linker that it must look for symbols like boost::system::system_category() in the library libboost_system.so.
If you have main.cpp, either:
g++ main.cpp -o main -lboost_system
OR
g++ -c -o main.o main.cpp
g++ main.o -lboost_system
When using CMAKE and find_package, make sure it is :
find_package(Boost COMPONENTS system ...)
and not
find_package(boost COMPONENTS system ...)
Some people may have lost hours for that ...
I got the same Problem:
g++ -mconsole -Wl,--export-all-symbols -LC:/Programme/CPP-Entwicklung/MinGW-4.5.2/lib -LD:/bfs_ENTW_deb/lib -static-libgcc -static-libstdc++ -LC:/Programme/CPP-Entwicklung/boost_1_47_0/stage/lib \
D:/bfs_ENTW_deb/obj/test/main_filesystem.obj \
-o D:/bfs_ENTW_deb/bin/filesystem.exe -lboost_system-mgw45-mt-1_47 -lboost_filesystem-mgw45-mt-1_47
D:/bfs_ENTW_deb/obj/test/main_filesystem.obj:main_filesystem.cpp:(.text+0x54):
undefined reference to `boost::system::generic_category()
Solution was to use the debug-version of the system-lib:
g++ -mconsole -Wl,--export-all-symbols -LC:/Programme/CPP-Entwicklung/MinGW-4.5.2/lib -LD:/bfs_ENTW_deb/lib -static-libgcc -static-libstdc++ -LC:/Programme/CPP-Entwicklung/boost_1_47_0/stage/lib \
D:/bfs_ENTW_deb/obj/test/main_filesystem.obj \
-o D:/bfs_ENTW_deb/bin/filesystem.exe -lboost_system-mgw45-mt-d-1_47 -lboost_filesystem-mgw45-mt-1_47
But why?
When I had this, problem, the cause was the ordering of the libraries. To fix it, I put libboost_system last:
g++ mingw/timer1.o -o mingw/timer1.exe -L/usr/local/boost_1_61_0/stage/lib \
-lboost_timer-mgw53-mt-1_61 \
-lboost_chrono-mgw53-mt-1_61 \
-lboost_system-mgw53-mt-1_61
This was on mingw with gcc 5.3 and boost 1.61.0 with a simple timer example.
in my case, adding -lboost_system was not enough, it still could not find it in my custom build environment. I had to use the advice at Get rid of "gcc - /usr/bin/ld: warning lib not found" and change my ./configure command to:
./configure CXXFLAGS="-I$HOME/include" LDFLAGS="-L$HOME/lib -Wl,-rpath-link,$HOME/lib" --with-boost-libdir=$HOME/lib --prefix=$HOME
for more details see Boost 1.51 : "error: could not link against boost_thread !"
...and in case you wanted to link your main statically, in your Jamfile add the following to requirements:
<link>static
<library>/boost/system//boost_system
and perhaps also:
<linkflags>-static-libgcc
<linkflags>-static-libstdc++

Static linking to libcrypto++, with g++

I am trying to compile a program on my system with Debian Wheezy and g++4.7. I want it to be able to run on another system with Debian Squeeze (and no recent g++). I can't compile the program on the Squeeze, because I use certain C++11 features the old g++ does not support, as well as a new Boost version and libcrypto++9.
As far as I understand the usual way to get around this problem is to static link the libraries not supported at the other system, in my case libstdc, boost and crypto++.
My (linking) compiler call right now is
g++-4.7 .obj/btcmirco.o -Wl,-Bstatic -lboost_program_options -lboost_system -lcrypto++ -Wl,-Bdynamic -lcurl -static-libgcc -std=c++11 -o MyProgram
However I seem to have missed something, because it throws a lot of undefined reference errors. It works fine if I dynamic link to crypto++ (and only static link libstdc and boost).
Can anyone tell me whats wrong, or if there is a fundamental error in my approach?
The linker errors I get are (shorted):
`.text._ZN8CryptoPP22BufferedTransformationD2Ev' referenced in section `.text._ZN8CryptoPP22BufferedTransformationD1Ev[_ZN8CryptoPP22BufferedTransformationD1Ev]' of /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/libcrypto++.a(cryptlib.o): defined in discarded section `.text._ZN8CryptoPP22BufferedTransformationD2Ev[_ZN8CryptoPP22BufferedTransformationD5Ev]' of /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/libcrypto++.a(cryptlib.o)
`.text._ZN8CryptoPP25MessageAuthenticationCodeD2Ev' referenced in section `.text._ZN8CryptoPP25MessageAuthenticationCodeD1Ev[_ZN8CryptoPP25MessageAuthenticationCodeD1Ev]' of /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/libcrypto++.a(cryptlib.o): defined in discarded section `.text._ZN8CryptoPP25MessageAuthenticationCodeD2Ev[_ZN8CryptoPP25MessageAuthenticationCodeD5Ev]' of /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/libcrypto++.a(cryptlib.o)
I experienced the same problem and this has to do with the fact that you are trying to mix code generated by g++-4.7 (your program) with code generated by a previous version of g++ (cryptopp library).
The reason behind this is that when you execute compile the library executing make command, it uses the default version of g++ set up for your system, usually the one that comes with the OS.
In order to solve the issue what you should do is compile cryptopp library with g++-4.7.
For that, compile the library by executing make CXX=g++-4.7. The resulting static library shouldn't give you the error when being linked with your code.

Boost Thread Destructor Undefined Symbol

I'm using OSX Mountain Lion. I just downloaded, unpacked, and built boost 1.52.0 using the instructions supplied from the boost website: http://www.boost.org/doc/libs/1_52_0/more/getting_started/unix-variants.html. I left the default installation prefix at /usr/local, meaning that the libraries are installed in /usr/local/lib and the header files are in /usr/local/include. I have verified that the libraries and headers are present there and recently modified.
I'm attempting to compile the boost asynchronous I/O example found here: http://www.boost.org/doc/libs/1_52_0/doc/html/boost_asio/tutorial/tuttimer5/src.html (source).
Here is my compilation command:
g++ -Wall -c -g -I/usr/local/include src/test1.cpp -o src/test1.o
where src/test1.cpp is the example source file. Here is my linking command (and error):
g++ -Wall -L/usr/local/lib -lboost_thread -lboost_system src/test1.o -o bin/test1
Undefined symbols for architecture x86_64:
"boost::thread::~thread()", referenced from:
_main in test1.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
I have tried using both Apple's clang++ 4.0 and g++ 4.6.0. I get the same undefined symbol error from both programs.
Other people seem to have had trouble compiling this code sample as well. I am aware of this question: C++ / Boost: Undefined Symbols in example? and this one: Linker error when compiling boost.asio example. However, each of these problems seems to have been fixed by adding the appropriate switches (-lboost_thread and -lboost_system) to the command line. I already have those. I have also tried adding -lpthread without luck.
Thank you for taking time to look at my question! Any help is appreciated. :)
Just ran into this same problem, and I found that reverting to Boost 1.49 fixes the problem. Download links for Boost 1.49 are here:
http://www.boost.org/users/history/version_1_49_0.html
Before installing 1.49, I removed 1.52 by deleting /usr/local/include/boost and /usr/local/lib/*boost*. Not sure what changed between 1.49 and 1.52 to cause this problem, or whether Boost 1.50 or 1.51 will work.
Put the libraries you link with last on the command line.
The GNU linker uses kind of reverse lookup of dependencies, so if file A depends on library B, B should come after A on the command line.

Boost::Thread linking error on OSX?

So I'm going nuts trying to figure this one out. Here's my basic setup:
I'm compiling a shared library with a bunch of core functionality that uses a lot of boost stuff. We'll call this library libpf_core.so. It's linked with the boost static libraries, specifically the python, system, filesystem, thread, and program_options libraries. This all goes swimmingly.
Now, I have a little test program called test_socketio which is compiled into a shared library (it's loaded as a plugin at runtime). It uses some boost stuff like boost::bind and boost::thread, and it's linked again libpf_core.so (which has the boost libraries included remember).
When I go to compile test_socketio though, out of all my plugins it gives me a linking error:
[ Building test_socketio ]
g++ -c -pg -g -O0 -I/usr/local/include -I../include test_socketio.cc -o test_socketio.o
g++ -shared test_socketio.o -lpy_core -o test_socketio.so
Undefined symbols:
"boost::lock_error::lock_error()", referenced from:
boost::unique_lock<boost::mutex>::lock() in test_socketio.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
And I'm going crazy trying to figure out why this is. I've tried explicitly linking boost::thread into the plugin to no avail, tried ensuring that I'm using the boost headers associated with the libraries linked into libpf_core.so in case there was a conflict there.
Is there something OSX specific regarding boost that I'm missing? In my searching on google I've seen a number of other people get this error but no one seems to have come up with a satisfactory solution.
Edit: Figured it out, OSX comes with boost 1.40 in /usr/local/include. Needed to put the headers for my version of boost somewhere and make sure that my plugins sees those first.
You need to link to libboost_thread. Add the -lboost_thread switch.
When you link libpf_core.so against the static boost libraries, it's only going to get copies of the functions it actually uses. The linker doesn't bother to pull in functions that aren't referenced by the code in your library.
You need to link your test program against the boost libraries as well. You can't reliably "chain" the linkages.