Why Can't Clang With Libc++ in C++0X Mode Link This Boost::Program_Options Example

Why can't clang with libc++ in c++0x mode link this boost::program_options example?

You need to rebuild boost using clang++ -stdlib=libc++.

libc++ is not binary compatible with gcc's libstdc++ (except for some low level stuff such as operator new). For example the std::string in gcc's libstdc++ is refcounted, whereas in libc++ it uses the "short string optimization". If you were to accidentally mix these two strings in the same program (and mistake them for the same data structure), you would inevitably get a run time crash.

This accident is exactly what has occurred in your case.

In order to turn this run time crash into a link time error, libc++ uses a C++11 language feature called inline namespace to change the ABI of std::string without impacting the API of std::string. That is, to you std::string looks the same. But to the linker, std::string is being mangled as if it is in namespace std::__1. Thus the linker knows that std::basic_string and std::__1::basic_string are two different data structures (the former coming from gcc's libstdc++ and the latter coming from libc++).

Linking troubles with boost::program_options on OSX using LLVM

You will need to recompile boost with clang and std11 flags, the libc++ library is not binary compatible with the installed libstdc++ in OSX (very early version of gcc prior to changing to gpl3). If your version of clang is 3.1 or over then you can use (otherwise change c++11 to c++0x for earlier versions).

./bootstrap.sh
mkdir build
sudo ./bjam toolset=clang cxxflags="-std=c++0x -stdlib=libc++" variant=release link=static threading=multi runtime-link=shared --build-dir=Build --layout=system --without-mpi --without-python install --prefix=/usr/local

You can of course alter any of these as you wish except

toolset=clang cxxflags="-std=c++0x -stdlib=libc++"

This should work for you.

How to compile/link Boost with clang++/libc++?

I didn't know how to do this either. But after poking around in here, the getting started, and trial and error:

$ ./bootstrap --with-toolset=clang
$ ./b2 clean
$ ./b2 toolset=clang cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++"

You'll get lots of warnings. And the signals library will fail to build due to LWG 2059. But otherwise I think it works.

Linking troubles with boost::program_options on OSX using LLVM

You will need to recompile boost with clang and std11 flags, the libc++ library is not binary compatible with the installed libstdc++ in OSX (very early version of gcc prior to changing to gpl3). If your version of clang is 3.1 or over then you can use (otherwise change c++11 to c++0x for earlier versions).

./bootstrap.sh
mkdir build
sudo ./bjam toolset=clang cxxflags="-std=c++0x -stdlib=libc++" variant=release link=static threading=multi runtime-link=shared --build-dir=Build --layout=system --without-mpi --without-python install --prefix=/usr/local

You can of course alter any of these as you wish except

toolset=clang cxxflags="-std=c++0x -stdlib=libc++"

This should work for you.

clang++ -stdlib=libc++ leads to undefined reference

According you error, it should be like you're trying to link a libc++ with stdlibc++,
the libc++ and stdlibc++ is different, stdlibc++ is gcc's c++ standard library, it will not compatible with each other.

For your issue, it's like your libpoppler.so is using stdlibc++,
but in your clang command line, you're trying use libc++ as standard lib, they have different name in linking stage, see link at the end of this answer for detail why.

So, maybe your solution is just change the compile command to

    clang++ -stdlib=libstdc++  po.cxx -lpoppler

Please see this question for detail why std:__1::set and std::set.

Why can't clang with libc++ in c++0x mode link this boost::program_options example?

Does boost use C++11 inline namespaces to avoid ABI incompatibilty errors at runtime?

Some libraries have started to use it, but not all. For example this is in Boost.Log:

//! NOTE: I've reformatted this to look cleaner.
#if !defined(BOOST_NO_CXX11_INLINE_NAMESPACES)
inline namespace BOOST_LOG_VERSION_NAMESPACE {}
[snip]
#endif

How to use boost::program_options to accept an optional flag?

A convenient way to do this is with the bool_switch functionality:

bool flag = false;

namespace po = boost::program_options;

po::options_description desc("options");

desc.add_options()
("flag,f", po::bool_switch(&flag), "description");
po::variables_map vm;
//store & notify

if (flag) {
// do stuff
}

This is safer than manually checking for the string (string only used once in whole definition).



Related Topics



Leave a reply



Submit