Static linking to libcrypto++, with g++ - c++

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.

Related

Boost regex: Undefined references when linking

Until some weeks ago, using the boost_regex library I used to compile a C++ file test.cpp using the following command.
g++-4.9 -Wall -O3 -march=native -flto -DNDEBUG -o test \
--std=c++14 test.cpp -lboost_regex -pthread
The compilation was working perfectly. But at some point, I needed to upgrade my OS (more precisely, it was Ubuntu 14.04, now it is Ubuntu 16.04).
I kept my local folders with my data, and I also installed the Boost library again in the new system, including boost_regex.
The Boost version in the new system is 1.58, unfortunately I cannot know which Boost version I was using before because it is now deleted.
I try to compile again the same file in the new system, with the same command as above, and the linker says it cannot find two functions called maybe_assign and construct_init. If I replace the -o test option with just -c (i.e. without linking) then the program is compiled without errors.
More precisely, when I try to do linking I get the following errors (they were extremely long, I hade to shorten using ... dots).
In function `boost::re_detail::perl_matcher<...>::match_match()':
undefined reference to `boost::match_results<...>::maybe_assign(boost::match_results<...> const&)'
In function `bool boost::regex_search<...>(...)':
undefined reference to `boost::re_detail::perl_matcher<...>::construct_init(...)'
In function `boost::re_detail::perl_matcher<...>::match_prefix()':
undefined reference to `boost::match_results<...>::maybe_assign(boost::match_results<...> const&)'
collect2: error: ld returned 1 exit status
I really don't know how this is possible, the libraries seem perfectly installed, nothing seems missing, and the compilation was working with a previous OS installation (then I guess older libraries).
At these point my only guess could be that Boost authors removed such functions? (maybe they are obsolete?). But I didn't find any trace of this on internet. If this is the case, how can I know the boost versions in which such functions are available?
Am I doing any mistake? Do you have any suggestions to investigate about this?
TL;DR use gcc5.
Ununtu 16.04 comes with gcc5 by default. Every C++ library in it is compiled with that compiler.
Now there was an incompatible C++ ABI change between gcc4 and gcc5. It made binaries built from C++ sources with gcc4 incompatible by default with binaries built with gcc5. This incompatibility often manifests itself as a bunch of undefined symbols that reference std::string and/or std::list.
The standard library comes built with a dual ABI to support objects built with older compilers. Other libraries like boost, hovever, don't.

Undefined reference when combining C++ and Fortran [duplicate]

I am trying to link a .o file generated using g++ and another .o file generated using gfortran.
g++ -c mycppcode.cpp
produces the file mycppcode.o and the command
gfortran -c myfortrancode.f
produces the file myfortrancode.o
When I link these two files to get an output file
g++ -O mycppcode.o myfortrancode.o
I get the following error
Undefined symbols for architecture x86_64:
"__gfortran_pow_c8_i4", referenced from:
Could some one help me with this? Should I use another compiler? Also, I would like to know what functions or subroutines call "__gfortran_pow_c8_i4", so that I can try to avoid these functions or subroutines in fortran in future.
The following assumes you are using the GNU compiler tools. Things may be slightly different if you are using other compilers.
You can use either compiler to link the two together, but you need to provide the appropriate libraries.
Typically, you can use either
gfortran fortobj.o cppobj.o -lstdc++
or
g++ fortobj.o cppobj.o -lgfortran
This assumes that you are using a setup where both compilers know about each other's libraries (like if you installed through a linux repository).
In the case of the OP the C compilers came from XCode and gfortran is from homebrew. In that case, gfortran knows about the g++ libraries (since they were used to compile the compiler), but g++ doesn't know about the gfortran libraries. This is why using gfortran to link worked as advertised above. However, to link with g++ you need to add the path to libgfortran.* when you call the linker using the -L flag, like
g++ fortobj.o cppobj.o -L/path/to/fortran/libs -lgfortran
If for some reason your gfortran compiler is unaware of your g++ libs, you would do
gfortran fortobj.o cppobj.o -L/path/to/c++/libs -lstdc++
Note that there shouldn't be any difference in the final executable. I'm no compiler expert, but my understanding is that using the compiler to link your objects together is a convenience for calling the linker (ld on UNIX-like OS's) with the appropriate libraries associated with the language you are using. Therefore, using one compiler or the other to link shouldn't matter, as long as the right libraries are included.

Statically linking matio library using g++

How do you statically link matio, a library for reading mat-files, mainly used by matlab and octave into an executable?
If the file main.cpp holds matio functionality the compiler call
g++ -o main main.cpp -Imatio/include matio/lib/libmatio.a
fails with a bunch of error messages like: undefined reference to `inflateEnd'. This can be resolved by also adding zlib to the compiler call:
g++ -o main main.cpp -Imatio/include matio/lib/libmatio.a -lz
Now the error messages differ with something like undefined reference to `__intel_sse2_strlen'. So it appears that the zlib library is necessary for the comilation.
I now have the following questions:
What do you need to do to statically link the matio library in an executable?
Why do I need to add the zlib library even though I configured and compiled matio with ./configure --without-libz?
To build matio without zlib you apparently need to invoke configure with
./configure --with-zlib=no
(Checked this from configure.ac and config/matio_zlib.m4.)
In case you want to build matio with icc, Intel's developer pages tell that __intel_sse2_strlen is defined in libirc.a on Linux and libirc.lib on Windows.
To compile matio with the gcc do
./configure --with-zlib=no CC=gcc
afterwards, the matio library is statically linkable with the call posted in the question

NVCC attempting to link unnecessary objects

I have a project that I'm working on making run with CUDA. For various reasons, it needs to compile an executable either with or without GTK support, without recompiling all of the associated files. Under C, I accomplished this by compiling a base version of the objects to *.o and a GTK version of the objects to *.gtk.o. Thus, I can link to that library and if it needs to use GTK it will pull in those functions (and their requirements); if it doesn't it won't touch those objects.
Converting to nvcc has caused some issues: it works in either always or never GTK mode; but if I compile the libraries with the additional GTK objects, it refuses to ignore them and link a GTKless executable. (It fails with errors about being unable to find the cairo functions I call.)
I'm guessing that nvcc is linking to (at least one of) its helper functions embedded in the object, which is causing the linker to resolve the entire object.
Running ar d <lib> <objects.gtk.o> to manually strip them from the library will "fix" the problem, so there isn't a real dependency there.
I'm compiling/linking with
/usr/local/cuda/bin/nvcc --compiler-options -Wall --compiler-options -pipe
-rdc=true -O0 -g -G -I inc -I inc/ext -arch compute_20 -o program
program.cu obs/external.o libs/base.a libs/extra.a libs/core.a -lm
How can I get nvcc to ignore the unneeded objects?
How can I get nvcc to ignore the unneeded objects?
Before you can achieve that, you need to understand which symbol is causing the *.gtk.o objects to be pulled in from the library when they shouldn't be.
The way to do that is to run link with -Wl,--print-map, and look for linker messages such as:
Archive member included because of file (symbol)
libfoo.a(foo.o) main.o (foo)
Above, main.o referenced foo, which is defined in libfoo.a(foo.o), which caused foo.o to be pulled in into the main binary.
Once you know which symbols cause xxxx.gtk.o to be pulled into the link, searching the web and/or NVidia documentation may reveal a way to get rid of them.

Libc++ linked programs fail with symbol lookup error

I've recently built libc++ from scratch as my prject needs some features that are not yet implemnted in libstdc++.
I try to compile the hello world program located in src/main.cpp with line
clang -Wall -stdlib=libc++ -std=c++11 -c src/main.cpp -obuild/main.o
and the build suceeds
Then I link it with
clang -lc++ build/main.o -o qasix
and the linking suceeds too.
But when I run the program with
./qasix
I get the following error:
./qasix: symbol lookup error: /usr/local/lib/libc++.so.1: undefined symbol: _ZTVN10__cxxabiv120__si_class_type_infoE
I would like to know why this is occurring and also how to fix it.
I am on Xubuntu 13.10 if that's of any help.
PS: This problem popped up yesterday. Earlier other libc++ programs would compile fine.
This started when I did a debug build of a program with the -g flag and it compiled and ran fine, but all later programs complained about this symbol lookup failure. Please help.
it appears that you need the support library "libc++abi". It provides things like low-level exception support, type_info support, etc.
For Ubuntu (as opposed to Xubuntu), it appears that you can get it here: http://www.ubuntuupdates.org/package/core/saucy/universe/base/libc++abi-dev