When/why are libstdc++ and libc++ symbols incompatible? - c++

Setup:
test.cpp
#include <set>
#include <string>
void common_config_file_iterator(const std::set<std::string>& allowed_options) {}
include.cpp
#include <set>
#include <string>
void common_config_file_iterator(const std::set<std::string>&) noexcept;
int main() {
std::set<std::string> set;
common_config_file_iterator(set);
return 0;
}
test.sh
clang++-7 test.cpp -c -O3 -fno-rtti -fno-exceptions -o test.o
g++-8 test.o include.cpp -O3 -fno-rtti -fno-exceptions -o test
Output:
Undefined symbols for architecture x86_64:
"common_config_file_iterator(std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&)", referenced from:
_main in ccWoGgrX.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
So I did nm -g test.o:
0000000000000000 T __Z27common_config_file_iteratorRKNSt3__13setINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEENS_4lessIS6_EENS4_IS6_EEEE
According to demangler.com, it means:
common_config_file_iterator(std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&)
Libc++ says:
[Features and Goals:] ABI compatibility with gcc's libstdc++ for some low-level features such as exception objects, rtti and memory allocation.
So, is the problem std::allocator<char>?
Note that I use the macOS assembler.
Curiosity caused by this issue and boost/program-options.

So, is the problem std::allocator<char>?
What? No. It's everything in your example.
The doc you quoted clearly says the goal is compatibility for "low-level features such as exception objects, rtti and memory allocation".
std::set and std::string are not "low-level features such as exception objects, rtti and memory allocation". They are very definitely not compatible between libc++ and libstdc++, which are completely different libraries with completely different implementations.
The compatible pieces are things like std::type_info and std::exception (and the derived exception types in <stdexcept>) because those are part of the basic language runtime. Anything above that, such as containers, strings, algorithms, I/O, locales etc. is not compatible.

Related

Protobuffer 2.6 Linking Error with gcc 4.8 (macports)

I have version 2.6 of Google protobuffers installed via macports and gcc 4.8 and, when I compile my code (with the -lprotobuf flag), get the following link error:
Undefined symbols for architecture x86_64:
"google::protobuf::MessageLite::ParseFromString(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)", referenced from:
_main in cclSIxVT.o
"google::protobuf::MessageFactory::InternalRegisterGeneratedFile(char const*, void (*)(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&))", referenced from:
protomessages::protobuf_AddDesc_msg_2eproto() in cc219IO6.o
"google::protobuf::io::CodedOutputStream::WriteStringWithSizeToArray(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned char*)", referenced from:
protomessages::DatabaseRequestInfo::SerializeWithCachedSizesToArray(unsigned char*) const in cc219IO6.o
"google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, google::protobuf::io::CodedOutputStream*)", referenced from:
protomessages::DatabaseRequestInfo::SerializeWithCachedSizes(google::protobuf::io::CodedOutputStream*) const in cc219IO6.o
"google::protobuf::internal::WireFormatLite::ReadBytes(google::protobuf::io::CodedInputStream*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >*)", referenced from:
protomessages::DatabaseRequestInfo::MergePartialFromCodedStream(google::protobuf::io::CodedInputStream*) in cc219IO6.o
"google::protobuf::DescriptorPool::FindFileByName(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const", referenced from:
protomessages::protobuf_AssignDesc_msg_2eproto() in cc219IO6.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
My LD_LIBRARY_PATH is correct (otherwise the -lprotobuf flag would not be recognised)
protoc --version returns 2.6.1
I am also compiling with the generated pb.o files so I don't think this is related to , what i know is a common omission.
The command in question I'm using is :
g++ -Wall -Wextra -pedantic -Wno-unused-parameter -Wno-long-long -Wno-variadic-macros -Wno-deprecated -Wno-unused-function -Wno-vla -Wno-unused-variable -std=c++11 -o testbin util/myutil.o util/config.o util/MySemaphore.o network/jobMsg.o network/JobQueue.o network/Message.o network/protocolMsgs.o network/socket/receiver.o network/socket/sender.o blocks/Block.o cluster.o blocks/tc/MVTxCoord.o blocks/tc/StoredProcedure.o blocks/tc/TxCoord.o blocks/tc/IInGroupTC.o blocks/tc/InGroupTCFactory.o blocks/tc/DummyInGroupTC.o blocks/tc/2PLInGroupTC.o blocks/ds/DataService.o blocks/ds/MVDataService.o blocks/ds/HashTableIndex.o blocks/ds/Storage.o blocks/ds/IInGroupDS.o blocks/ds/InGroupDSFactory.o blocks/ds/DummyInGroupDS.o blocks/ds/2PLInGroupDS.o blocks/ds/Lock.o blocks/gm/GroupManager.o blocks/ts/TimestampServer.o blocks/client/Client.o blocks/client/ClientLib.o blocks/client/ClientEnv.o msg.pb.o microbenchmarks/main.o -L/opt/local/lib -lprotobuf -lpthread
I've checked that the library is compiled for 64 bits.
Non-fat file: /opt/local/lib/libprotobuf.a is architecture: x86_64
Any ideas where I am going wrong?

Compiling boost::program_options on Mac OS X with g++ 4.8 (Mac Ports)

I'm trying to compile one of the boost::program_options examples, http://svn.boost.org/svn/boost/trunk/libs/program_options/example/first.cpp, using gcc 4.8 (installed via MacPorts). However, I keep getting errors:
Undefined symbols for architecture x86_64:
"boost::program_options::to_internal(std::basic_string, std::allocator > const&)", referenced from:
std::vector, std::allocator >, std::allocator, std::allocator > > > boost::program_options::to_internal, std::allocator > >(std::vector, std::allocator >, std::allocator, std::allocator > > > const&) in ccEWnIGV.o
"boost::program_options::options_description::options_description(std::basic_string, std::allocator > const&, unsigned int, unsigned int)", referenced from:
_main in ccEWnIGV.o
"boost::program_options::invalid_option_value::invalid_option_value(std::basic_string, std::allocator > const&)", referenced from:
void boost::program_options::validate(boost::any&, std::vector, std::allocator >, std::allocator, std::allocator > > > const&, double*, long) in ccEWnIGV.o
"boost::program_options::error_with_option_name::error_with_option_name(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&, int)", referenced from:
boost::program_options::validation_error::validation_error(boost::program_options::validation_error::kind_t, std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&, int) in ccEWnIGV.o
"boost::program_options::detail::cmdline::set_additional_parser(boost::function1, std::allocator >, std::basic_string, std::allocator > >, std::basic_string, std::allocator > const&>)", referenced from:
boost::program_options::basic_command_line_parser::extra_parser(boost::function1, std::allocator >, std::basic_string, std::allocator > >, std::basic_string, std::allocator > const&>) in ccEWnIGV.o
"boost::program_options::detail::cmdline::cmdline(std::vector, std::allocator >, std::allocator, std::allocator > > > const&)", referenced from:
boost::program_options::basic_command_line_parser::basic_command_line_parser(int, char const* const*) in ccEWnIGV.o
"boost::program_options::operator >&, boost::program_options::options_description const&)", referenced from:
_main in ccEWnIGV.o
"boost::program_options::abstract_variables_map::operator[](std::basic_string, std::allocator > const&) const", referenced from:
boost::program_options::variables_map::operator[](std::basic_string, std::allocator > const&) const in ccEWnIGV.o
"boost::program_options::error_with_option_name::substitute_placeholders(std::basic_string, std::allocator > const&) const", referenced from:
vtable for boost::program_options::invalid_option_value in ccEWnIGV.o
vtable for boost::program_options::validation_error in ccEWnIGV.o
etc...
The boost libraries were installed via MacPorts, placing the header files in /opt/local/include and library files in /opt/local/lib. The compile command used was:
$ g++ -I/opt/local/include first.cpp -L/opt/local/lib -lboost_program_options-mt
Compiling header-only boost functions work fine using g++ 4.8 i.e factorial, hermite etc.
What I find strange is that this example compiles if I use the llvm-g++ compiler:
$ llvm-g++ -I/opt/local/include first.cpp -L/opt/local/lib -lboost_program_options-mt
$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/opt/local/libexec/gcc/x86_64-apple-darwin12/4.8.1/lto-wrapper
Target: x86_64-apple-darwin12
Thread model: posix
gcc version 4.8.1 (MacPorts gcc48 4.8.1_3)
\
$ llvm-g++ -v
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix
\
Why doesn't this example compile with gcc 4.8? Any ideas? Is there a way to fix this?
Update: The example also compiles using clang++
I suspect you're using Boost compiled with Clang, which is incompatible with GCC.
This is because C++ implementation differs between them, and Clang's STL classes are put in a namespace different from GCC's using inline namespace for the sake differentiating Clang from more popular GCC; e.g. std::basic_string is std::__1::basic_string in Clang by inline namespace).
Try a command below, If you see "libc++" in output, yes, your Boost was built with Clang (or "libstdc++" for GCC):
$ otool -L /opt/local/lib/libboost_program_options-mt.dylib
/opt/local/lib/libboost_program_options-mt.dylib:
/opt/local/lib/libboost_program_options-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
If Boost was built with Clang, I recommend you to rebuild Boost with GCC-4.8 provided by MacPorts:
sudo port upgrade --force boost configure.compiler=macports-gcc-4.8
You can find other available compilers in https://trac.macports.org/wiki/UsingTheRightCompiler#configure-compiler .
Other useful link:
http://wiki.inkscape.org/wiki/index.php/CompilingMacOsX#Compiling_with_clang_3.3_and_libc.2B.2B_.28c.2B.2B11_enabled.29_.282013.29
As Shigerello already mentioned, the problem lies in boost compiled with clang and boost compiled with gcc being incompatible.
A simpler variation to get boost compiled with GCC-4.8 is to just use the gcc48 variant of boost:
sudo port install boost +gcc48

Linking C++ library (libtorrent) from Objective-C

I'm trying to use libtorrent library from Xcode 5.0 Objective-C Project without success.
I've built boost 1.54 and libtorrent-rasterbar (latest) from sources using LLVM 5.0, no problems with that. Also, via MacPorts I obtained pkg-config to get the proper cflags for libtorrent-rasterbar library. From my build settings, the output for pkgconfig libs and cflags were:
-DTORRENT_USE_OPENSSL -DWITH_SHIPPED_GEOIP_H
-DBOOST_ASIO_HASH_MAP_BUCKETS=1021
-DBOOST_EXCEPTION_DISABLE -DBOOST_ASIO_ENABLE_CANCELIO
-DBOOST_ASIO_DYN_LINK -DTORRENT_LINKING_SHARED -I/usr/local/include
-I/usr/local/include/libtorrent
-L/usr/local/lib -ltorrent-rasterbar
Naturally, I added those parameters to Xcode "Linker Flags" and "C/C++ Flags" settings.
Unfortunately, I cannot get my called functions to link right. This is a sample class I wrote in a testclass.cpp file:
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/file.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/create_torrent.hpp"
void testclass::addFilesFromPath(const char* path)
{
libtorrent::file_storage fs;
libtorrent::add_files(fs, path);
}
Tried to get called from a createpackage.mm file:
testclass* pPackage = new testclass();
testclass->addFilesFromPath([_sessionDir UTF8String]);
The linker cannot found the symbols, output is:
Undefined symbols for architecture x86_64:
"libtorrent::parent_path(std::__1::basic_string, std::__1::allocator > const&)",
referenced from:
libtorrent::add_files(libtorrent::file_storage&, std::__1::basic_string,
std::__1::allocator > const&, unsigned int) in
createpackage.o
"libtorrent::detail::add_files_impl(libtorrent::file_storage&,
std::__1::basic_string,
std::__1::allocator > const&, std::__1::basic_string, std::__1::allocator > const&,
boost::function, std::__1::allocator >)>, unsigned
int)", referenced from:
libtorrent::add_files(libtorrent::file_storage&, std::__1::basic_string,
std::__1::allocator > const&, unsigned int) in
createpackage.o
"libtorrent::complete(std::__1::basic_string, std::__1::allocator > const&)",
referenced from:
libtorrent::add_files(libtorrent::file_storage&, std::__1::basic_string,
std::__1::allocator > const&, unsigned int) in
createpackage.o
"libtorrent::filename(std::__1::basic_string, std::__1::allocator > const&)",
referenced from:
libtorrent::add_files(libtorrent::file_storage&, std::__1::basic_string,
std::__1::allocator > const&, unsigned int) in
createpackage.o ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see
invocation)
I'm pretty puzzled. Checked that libtorrent-raster bar architecture is x86_64. Also, boost is built OK. I'm new to this C++ / Objetive-C code mixing approach.
Thanks.
EDIT 1:
I've resorted to a minimal sample. Made the following CPP file:
#include "libtorrent/file.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/create_torrent.hpp"
int main()
{
libtorrent::file_storage fs;
libtorrent::add_files(fs, ".");
}
At command line, tried:
c++ test.cpp $(pkg-config /usr/local/lib/pkgconfig/libtorrent-rasterbar.pc --cflags --libs) -lboost_system
Build is successful. So I wonder how to put all that pkg-config data into the proper target configurations in OSX.
Finally, problem was solved.
Let's check symbols comparing the produced object file and the symbols contained in libtorrent library.
nm createpackage.o|grep 'add_files'
U __ZN10libtorrent6detail14add_files_implERNS_12file_storageERKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEESB_N5boost8functionIFbS9_EEEj
00000000000002a0 S __ZN10libtorrent9add_filesERNS_12file_storageERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEj
00000000000018e0 S __ZN10libtorrent9add_filesERNS_12file_storageERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEj.eh
Compare with:
$ nm libtorrent-rasterbar.a | grep 'add_files'
00000000000002f0 T __ZN10libtorrent6detail14add_files_implERNS_12file_storageERKSsS4_N5boost8functionIFbSsEEEj
0000000000006e68 S __ZN10libtorrent6detail14add_files_implERNS_12file_storageERKSsS4_N5boost8functionIFbSsEEEj.eh
The difference as many could imagine seeing that output, it's that i'm using the LLVM Standard C++ library for my .mm files while libtorrent was compiled with GCC Stdlib, that's the reason of different symbols referring to char_traits, basic_string, etc.
So, changing in XCode Build Settings > Standard C++ Library to libstdc++ fixed the problem.

clang mac link errors with gtest Undefined symbols for architecture x86_64

Not sure what issue I am having here.
Mac clang 3.1 cmake
gtest
few files
using few C++11 features
I have downloaded and installed XCode build tools
CMAKE_CXX_FLAGS = -Wall -std=c++0x -stdlib=libc++ -v
builds fine with output...
[100%] Building CXX object CMakeFiles/soupbintcptest.dir/soupmessages_tests.cpp.o
clang version 3.1 (tags/RELEASE_31/final)
Target: x86_64-apple-darwin11.3.0
Thread model: posix
Linking dumps a slew of errors. ABI errors? I know there is this C++11 namespace mangling thing happening.
Undefined symbols for architecture x86_64:
They are all things in the std:: namespace that will not link like:
"std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::_Setprecision)", referenced from:
testing::AssertionResult testing::internal::FloatingPointLE<float>(char const*, char const*, float, float) in libgtest.a(gtest-all.cc.o)
testing::AssertionResult testing::internal::FloatingPointLE<double>(char const*, char const*, double, double) in libgtest.a(gtest-all.cc.o)
testing::Message::Message() in libgtest.a(gtest-all.cc.o)
or
"std::cerr", referenced from:
testing::internal::GTestLog::GetStream() in libgtest.a(gtest-all.cc.o)
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()", referenced from:
testing::UnitTest::AddTestPartResult(testing::TestPartResult::Type, char const*, int, testing::internal::String const&, testing::internal::String const&) in libgtest.a(gtest-all.cc.o)
testing::internal::SingleFailureChecker::~SingleFailureChecker() in libgtest.a(gtest-all.cc.o)
testing::internal::StringStreamToString(std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >*) in libgtest.a(gtest-all.cc.o)
testing::TestInfo::TestInfo(char const*, char const*, char const*, char const*, void const*, testing::internal::TestFactoryBase*) in libgtest.a(gtest-all.cc.o)
testing::TestInfo::~TestInfo() in libgtest.a(gtest-all.cc.o)
testing::internal::ReportInvalidTestCaseType(char const*, char const*, int) in libgtest.a(gtest-all.cc.o)
testing::internal::XmlUnitTestResultPrinter::PrintXmlUnitTest(__sFILE*, testing::UnitTest const&) in libgtest.a(gtest-all.cc.o)
...
I believe I have built gtest with the same clang++ version. Not sure what else is going on here to drive these issues.
I've seen similar errors to yours when the linker is pulling in a different c++ library to the one that matches what the compiler is building for. In your case, you are only modifying the compiler flags, but the linker doesn't know your choice and is likely linking to the wrong C++ library.
If you are able to use CMake 3.2 or later, then rather than modifying the C++ compiler flags directly, I'd recommend you just tell CMake you want to use C++11 and then let it work out the appropriate compiler and linker flags for you. This can be done by adding the following before your project() call:
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
This and related CMake features are discussed in detail in this article.
There is nothing C++11 about name mangling, it's been going on since the very first C++ implementations. However, do not forget that you must have built gtest for the same stdlib switch, because it can't find the Standard libraries.

Attempting to use Boost.Filesystem however it doesn't seem to link?

I'm using OS X 10.7.3. I've been playing with the boost headers for a while now and i wanted to move onto using the Boost.Filesystem lib however it keeps throwing this message at me:
Undefined symbols for architecture x86_64:
"boost::system::generic_category()", referenced from:
__static_initialization_and_destruction_0(int, int)in ccOhIhNG.o
boost::filesystem3::detail::create_directories(boost::filesystem3::path const&, boost::system::error_code*)in libboost_filesystem.a(operations.o)
boost::filesystem3::detail::canonical(boost::filesystem3::path const&, boost::filesystem3::path const&, boost::system::error_code*)in libboost_filesystem.a(operations.o)
"boost::system::system_category()", referenced from:
__static_initialization_and_destruction_0(int, int)in ccOhIhNG.o
(anonymous namespace)::error(bool, boost::system::error_code const&, boost::filesystem3::path const&, boost::system::error_code*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)in libboost_filesystem.a(operations.o)
(anonymous namespace)::error(bool, boost::filesystem3::path const&, boost::system::error_code*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)in libboost_filesystem.a(operations.o)
(anonymous namespace)::error(bool, boost::filesystem3::path const&, boost::filesystem3::path const&, boost::system::error_code*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)in libboost_filesystem.a(operations.o)
boost::filesystem3::detail::dir_itr_close(void*&, void*&)in libboost_filesystem.a(operations.o)
boost::filesystem3::detail::directory_iterator_increment(boost::filesystem3::directory_itera tor&, boost::system::error_code*)in libboost_filesystem.a(operations.o)
boost::filesystem3::detail::directory_iterator_construct(boost::filesystem3::directory_itera tor&, boost::filesystem3::path const&, boost::system::error_code*)in libboost_filesystem.a(operations.o)
...
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
i get this when i try to compile using this:
g++ -o test main.cpp -I -l/opt/local/include ~/boost/libs/libboost_filesystem.a
So i went back to the boost.org tutorials and tried out the regex example. It worked perfectly using this:
g++ -o test main.cpp -I -l/opt/local/include ~/boost/libs/libboost_regex.a
try
g++ -o test main.cpp -I/opt/local/include -L/opt/local/lib -lboost_filesystem
Your compiler flags seem a bit off. Generally, the following hold:
-I // Sets the path for the relevant header files
-L // Sets the path where your libraries reside
-l // specifies the library you want to link against.
So, if you have a library called mylib in ~/libs/ and need to use header files located in ~/include, you'd pass
-I ~/include -L ~/libs -lmylib
as flags to the compiler.