How do I compile boost for OS X 64b platforms with stdlibc++?
Asked Answered
P

2

8

I would like to compile boost for Mac OS X 10.9, with stdlibc++. I run the following command:

./b2 threading=multi link=static runtime-link=static cxxflags="-stdlib=libstdc++" linkflags="-stdlib=libstdc++"

The build completes successfully; however, my application build fails at linkage time, when it can't find symbols suck as std::__1::locale::use_facet, std::__1::basic_string etc. The pertinent detail there is the __1, I believe.

My question is, how do I compile boost for OSX 64b platforms with stdlibc++?

More info:

I have noticed the following logs during compilation:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib: file: bin.v2/libs/filesystem/build/clang-darwin-4.2.1/release/link-static/runtime-link-static/threading-multi/libboost_filesystem.a(windows_file_codecvt.o) has no symbols

Phineas answered 20/11, 2013 at 22:27 Comment(6)
You are compiling your application with -stdlib=libstdc++? because that will also be neededRialto
@Petesh yes I'm compiling the app with libstdc++Phineas
Pick a boost library that you built which definitely relies on something in STL, run an nm on it, pipe it through c++filt and check that it's mentioning std::__1::. If it mentions that, then boost has been built with libstdc++ and you're not compiling/linking your application properly in that case.Rialto
@Petesh if I perform those steps on libboost_filesystem.a I see the expected namespace. However I do notice in my compilation logs the following message >/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib: file: bin.v2/libs/filesystem/build/clang-darwin-4.2.1/release/link-static/runtime-link-static/threading-multi/libboost_filesystem.a(windows_file_codecvt.o) has no symbolsPhineas
At a wild guess the .o file in question (with a name like windows_file_codecvt) is windows specific. It has a guard around the code: #ifdef BOOST_WINDOWS_API, so the lack of symbols in it is not unexpectedRialto
I had one of those colossal brain farts. Your boost is compiled with libc++, not libstdc++. I am losing my mind (apologies for the misdirection in this).Rialto
R
21

Downloaded Boost 1.55, bootstrapped using:

./bootstrap.sh --prefix=/usr/local/boost155 cxxflags="-arch i386 -arch x86_64" \
    address-model=32_64 threading=multi macos-version=10.8 stage

Built using:

./b2 threading=multi link=static runtime-link=static \
    cxxflags="-stdlib=libstdc++" linkflags="-stdlib=libstdc++"

Yields in libboost_chrono.a:

     U std::string::_Rep::_M_destroy(std::allocator<char> const&)
     U std::string::_Rep::_S_empty_rep_storage
     U std::string::append(char const*, unsigned long)
     U std::string::append(std::string const&)
     U std::string::assign(char const*, unsigned long)
     U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)
     U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&)

Which implies that the library was built with the option -stdlib=libstdc++ - i.e. it's linked against the gnu version of the C++ runtime.

We purge the build using:

find . -name \*.o -print0 | xargs -0 rm
find . -name \*.a -print0 | xargs -0 rm

If we don't do that then it doesn't rebuild, and you end up with the same code as before. Next we build using:

./b2 threading=multi link=static runtime-link=static \
    cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++"

Yields in libboost_chrono.a:

     U std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::append(char const*)
     U std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::append(char const*, unsigned long)
     U std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::assign(char const*)
     U std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
     U std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()

Which implies that it's built against libc++.

This can be verified by using a simple test c++ program (to indicate the linking):

#include <string>

int
main(int argc, char **argv)
{
    std::string s("Hello World");
    return 0;
}

$ make test
c++     test.cpp   -o test
$ nm ./test | c++filt
                 U std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(char const*, unsigned long)
                 U std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()

$ rm test
$ make test CXXFLAGS=-stdlib=libstdc++
c++ -stdlib=libstdc++    test.cpp   -o test
$ nm ./test | c++filt
                 U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)
                 U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()

so yes, it's compiling with the relevant flag. What it does indicate that you have to pass the -stdlib=libstdc++ to everything you're compiling if you're using XCode 5 as it now defaults to using -stdlib=libc++. This means that any C++ based libraries that depend on c++ stdlib that you depend on also have to be compiled with the same flag.

Be careful with an incremental build of boost - if you don't purge the .o and .a files, they don't get recompiled based on the changed flags, which keeps the files as compiled, so if they were miscompiled then you encounter the problem.

Rialto answered 26/11, 2013 at 22:25 Comment(7)
Do you have ideas how it can be compiled under FreeBSD? When I have tried to compile boost under FreeBSD with this command sudo ./b2 -j 4 threading=multi link=static toolset=clang cxxflags="-stdlib=libstdc++" linkflags="-stdlib=libstdc++, I have the following error libs/atomic/src/lockpool.cpp:15:10: fatal error: 'cstddef' file not found #include <cstddef>Gwennie
You're compiling on a new release of FreeBSD (11.0?) that does not have a copy of gcc or libstdc++ installed. You will first need to ensure that they have been installed on the system; then you might be able to build it. the FreeBSD project moved from gcc to clang, so in the long term, you're far better off building everything with clang, rather than trying to get this to work.Rialto
Petesh, thank you for a quick reply! Yes, I have FreeBDS 11.0 and actually I have gcc installed and here is locate output : /usr/local/lib/gcc48/{libstdc++.a, libstdc++.so, libstdc++.so.6, libstdc++.so.6.0.19, libstdc++.so.6.0.19-gdb.py, libstdc++.a, libstdc++.so, libstdc++.so.6, libstdc++.so.6.0.20, libstdc++.so.6.0.20-gdb.py} /usr/local/lib/gcc5/{libstdc++.a, libstdc++.so, libstdc++.so.6, libstdc++.so.6.0.21, libstdc++.so.6.0.21-gdb.py, libstdc++fs.a} /usr/ports/lang/libstdc++_stldoc_4.2.2/{Makefile, distinfo, pkg-descr} What might be a problem in this case?Gwennie
using toolset=clang with -stdlib=libstdc++ won't work - it relies on clang being compiled with that support, and it isn't on FreeBSD. You'll have to bootstrap and build boost with gcc to get libstdc++ support - ./bootstrap.sh --with-toolset=gcc && ./b2 -j 4 threading=multi link=staticRialto
I've built b2 with gcc flag, but unfortunately still have an error: gcc.compile.c++ bin.v2/libs/math/build/gcc-5.4.0/release/link-static/threading-multi/assoc_laguerre.o g++: internal compiler error: Segmentation fault (program cc1plus) ...failed gcc.compile.c++ bin.v2/libs/math/build/gcc-5.4.0/release/link-static/threading-multi/assoc_laguerre.o... I use gcc 5.4.0Gwennie
Looks to be an internal compiler error in relation to the precompiled header - probably compiler specific. as a potential workaround, do rm bin.v2/libs/math/build/gcc-5.4.0/release/link-static/threading-multi/../src/tr1/pch.hpp.gch && touch bin.v2/libs/math/build/gcc-5.4.0/release/link-static/threading-multi/../src/tr1/pch.hpp.gch and then rerun b2 - this nukes the precompiled header file, which hopefully will get you past the issue.Rialto
Thank you for your help! I've compiled boost and project with clang and libc++Gwennie
M
0

I use an easy command line to do the trick found on boost mailing list: http://lists.boost.org/boost-users/2014/02/81274.php

this is the snippet in case the link doesn't work anymore:

$ cd tools/build/v2/ 
$ ./bootstrap.sh 
$ cd ~/boost-stdc++-install/boost_1_54_0 
$ cd ~/boost-stdc++-install/boost_1_54_0 
$ tools/build/v2/b2 \ 
     --build-dir=`pwd`/tmp/build/ \ 
     --stagedir=`pwd`/tmp/stage/ \ 
     --buildid=libstdc++ \ 
     --layout=tagged -j24 \ 
     toolset=clang \ 
     cxxflags="-ftemplate-depth=999 -stdlib=libstdc++" \ 
     linkflags="-stdlib=libstdc++" \ 
     define=BOOST_SYSTEM_NO_DEPRECATED stage 
Maltose answered 21/10, 2014 at 9:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.