C++ Dynamically Linked Libraries loaded at runtime - Poco / qmake - c++

I am having trouble with Boost and my Mac OS X.
I am using Qt Creator as a development platform for C++ projects, primarily because of the IDE and qmake.
Right now I am working on a C++ app that is supposed to be cross-platform but I do not want to use the Qt framework itself. Instead I am using the STD libraries (C++11), Poco and Boost.
One of the things I am trying to achieve is a plugin system that loads dynamically linked libraries at runtime.
I saw a few projects like Boost-extension which is no longer supported and several others.
Right now I am using Poco's Shared Libraries and their Class Loader. I am following closely the tutorial at the end of the presentation. Unfortunately I cannot get it working and I am receiving the following error upon compilation, where the ServiceBase class is my plugin interface.
Undefined symbols for architecture x86_64:
"Poco::SharedLibrary::getSymbol(std::string const&)", referenced from:
Poco::ClassLoader<ServiceBase>::loadLibrary(std::string const&, std::string const&) in main.o
"Poco::SharedLibrary::hasSymbol(std::string const&)", referenced from:
Poco::ClassLoader<ServiceBase>::loadLibrary(std::string const&, std::string const&) in main.o
"Poco::SharedLibrary::SharedLibrary(std::string const&)", referenced from:
Poco::ClassLoader<ServiceBase>::loadLibrary(std::string const&, std::string const&) in main.o
"Poco::SystemException::SystemException(std::string const&, int)", referenced from:
Poco::MutexImpl::unlockImpl() in main.o
Poco::MutexImpl::lockImpl() in main.o
"Poco::LibraryLoadException::LibraryLoadException(std::string const&, std::string const&, int)", referenced from:
Poco::ClassLoader<ServiceBase>::loadLibrary(std::string const&, std::string const&) in main.o
ld: symbol(s) not found for architecture x86_64
I have the Poco libraries linked and pretty much everything seems to be implemented.
Any advice on how to fix that?
P.S. I am also looking for alternatives on implementing the plugin system, probably more-powerful and certainly cross-platform.

Disclaimer. I have no experience with this Poco library.
Without further details on your environment or your tools... I can only provide some very general advice:
How I'd chase this is:
Locate in what library or object file are defined the symbols reported as undefined symbols. On unix-like environments this can be achieved with the nm tool
Verify that the libraries or objects are compiled on the right architecture (I see you're using x86_64) file tool might help you there
Verify that you're referring to the library in the linker command line (look for a -l for dynamic or static libraries) or that you're including the object file or the static library in the list of things to link.
Verify that you're referring to the right library (either through -L flags or the LD_LIBRARY_PATH env variable (or LD_LIBRARY_PATH_64 in some systems e.g. Solaris for 64bits build)
I know you said you have linked the Poco libraries, but the error is clearly that a symbol is missing. Either the library is missing or you need to fiddle with the order of the -l flags to satisfy the dependencies. The nm might help you there in determining what objects or libraries refer to the symbol (must come first) and what objects or libraries define the symbol (must come later).
Sorry not being of more help.
P.S. In addition you might want to look at Linking error with Poco Net which might be related.
One more reference to a question that details different causes for linker errors: What is an undefined reference/unresolved external symbol error and how do I fix it?

Related

LLVM symbol lookup difficulties

I'm following along with the tutorial LLVM provides to get familiar with its IR that can be found here.
Unfortunately, it seems that when I add in the JIT support, the linker has some difficulty following along. Namely, I get a number of undefined symbols,
Undefined symbols for architecture x86_64:
"_LLVMInitializeX86AsmParser", referenced from:
llvm::InitializeNativeTargetAsmParser() in lexer.cc.o
"_LLVMInitializeX86AsmPrinter", referenced from:
llvm::InitializeNativeTargetAsmPrinter() in lexer.cc.o
etc.
I'm building using CMAKE using the LLVM config and can find the headers in my include directories, so I'm unsure why the symbols can't be fine. My code is here, but isn't too specific to the problem. I'm on MacOS.
How can I make the linker find the header files or why is it not working?
If you are using CMake, you need to add some LLVM components. Here is an excerpt from my CMakeLists.txt for the same chapter.
llvm_map_components_to_libnames(llvm_libs analysis core executionengine instcombine object orcjit runtimedyld scalaropts support native)
Relevant links:
The official CMakeLists.txt for the chapter
A StackOverflow question about a similar problem
The example CMakeLists.txt from the documentation

How to fix ncurses? [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 4 years ago.
I'm a mac user, and I'm using the XCode developer tools and using CLion as a compiler. When I try to use ncurses and its functions, specifically getch(), I get the following error.
Undefined symbols for architecture x86_64:
"_stdscr", referenced from:
_main in main.cpp.o
"_wgetch", referenced from:
_main in main.cpp.o
ld: symbol(s) not found for architecture x86_64
I've tried to go online and reinstall ncurses, but it hasn't fixed anything. I would greatly appreciate any help.
First of all, CLion isn't a compiler. It's an IDEA (integrated development
environment). As I remember using it last time it uses CMake as a build tool. And CMake uses GCC, Clang, MSVC, whatever under the hood.
As you don't post any code sample I will try to guess the problem. Usually
when using ncurses you need to link with it as: -lncurses. For more info you
should look man ncurses on your platform. Also check that you don't forget to include the required header. E.g. on my system it's #include <curses.h>.
How to link with ncurses via CMake

Yet another "ld: symbol(s) not found for architecture x86_64" issue with boost, this time with mgiza

I apologize for asking such a common question; I can't find any solution out there that works or is clear enough for me to implement. I am simply trying to install mgiza. Here is the INSTALL file:
cmake .
make
make install
If you want to install to a custom location, add the following flag when you run cmake:
-DCMAKE_INSTALL_PREFIX=/path/to/custom/location
NOTE: Boost Version 1.48 has problem with the code, you can use either 1.46 or 1.50+. Unfortunately 1.48 is shipped with Ubuntu 12.04 LTS, you can either download and compile libboost 1.50+ from their website, or just do this:
sudo apt-get install libboost1.46-all-dev
Looks easy, right? Typing in cmake . works without any apparent problems. Unfortunately, make runs into this dreaded error ("undefined symbols ...") with boost.
1 warning generated.
Linking CXX executable ../bin/d4norm
Undefined symbols for architecture x86_64:
"std::string::_Rep::_M_destroy(std::allocator<char> const&)", referenced from:
boost::system::(anonymous namespace)::generic_error_category::message(int) const in libboost_system-mt.a(error_code.o)
"std::string::_Rep::_S_empty_rep_storage", referenced from:
boost::system::(anonymous namespace)::generic_error_category::message(int) const in libboost_system-mt.a(error_code.o)
"std::string::assign(char const*, unsigned long)", referenced from:
boost::system::(anonymous namespace)::generic_error_category::message(int) const in libboost_system-mt.a(error_code.o)
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)", referenced from:
boost::system::(anonymous namespace)::generic_error_category::message(int) const in libboost_system-mt.a(error_code.o)
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&)", referenced from:
boost::system::(anonymous namespace)::generic_error_category::message(int) const in libboost_system-mt.a(error_code.o)
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()", referenced from:
boost::system::(anonymous namespace)::generic_error_category::message(int) const in libboost_system-mt.a(error_code.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Based on other questions, it's a problem with Mavericks because it uses clang to compile c++ code, implying that the library is libc++, not libstdc++. For completeness, and so that others can reproduce my errors, I am using OS X 10.9.5, Xcode 6.1, and my boost version is 1.56 (boost was installed via homebrew).
Now, there has to be some fix out there, right? Let's go through some of them:
Applying the -m32 flag: not applicable because the Makefile
doesn't have any "g++" in it, and it also explicitly tells me NOT to
edit it, because it's a "Cmake" generated file.
Not defining something in a header file: not applicable because the code should be ready to compile.
Adding -stdlib=libstdc++ to linker: I am not sure how to add this to a make command? I tried just doing make -stdlib=libstdc++ and while that seemed to avoid the errors above, it introduced some additional errors: make: *** [all] Error 2 (not sure what that means).
Linking to proper boost libraries: There's a comment there that says "You just need to link to the proper boost libraries ... plenty of Q/As on how to do that". Unfortunately, I don't think any of the questions that commenter linked to address my problem.
Linking Qt with boost: I don't think this is applicable because I'm not using Qt, and I don't know where I'd put in a LIBS += [...] boost line.
Linking a missing file: That issue seems to be more about linking when running g++ but I'm using a Makefile that doesn't have g++ anywhere in it.
Using g++ vs gcc: I don't know how I can change which of these I use, because I'm using cmake and make...
Changing a link command: Again, I don't know how I can change the compilation from cmake/make to gcc. (Note: from this point on, I will ignore most questions that are answered by adding something to gcc or g++.)
Changing the standard c++ library: the solution involves going into Xcode and changing the libraries there. I don't think this is the correct approach and in any case I'd probably screw up something if I changed a setting in Xcode (I also have no experience with Xcode's GUI).
Linking libraries in Xcode: I think this is a similar case as #9 on this list. The answer here also recommends using homebrew instead of macports for installing boost, but I already said earlier that I used homebrew for installing boost.
Compile with clang: A similar issue, but how do I get cmake or make to compile with clang?
From a (popular) bitcoin issue: Now this looks interesting! A ton of people ran into my error. Unfortunately, there seems to be no consensus or easy solution. There are also a few solutions that I don't know to implement. For instance, one solution by "imbolo" there is to compile boost using a cxxflag flag, but what does that mean?
So I'm at a little bit of a loss on how to correctly install mgiza ... I mean, the whole point of mgiza giving me cmake and make is so that I don't have to worry about the messy details of compiling things, right? This isn't just an mgiza issue, though, since I've run into this problem when trying to do make elsewhere. I understand the high-level ideas of (C)Makefiles, but not the low-level details.
To address some of the concerns by the commenters: the best way to deal with this problem is to try and clear your system as much as possible and start the process from scratch.
Also, since this was posted, OS X 10.10 Yosemite was released, which may have fixed this problem (IIRC this problem is mostly due to 10.9 and the clang/gcc complier changes).

Trouble linking C++ with Xcode 5

So I have this legacy project, which I am trying to bring to iOS 7 and Xcode 5. And by legacy, I mean real legacy. Like 2004 legacy.
Anyhow, I am trying to build this thing, and it spits out a few libraries, including some common third party libs. When linking, I get errors like these:
Undefined symbols for architecture ${arch}:
"google::protobuf::internal::WireFormatLite::WriteBytes(int, std::string const&, google::protobuf::io::CodedOutputStream*)"
Upon examination with nm, the old (arm only) binary library still included in the project contains this:
U __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPNS0_2io17CodedOutputStreamE
00000a8c T __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPNS0_2io17CodedOutputStreamE
00002b28 S __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPNS0_2io17CodedOutputStreamE.eh</code>
The new library (universal), created when I run the project through Xcode 5 (and thus, clang/llvm) contains this:
U __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKSsPNS0_2io17CodedOutputStreamE
00000514 T __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKSsPNS0_2io17CodedOutputStreamE
00000b2c S __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKSsPNS0_2io17CodedOutputStreamE.eh
To me, it looks like the parameters are missing in the mangled name.
Is this normal and I need to look somewhere else?
Or if this is the problem: Any idea how to solve it?
EDIT: I mixed up OLD and NEW. I left the original post unchanged
The old, arm only libary seems to indicate:
google::protobuf::internal::WireFormatLite::WriteBytes(int, std::string const&, google::protobuf::io::CodedOutputStream*)
Which has all the hallmarks of being compiled with libstdc++.
The new universal library indicates:
google::protobuf::internal::WireFormatLite::WriteBytes(int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, google::protobuf::io::CodedOutputStream*)
This has all the hallmarks of being compiled with libc++
Your link error indicates that there is a problem finding:
google::protobuf::internal::WireFormatLite::WriteBytes(int, std::string const&, google::protobuf::io::CodedOutputStream*)
This would be the case if the code linking to the library was compiled using libstdc++ and, because your new universal library is compiled using libc++ the code will not link.
You have to compile everything with the same libc++/libstdc++ support, you cannot mix and match as they will refuse to link. Make sure that every element in your project is compiled using the same C++ Standard Library and the link error should be resolved.
In general, demangling the symbols (using c++filt) allows you to see the proper signatures, and in the case of this code, once you start seeing std::__1:: in the symbols, it indicates that the library was compiled using libc++, and when you see the link failing with unadorned std:: symbols (i.e. without the inner __1::), then it indicates that the item performing the linking is using libstdc++.
Are you perhaps mixing and matching SDKs or compilers? Name mangling might differ between compilers. The only other thing I know that might affect name mangling is the 'extern "C"' keyword, but that usually turns it off completely, so I don't think that's it.
So, if the old code was still built with GCC 2.x and your new code is clang-built, they probably just mangle differently.
Does the error message really say $(arch) ? Not a particular architecture? If it gave a concrete architecture, I'd expect that you have one project that builds e.g. for arm5 and arm6, linking in a library that only has one of these architectures. Then it usually complains about the symbols in that library not being available, I think.

How I do compile a application against a static library compiled with libc++ in xcode/clang/macos?

When I try to compile a test console application to test some functionality on a static library on the same workspace, i run into problems in the linking stage of the binary, it only happen when I choose to use libc++ standard library.
The missing symbols error is the follow :
Undefined symbols for architecture x86_64:
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::empty() const", referenced from:
libtorrent::torrent::replace_trackers(std::__1::vector<libtorrent::announce_entry, std::__1::allocator<libtorrent::announce_entry> > const&) in libLibOFFTorrent-xcode.a(torrent.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
When I choose stdlibc++ in both targets everything compiles ok and it runs OK.
my questions are :
there are some restriction on using libc++ on static libraries?
its a bug in apple/clang++ linker tool?
how can I configure the project to use libc++ with my static
libraries?
why the linker tool does not find the symbols of a standard c++
libraries on a static lib?, (any other lib that depends on is compiled against libc++)
should I forget the idea on using libc++?
notes:
the static library depends on libboost_system, witch i had compiled with libc++ and libstdc++ with the same results
when i run the test with the 'bjam' tool it runs OK, maybe the jam files chooses libstdc++ to compile the files.
I know that changing the standard library fix the linking problem , I only want to know why is that.
UPDATE: when I remove the reference to string::empty in the static lib project, the project that depends on compiles with libc++ fine and runs, but it gets in a infinite loop.
UPDATE 2: removing the string::empty references causes no effect when I compile the whole thing with libstdc++ it runs fine. no loops, this makes me think that is a bug or something like that.
UPDATE 3: when it compiles this is the place where the programs loops indefinitely :
It seems that one of your dependencies (libtorrent) has been built against libstdc++.
Check the namespace : std::__1::basic_string. It has the __1 prefix, usually indicating libstdc++).
I may be wrong but I think you need to rebuild your libtorrent against libc++ if you absolutely want to use this one.
Note that it is pretty common to use the stdlibc++.
Did you by any chance compile libtorrent with a -D_LIBCPP_INLINE_VISIBILITY=""?
The reason I ask is that std::string::empty() isn't in libc++.dylib because it is marked up with "always_inline". And so it should have been inlined into libtorrent when it was used.