Почему нельзя связать с libc ++ в режиме c ++ 0x ссылку на этот пример boost :: program_options? - PullRequest
63 голосов
/ 10 декабря 2011

Компиляция этого примера кода для boost :: program_options: http://svn.boost.org/svn/boost/trunk/libs/program_options/example/first.cpp

... на MacOS Lion (10.7.2), используя boost-1.48.0, установленный с MacPorts:

$ clang++ -v
Apple clang version 3.0 (tags/Apple/clang-211.12) (based on LLVM 3.0svn)
Target: x86_64-apple-darwin11.2.0
Thread model: posix
$ clang++ -std=c++0x --stdlib=libc++ -lc++ -I/opt/local/include -L/opt/local/lib -lboost_program_options first.cpp -o first
Undefined symbols for architecture x86_64:
  "boost::program_options::options_description::options_description(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned int, unsigned int)", referenced from:
      _main in cc-6QQcwm.o
  "boost::program_options::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, boost::program_options::options_description const&)", referenced from:
      _main in cc-6QQcwm.o
  "boost::program_options::abstract_variables_map::operator[](std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const", referenced from:
      boost::program_options::variables_map::operator[](std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const in cc-6QQcwm.o
  "boost::program_options::detail::cmdline::set_additional_parser(boost::function1<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>)", referenced from:
      boost::program_options::basic_command_line_parser<char>::extra_parser(boost::function1<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>) in cc-6QQcwm.o
  "boost::program_options::detail::cmdline::cmdline(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&)", referenced from:
      boost::program_options::basic_command_line_parser<char>::basic_command_line_parser(int, char const* const*) in cc-6QQcwm.o
  "boost::program_options::to_internal(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      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> > > > boost::program_options::to_internal<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(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&) in cc-6QQcwm.o
  "boost::program_options::invalid_option_value::invalid_option_value(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      void boost::program_options::validate<int, char>(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&, int*, long) in cc-6QQcwm.o
  "boost::program_options::validation_error::validation_error(boost::program_options::validation_error::kind_t, 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> > const&)", referenced from:
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const& boost::program_options::validators::get_single_string<char>(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&, bool) in cc-6QQcwm.o
  "boost::program_options::value_semantic_codecvt_helper<char>::parse(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&, bool) const", referenced from:
      vtable for boost::program_options::typed_value<int, char> in cc-6QQcwm.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Тот же код, скомпилированный / связанный с g ++ 4.7, установленный с MacPorts:

$ g++-mp-4.7 -std=c++0x -I/opt/local/include -L/opt/local/lib -lboost_program_options -o first first.cpp

... отлично работает. Как и при использовании clang без libc ++:

clang++ -std=c++0x -I/opt/local/include -L/opt/local/lib -lboost_program_options first.cpp -o first

Что не так? Почему boost :: program_options и libc ++ не работают вместе?

1 Ответ

134 голосов
/ 10 декабря 2011

Вам необходимо перестроить boost, используя clang ++ -stdlib = libc ++.

libc ++ не двоично совместим с libstdc ++ gcc (за исключением некоторых вещей низкого уровня, таких как оператор new).Например, std::string в gcc в libstdc ++ пересчитан, тогда как в libc ++ он использует «оптимизацию коротких строк».Если бы вы случайно смешали эти две строки в одной и той же программе (и приняли их за одну и ту же структуру данных), вы неизбежно получили бы сбой во время выполнения.

Это именно то, что произошло в вашем случае.

Чтобы превратить этот сбой во время выполнения в ошибку времени компоновки, libc ++ использует функцию языка C ++ 11 под названием inline namespace, чтобы изменить ABI std::string без влияния на API из std::string.То есть для вас std::string выглядит так же.Но для компоновщика std::string искажается, как если бы он находился в пространстве имен std::__1.Таким образом, компоновщик знает, что std::basic_string и std::__1::basic_string - это две разные структуры данных (первая происходит из libstdc ++ gcc, а вторая - из libc ++).

...