简体   繁体   中英

Linking troubles with boost::program_options on OSX using LLVM

I'm having trouble getting through the linking phase in my C++ program due to problems with Boost 1.49. I have switched to C++ ( -std=c++11 -libc=libc++ ) which works fine for another piece of code (which also uses boost). Boost was installed using homebrew with:

brew install boost --universal --with-mpi --with-icu

The trouble starts with boost::program_options . I get the link errors like this:

  "boost::program_options::validate(boost::any&, std::__1::vector<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&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, int)", referenced from:

... etc. ...

ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

This is a little strange, because doing an nm on the library used reveals, that the symbol appears to be there:

nm -U /usr/local/lib/libboost_program_options-mt.dylib  | grep validate
0000000000019880 - 01 0000   FUN __ZN5boost15program_options8validateERNS_3anyERKSt6vectorISbIwSt11char_traitsIwESaIwEESaIS7_EEPSsi
0000000000019880 T __ZN5boost15program_options8validateERNS_3anyERKSt6vectorISbIwSt11char_traitsIwESaIwEESaIS7_EEPSsi
00000000000199e0 - 01 0000   FUN __ZN5boost15program_options8validateERNS_3anyERKSt6vectorISbIwSt11char_traitsIwESaIwEESaIS7_EEPbi
00000000000199e0 T __ZN5boost15program_options8validateERNS_3anyERKSt6vectorISbIwSt11char_traitsIwESaIwEESaIS7_EEPbi
0000000000019930 T __ZN5boost15program_options8validateERNS_3anyERKSt6vectorISsSaISsEEPSsi
0000000000019930 - 01 0000   FUN __ZN5boost15program_options8validateERNS_3anyERKSt6vectorISsSaISsEEPSsi
0000000000019c70 - 01 0000   FUN __ZN5boost15program_options8validateERNS_3anyERKSt6vectorISsSaISsEEPbi
0000000000019c70 T __ZN5boost15program_options8validateERNS_3anyERKSt6vectorISsSaISsEEPbi

I have already tried coaxing homebrew to compile boost with clang instead of gcc by setting CXX and CXX_FLAGS accordingly prior to installation. Not sure I succeeded though.

Pointers greatly appreciated.

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.

I would like to share my (moderately painful) experience of building Boost 1.54 on Mac OS X 10.8.5 with clang 5.0.0 as supplied by Xcode 5.0 . If you want the C++11 features it is very important to compile and link with clang++ , not with clang .

Illustration: take the following simple program:

#include <iostream>
#include <string>

int main(int argc, char *argv[]) {
    std::string str = "OK";
    std::cout << str << std::endl;
    return 0;
}

Can be built with the following command:

clang++ -std=c++11 -stdlib=libc++ clangstr.cc -o clangstr

however, if you try this instead:

clang -std=c++11 -stdlib=libc++ clangstr.cc -o clangstr

then you get linker errors. Note that the clang manpage says that the language is selected by the -std= option, but this is clearly not enough.

The lesson is that we have to tell bjam to explicitly use clang++ when compiling Boost with C++11 support.

Following this very useful post , I put the following into my tools/build/v2/user-config.jam :

using clang : 11
    : "/usr/bin/clang++"
    : <cxxflags>"-std=c++11 -stdlib=libc++ -ftemplate-depth=512" <linkflags>"-stdlib=libc++"
    ;

Then I ran ./b2 clean , then I built Boost with the following command:

mkdir -p build/clangstage/
./b2 -j8 --build-dir=build --stagedir=build/clangstage toolset=clang-11 define=BOOST_SYSTEM_NO_DEPRECATED variant=release threading=multi address-model=64 stage

This builds the 64-bit static and dynamic libraries with multithreading support. If you need a different set then change the command above accordingly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM