Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using c++11 in MacOS X and compiled Boost libraries conundrum

I am trying to compile a c++ project that uses c++11 standards extensively. Everything was going well with just -std=c++11, until I tried to use unordered_map and MacOS simply doesn't have the unordered_map header file anywhere in usr/include.

I did some research and found that using -stdlib=libc++ would fix it (not sure how, this seems like magic to me if the include file is nowhere in the filesystem). It certainly did. It compiled well, but the linker cannot link to the boost::program_options that my program also uses extensively. Without -stdlib=libc++, boost links perfectly, but I lose the unordered_map.

What should I do to have the latest C++11 features with the Mac OS clang++ compiler and still be able to link to boost libraries (which were built from sources on this very mac)

ps: all works fine in my arch linux box

my makefile:

LIBS = -lboost_program_options CXXFLAGS = -stdlib=libc++ -std=c++11 -Wall -g OBJ = fastq.o fastq_reader.o main.o degenerate.o interleave.o complement.o interval_utils.o interval.o interval_utils_test_tool.o

foghorn: $(OBJ) $(LINK.cc) -o $@ $^ $(LIBS)

The output using -stdlib=libc++

$ make c++ -stdlib=libc++ -std=c++11 -Wall -g -c -o fastq.o fastq.cpp c++ -stdlib=libc++ -std=c++11 -Wall -g -c -o fastq_reader.o fastq_reader.cpp c++ -stdlib=libc++ -std=c++11 -Wall -g -c -o main.o main.cpp c++ -stdlib=libc++ -std=c++11 -Wall -g -c -o degenerate.o degenerate.cpp c++ -stdlib=libc++ -std=c++11 -Wall -g
-c -o interleave.o interleave.cpp c++ -stdlib=libc++ -std=c++11 -Wall -g -c -o complement.o complement.cpp c++ -stdlib=libc++ -std=c++11 -Wall -g -c -o interval_utils.o interval_utils.cpp c++ -stdlib=libc++ -std=c++11 -Wall -g -c -o interval.o interval.cpp c++ -stdlib=libc++ -std=c++11 -Wall -g -c -o interval_utils_test_tool.o interval_utils_test_tool.cpp c++ -stdlib=libc++ -std=c++11 -Wall -g
-o foghorn fastq.o fastq_reader.o main.o degenerate.o interleave.o complement.o interval_utils.o interval.o interval_utils_test_tool.o -lboost_program_options Undefined symbols for architecture x86_64: "boost::program_options::to_internal(std::__1::basic_string, std::__1::allocator > const&)", referenced from: std::__1::vector, std::__1::allocator >, std::__1::allocator, std::__1::allocator > > > boost::program_options::to_internal, std::__1::allocator >

(std::__1::vector, std::__1::allocator >, std::__1::allocator, std::__1::allocator > > > const&) in main.o

  ... [clipped output for readability]

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

like image 576
Carneiro Avatar asked Aug 09 '13 03:08

Carneiro


1 Answers

edit: See comments below for modern MacOS; the --c++11 flag is no longer valid

After a lot of research, I learned the following:

  • Everything on MacOS X is built using stdlibc++ (including everything you install with homebrew -- which was my case)
  • stdlibc++ that comes with gcc 4.2 does not implement many of the features of c++11. Examples are unordered_map, to_string, stoi, ... only libc++ does.
  • libc++ is installed in MacOS by XCode.

Conclusion:

  • If you're using c++11, you have to use -stdlib=libc++.
  • If you want to use boost or any other library, you have to recompile them with -stdlib=libc++ as well.

So I downloaded boost sources from their website, and compiled using the following command line:

bootstrap.sh && b2 toolset=clang cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++" install

If you use Homebrew, you can do it with and it will do the right thing for you:

brew install boost --c++11 
like image 196
Carneiro Avatar answered Nov 05 '22 22:11

Carneiro