Связывание различных стандартных библиотек C++ в Mac OS X

Теперь, когда в Mac OS X может существовать несколько стандартных библиотек C++, ситуация выглядит довольно хаотической. Согласно https://stackoverflow.com/a/8457799/1772681, смешивание libstdc++ и libc++ приведет к ошибке ссылки, который улавливает такую ​​опасную ситуацию и это хорошо.

С другой стороны, есть еще 2 ситуации, требующие дальнейшего изучения, и я создал несколько тестовых случаев для этого в github gist (https://gist.github.com/manphiz/7195515). Это подтверждает, что смешивание динамических библиотек, которые ссылаются на libstdc++ (либо из системы, либо из vanilla GNU GCC) и libc++ (система), приведет к ошибке связывания. Однако, если одна динамическая библиотека ссылается на системную libstdc++, а другая динамическая библиотека ссылается на vanilla GNU GCC libstdc++, а затем связывает обе в двоичный файл, это также работает, и для моего простого тестового примера это работает даже во время выполнения.

$ make -f Makefile.system_gnu 
g++-4.8 -g -Wall -fPIC -o main.o -c main.cc
g++-4.8 -g -Wall -fPIC -o test_a.o -c test_a.cc
g++-4.8 -dynamiclib -o libtest_a.dylib test_a.o
clang++ -g -Wall -fPIC "-stdlib=libstdc++" -o test_b.o -c test_b.cc
clang++ -dynamiclib "-stdlib=libstdc++" -o libtest_b.dylib test_b.o
g++-4.8 -o test main.o -L. -ltest_a -ltest_b

$ ./test
main_test_a_test_b

Так что тут нужен совет:

  • Можем ли мы смешать системную libstdc++ и собранную вручную GNU GCC libstdc++? Если нет, то когда это вызовет проблемы?
  • Можем ли мы смешивать системную libc++ и вручную собранную Clang libc++? Если нет, то когда это вызовет проблемы?

Информация о компиляторах:

$ clang -v
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix

$ gcc-4.8 -v
Using built-in specs.
COLLECT_GCC=gcc-4.8
COLLECT_LTO_WRAPPER=/opt/homebrew/Cellar/gcc48/4.8.2/libexec/gcc/x86_64-apple-darwin13.0.0/4.8.2/lto-wrapper
Target: x86_64-apple-darwin13.0.0
Configured with: ../configure --build=x86_64-apple-darwin13.0.0 --prefix=/opt/homebrew/Cellar/gcc48/4.8.2 --enable-languages=c,c++,fortran,java,objc,obj-c++ --program-suffix=-4.8 --with-gmp=/opt/homebrew/opt/gmp4 --with-mpfr=/opt/homebrew/opt/mpfr2 --with-mpc=/opt/homebrew/opt/libmpc08 --with-cloog=/opt/homebrew/opt/cloog018 --with-isl=/opt/homebrew/opt/isl011 --with-system-zlib --enable-version-specific-runtime-libs --enable-libstdcxx-time=yes --enable-stage1-checking --enable-checking=release --enable-lto --disable-werror --enable-plugin --disable-nls --with-ecj-jar=/opt/homebrew/opt/ecj/share/java/ecj.jar --enable-multilib
Thread model: posix
gcc version 4.8.2 (GCC)

Система Mac OS X 10.9.


person manphiz    schedule 28.10.2013    source источник


Ответы (1)


Я не говорю за Apple, но наблюдая за их действиями, я считаю, что их цель — вернуться к реализации одной стандартной библиотеки для Mac OS (и iOS) — и это будет libc++. Я верю, что когда-нибудь в будущем libstdc++ больше не будет частью Mac OS X.

Можем ли мы смешивать системную libc++ и вручную собранную Clang libc++? Если нет, то когда это вызовет проблемы?

Я делаю это довольно регулярно, но не заменяю файл в usr/lib. Вместо этого я запускаю определенные программы после установки переменной среды DYLD_LIBRARY_PATH, чтобы она указывала на мою недавно созданную библиотеку libc++. Замена файла в /usr/lib может привести к поломке вашей системы. (если вы сломаете что-то в dylib - или даже просто изменить макет std::string, скажем).

person Marshall Clow    schedule 28.10.2013
comment
На самом деле мне интересно, что произойдет, если две общие библиотеки, которые я использую, ссылаются на разные libc++ (одну на системную libc++, одну на libc++, которую я создал с помощью llvm). - person manphiz; 29.10.2013
comment
Кроме того, для случая libstdc++ означает ли, что мой пример работает, что libstdc++ поддерживает совместимость API, и поэтому можно передавать вызов из границ dylib, который ссылается на разные версии libstdc++? - person manphiz; 29.10.2013
comment
Я думаю, это означает, что части libstdc++, которые вы вызываете в своем примере, поддерживают совместимость API (или, по крайней мере, любые совместимости API не являются фатальными), но следующий вызов libstdc++, который вы делаете, может сломаться. - person Marshall Clow; 29.10.2013
comment
Спасибо за ваши ответы. Я думаю, что это на самом деле сводится к тому, как работает разделяемая библиотека, а также зависит от реализации. Пожалуйста, также включите свой комментарий о libstdС++ в ответ, который, я думаю, будет полезен для других. - person manphiz; 30.10.2013