gcc ignores the explicitly specified linked libraries to be linked - c++

I use CMake/vcpkg to manage my C++ programs dependencies, and ran into a linking issue on Linux.
My program depends on library X (arrow more specifically), and library X depends on another library Y internally (RE2 in this case). When I linked my program to library X, the linking worked on macOS X (Apple clang 11) while didn't work on debian (g++ 9.3), reporting symbols in library Y cannot be found, and symbol missing were still reported by linker under Linux even if I explicitly linked library Y to my program directly.
Currently the only workaround I found is writing a useless function in my program using library Y, so that the linker will link the library Y. It seems to me the linker tries to be smart and avoid linking the library Y because it is not directly used by my program but reporting error when linking to library X due to it cannot find symbols in library Y used by X.
This doesn't seem to be a problem for this particular library since I had another library with the same case on Linux as well. One of the possible cause is I tried to make my program a shared library, but I don't know if it is relevant or not. Could some one shed some light on how this happens and how I may fix it?
Here is the error message reported:
/usr/bin/ld: /vcpkg/installed/x64-linux/debug/lib/libarrow.a(gdv_function_stubs.cc.o): in function `bool re2::RE2::FullMatch<>(re2::StringPiece const&, re2::RE2 const&)':
/vcpkg/installed/x64-linux/include/re2/re2.h:368: undefined reference to `re2::RE2::FullMatchN(re2::StringPiece const&, re2::RE2 const&, re2::RE2::Arg const* const*, int)'

Related

Linking with BLAS OS X

I am currently trying to compile a program using a library that I'm not very familiar with. When I run the compiler, I get the following output/error:
Undefined symbols for architecture x86_64:
"_cblas_ddot", referenced from:
shark::LDA::train(shark::LinearClassifier<shark::blas::vector<double> >&, shark::LabeledData<shark::blas::vector<double>, unsigned int> const&) in libshark.a(LDA.cpp.o)
shark::LDA::train(shark::LinearClassifier<shark::blas::vector<double> >&, shark::WeightedLabeledData<shark::blas::vector<double>, unsigned int> const&) in libshark.a(LDA.cpp.o)
My current idea is that this is from missing BLAS library, which I just downloaded and compiled (from fortran code?).
The command-line arg for compiling looks like thsi
g++ -o example -I/to/boost/include -I/to/shark/include -L/to/boost/lib -L/to/shark/lib -L/to/BLAS -lshark -lblas -l(boost_flags)
In /to/BLAS have a libblas.a, and I ran nm libblas.a which gives a line
libblas.a(ddot.o):
00000000000001c0 s EH_frame1
0000000000000000 T _ddot_
Without being too secure abut this, I assume that this means that the library does have the symbol, but without the _cblas_ prefix.
What can I do from this point? Can I change the symbols name? Or do I need to link this library with something else?
I use OS X Mavericks
Thanks in advance : )
OS X ships with BLAS (including cblas) already installed (it's part of the Accelerate.framework). There's no need to download and build your own. Just link with -lcblas.
Solution was as suggested by Logicrat, that I needed other files, I downloaded te source code from here and build it with cmake/make very seamless. Linking with the libraries that came from this resolved the issue.

Using ArrayFire libraries

I downloaded the free version of ArrayFire library. I tried to test matrix multiplication with it. However I got a bunch of undefined references such as
matrixdata.cpp:(.text+0x19e5): undefined reference to af::array::array<unsigned char>(int, int, unsigned char const*, af::af_source_t, int)
matrixdata.cpp:(.text+0x1a22): undefined reference to af::array::operator=(af::array const&)'
matrixdata.cpp:(.text+0x1a31): undefined reference to af::array::~array()
Naturally I noticed that I haven't linked arrayfire libraries in my makefile.
However, all my attempts to link the libraries have failed. Can someone please tell what command should I add to link the proper libraries
The files in the lib folder are:
libafcpu.so
libafcuda.so
libafopencl.so
libclBLAS.so
libclBLAS.so.2
libclBLAS.so.2.3.0
libclFFT.so
libclFFT.so.2
libclFFT.so.2.3.0
libStatTimer.so
libStatTimer.so.2
libStatTimer.so.2.3.0
After installation, add the path to the shared libraries of ArrayFire to your LD_LIBRARY_PATH variable. Once you do that, it is merely indicating the correct backend library you need with -l option. Say for cpu, it would be -lafcpu.
What command are you trying ?

Why will I have C++ unknown reference link error on the application program but not the library in linux

Now I am building a C++ dynamic library libabc.so and an application test based on this library in linux. libabc.so will invoke boost dynamic library libboost.so. I can compile libabc.so very well, and no errors can be found. If I use ldd command on libabc.so, I can easily observe that this library has a dependency on libboost.so. However, when I compile the application program test, I have the following link error:
abc.so: undefined reference to `boost::filesystem::detail::copy_file(boost::filesystem::path const&, boost::filesystem::path const&, boost::filesystem::copy_option, boost::system::error_code*)'
collect2: ld returned 1 exit status
I do not know where the problem comes from. When I compile test program, I am sure that I link it with both libabc.so and libboost.so. I also changed the sequence of libabc.so and libboost.so when linking just to make sure that the right library sequence is given. Any ideas? Thanks.
The function in question is defined to take different arguments, depending on whether the programis compiled as C++03 or C++11.
void boost::filesystem::detail::copy_file(boost::filesystem::path const&, boost::filesystem::path const&, boost::filesystem::copy_option::enum_type, boost::system::error_code*) // pre-C++11
void boost::filesystem::detail::copy_file(boost::filesystem::path const&, boost::filesystem::path const&, boost::filesystem::copy_option, boost::system::error_code*) // C++11
In my opinion this is a Boost bug.
Consequently, if this function is used in a program, then both Boost and the program must be compiled with C++11 support, or both without. Otherwise the program will fail at the linking stage.
Shared libraries in Linux are normally allowed to have unresolved references, this doesn't cause their linking to fail.

Linking with gmock libs generated using GCC 3.4.6 (libstdc++.so.6.0.13) gives "undefined reference to... #GLIBCXX_3.4.9" errors

Linking with gmock(1.4+svn281) libs generated on a Linux machine "A", having GCC 3.4.6 using libstdc++.so.6.0.13 gives me the following linking error:
libgmock.so: undefined reference to `std::basic_ostream >& std::__ostream_insert >(std::basic_ostream >&, char const*, long)#GLIBCXX_3.4.9'
...
I tried also with the latest gmock release version and also got the undefined reference to... #GLIBCXX_3.4.9 errors (this time with other symbols).
Building gmock using the same build procedure, however on another machine "B" (retired machine now, but previously used to generate the older binaries) I was able to link successfully. The machine uses GCC 3.4.6, with a different libstdc++ version: libstdc++.so.6.0.3.
Grepping on libstdc++.so.6.0.13 for GLIBCXX_3.4.9 shows that it contains such symbol patterns:
_ZNSt13basic_ostreamIwSt1##GLIBCXX_3.4.9 (referencing GLIBCXX_3.4.9, hence the error). I verified that this is not the case for libstdc++.so.6.0.3
To understand the linking error and what are my options, I read about libstdc++ and glibcxx to get some perspective, but couldn't conclude the relation between the libs: Does libstdc++ need glibcxx or is it the other way around (the error message makes it seem that the problem is: at glibcxx there is an undefined reference to a symbol in libstdc++)?
Does libstdc++ implicitly link with glibcxx (knowing that libstdc++ can reference multiple glibcxx versions at a time)?
I don't want to go back to the old machine to build gmock whenever I want to update the libs, am I constrained to building gmock with specific libstdc++ versions that work?
Appreciate any help on the issue
EDIT:
I built gmock libs on machine "A" and specified the version of libstdc++: libstdc++.so.6.0.3 and got the same errors as before, but this time without the #GLIBCXX_3.4.9 appended at the end of the symbol:
libgmock.so: undefined reference to `std::basic_ostream >& std::__ostream_insert >(std::basic_ostream >&, char const*, long)'
...
I also verified that libstdc++.so.6.0.3 was actually taken, by launching the command: "readelf -a libgmock.so" and verifying that GLIBCXX_3.4.9 was not referenced.
To understand the linking error and what are my options, I read about libstdc++ and glibcxx to get some perspective, but couldn't conclude the relation between the libs: Does libstdc++ need glibcxx
There is no such thing as glibcxx library. The libstdc++.so uses GNU symbol versioning, and uses GLIBCXX symbol prefix. The whole GLIBCXX is implementation detail of libstdc++ itself.
Your actual problem, and possible solutions, is explained here.
Effectively, you can not expect a binary linked on a newer Linux system to work on an older one.

How can I resolve single symbol link error when dynamically linking XCode project to lib4cxx library?

I'm writing in C++ under XCode 4.6 on Mountain Lion. I'm trying to add and use the Apache log4cxx library. I installed the library this morning via Brew. I'm linking against liblog4cxx.dylib. I'm getting a link error that just one symbol can't be found:
Undefined symbols for architecture x86_64:
"log4cxx::Logger::forcedLog(log4cxx::helpers::ObjectPtrT
const&, std::__1::basic_string,
std::__1::allocator > const&, log4cxx::spi::LocationInfo const&)
const", referenced from:
I know it's finding the library file because if I remove it, I get lots more undefined symbol errors relating to log4cxx.
relevant code is basically:
#include <log4cxx/logger.h>
static LoggerPtr logger(log4cxx::Logger::getLogger("foo.bar.Baz"));
void foo(int p1, int p2)
{
LOG4CXX_WARN(logger, "blah blah blah");
}
Creating the logger object inside the function, either as static or not, doesn't change the behavior. Also, linking with the static library, with or without defining LOG4CXX_STATIC in my project, does not change the behavior.
Looking at the macro I'm calling, I see that this symbol is the actual method that performs the log operation. If take out the logging call but leave in the code that defines the logger object, the code links fine as you might expect.
What do I need to do to have this last symbol resolve?
TIA!
I traced my issue down to compiling the library in a non C++11 compiler, but then my target project was a C++11 compiler.
I was able to compile log4cxx in a C+11 compiler by viewing the changes to log4cxx in the development git repo, which mainly consisted of inserting static_casts, as in this update:
http://apache-logging.6191.n7.nabble.com/C-11-does-not-allow-char-literals-with-highest-bit-set-unless-cast-td34908.html
I suppose the few incompatible routines came up undefined, which is why we were getting confused with only a few seemingly random undefines. (Or I was anyway)