Обновление GCC
Данный документ показывает пользователям процесс обновления GCC.
Обратите внимание, что понижение версии GCC может иметь нежелаемые побочные эффекты. Обратитесь к секции Устранение проблем для информации по часто встречаемым проблемам.
Вкратце
Следующий раздел быстро введет вас в процесс обновления GCC (и того, как просто его сделать). Больше деталей предоставлено в следующем разделе Объяснение обновления GCC.
Большинство обновлений GCC так же просты, как смена версии компилятора (тут с 5.4.0 на 6.4.0) и пересборка libtool:
root #
emerge --ask --oneshot sys-devel/gcc
root #
gcc-config --list-profiles
[1] x86_64-pc-linux-gnu-5.4.0 * [2] x86_64-pc-linux-gnu-6.4.0
root #
gcc-config 2
root #
source /etc/profile
root #
emerge --ask --oneshot --usepkg=n sys-devel/libtool
Если вы обновляетесь с GCC 4.x на GCC 5.x или позднее, есть дополнительные инструкции; смотрите отдельную страницу Обновление с gcc-4.x на gcc-5.x.
Проверьте текущую версию и удалите старую версию:
root #
gcc --version
root #
emerge --ask --depclean =sys-devel/gcc-5.4.0
После этого, убедитесь в целостности системы, запустив revdep-rebuild:
root #
revdep-rebuild
Наслаждайтесь новым компилятором!
Объяснение обновления GCC
Обновление GCC всегда считалось какой-то мистикой, с предположениями от "пользователям ничего не нужно делать" до "пользователям нужно дважды пересобрать всю свою систему". Большинство страха, неуверенности и сомнений проистекает из проблем, связанных с несовместимостью ABI. Такое редко происходит в наши дни (и когда происходит, это анонсируется). Но, сначала кратко о libtool.
libtool
Причина, по которой нужно пересобирать libtool после обновления версий gcc это потому, что главной функцией libtool является объединение кода, зависящего от платформы в общем интерфейсе, что позволяет приложениям использовать разделяемые библиотеки без нужды иметь дело с вещами, зависящими от платформы для разделяемых библиотек. Чтобы реализовать эту функцию, скрипт libtool использует различные пути до библиотек, в которых есть жестко заданная информация о версии gcc.
Изменения ABI
ABI, или Двоичный интерфейс приложений, это набор соглашений, используемых всеми инструментами, работающими с бинарным видом программ, например, компиляторы, ассемблеры, линкеры и поддержка рантайма для языков (источник: Бинарная совместимость GCC). Когда ABI, используемый для бинарных приложений и библиотек меняется, появляется риск получить ошибку компоновщика, либо неработающие программы, если только вы не пересоберёте все программы, использующие код C++.
Да, C++, поскольку в большинстве случаев несоответствия обнаруживаются на уровне двоичного интерфейса приложений C++. Если вы обновляетесь до GCC 4.1, или GCC 5.1, вы, вероятно, столкнетесь с проблемами в двоичном интерфейсе. Чтобы избежать этого должна быть запущена команда revdep-rebuild для libstdc++.so.5 (от GCC 3 до GCC 4.1), или libstdc++.so.6 (от GCC 4 до GCC 5.1).
root #
revdep-rebuild --library 'libstdc++.so.6' -- --exclude gcc
Так почему же это нужно только до GCC 3.4.0/4.1/5? Это потому что с этой версии GCC использует обратно-совместимое ABI, и пересборка приложений и библиотек больше не требуется. Конечно, мы не можем дать вам гарантию, что так будет вечно, но если снова возникнет несоответствие, мы явно опишем этот случай здесь. В этом случае, скорее всего, будет увеличена версия библиотеки libstdc++.so.
Особый случай C++11 (и C++14)
В то время как GCC (или точнее libstdc++) идет большими шагами вперед, гарантируя стабильность ABI, эта гарантия не распространяется на все части C++ в libstdc++. Формально, начиная с версии 3.4, GCC/libstdc++ только гарантируется стабильность C++98/C++03 ABI и не более. Это очень важно для пакетов, которые зависят от C++11. GCC даёт гарантию на стабильность C++11 ABI, начиная только с версии 5.1. Это означает, что переключение (даже незначительные) версии GCC (скажем, от 4.7.3 -> 4.7.4) может привести к поломке ABI для бинарных файлов, собранных из C++11 кода.
Более подробную информацию и некоторые примеры можно найти здесь:
- bug #513386
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61758
- https://blogs.gentoo.org/blueness/2015/03/10/the-c11-abi-incompatibility-problem-in-gentoo/
- https://stackoverflow.com/questions/16190269/g-always-backward-compatible-with-older-static-libraries/16196475#16196475
Какие пакеты определенно нужно пересобрать?
В следующей таблице приведены пакеты, которые нужно пересобрать, если они установлены, и причины этой необходимости.
Пакет | Нужно пересобрать, потому что ... |
---|---|
sys-devel/libtool | приложение libtool имеет внутри себя вшитые пути к встроенным библиотекам GCC |
sys-devel/llvm | зависит от конкретной версии GCC, могут возникнуть ошибки линкования с другими ебилдами, использующими LLVM (к примеру, media-libs/mesa), если их не пересобрать. |
sys-devel/clang | зависит от конкретной версии GCC, может зависеть от sys-devel/llvm. |
root #
emerge --ask --oneshot --usepkg=n --verbose sys-devel/libtool sys-devel/llvm sys-devel/clang
Также известны случаи, когда пакеты должны быть собраны одним и тем же компилятором (к примеру, различные qt-* пакеты). Эти пакеты чаще всего обновляются сопровождающими пакета одновременно (поэтому они всегда будут собираться одной и той же версией GCC). Выборочная переустановка таких пакетов часто сопровождается проблемами.
Пересборка всего
Некоторые люди клянутся, что нужно пересобрать все пакеты на их системе при выходе новой версии GCC. Конечно, в этом нет смысла, так как многие приложения не используют GCC для процесса сборки и установки, и на них вообще не распространяется это изменение.
Это, однако, не означает, что они полностью неправы: новые версии GCC часто предлагают более хорошую поддержку набора инструкций процессора, а это может повлиять на производительность приложений в лучшую сторону.
Кроме таких "небольших" плюсов, пересборка всего с нуля может быть обязательна в некоторых случаях, чтобы исправить проблемы без очевидных причин.
Некоторые проблемы с программами исконно трудны в диагностике, но их можно решить простой пересборкой одного или больше соответствующих пакетов. Если подобная проблема возникла после обновления GCC и сохранилась после применения revdep-rebuild как показано выше (и после пересборки прочих очевидно связанных пакетов), полная пересборка системы может решить этот вопрос.
Самый "безопасный" (но также затратный по времени) способ этого достичь - использование опции --emptytree
(-e
) для emerge, чтобы пересобрать системные пакеты и мир:
root #
emerge --ask --emptytree --usepkg=n @system
root #
emerge --ask --emptytree --usepkg=n @world
Пользователям рекомендуется попробовать этот подход, прежде чем писать о багах, которые могли произойти из-за обновления GCC.
(Заметьте, что команды выше пересоберут пакеты в системном наборе дважды, что необходимо, дабы быть "абсолютно уверенными", что каждый пакет был собран в одинаковой [предположительно] "безпроблемной" среде. Любые проблемы, что сохраняются после этого - действительно баги, о которых нужно сообщить, или серьёзные проблемы с конфигурацией системы.)
Устранение проблем
пересборка boost
Если dev-libs/boost нужно пересобрать, вы получите следующее сообщение об ошибке:
root #
emerge ...
checking for the Boost _____ library... no configure: error: cannot find the flags to link with Boost _____
Пересобрать можно с помощью:
root #
emerge --ask --oneshot --usepkg=n --verbose dev-libs/boost
libstdc++.so.6: version `GLIBCXX_3.4.15' not found
В процессе обновлений вы можете встретить ошибку, похожую на следующую:
cmake_bootstrap_28021_test: /usr/lib/gcc/i486-pc-linux-gnu/4.1.2/libstdc++.so.6: version `GLIBCXX_3.4.11' not found
Это означает, что вы пытаетесь собрать пакет более старой версией GCC, чем собирались библиотеки, от которых зависит пакет. Помните, мы говорили, что C++ ABI обратно совместим? Это так, но означает только, что для сборки приложений и линковки библиотек могут использоваться более новые (или те же самые) версии GCC (по сравнению с версией GCC, использованной для сборки этих библиотек).
Для пересоборки всех зависящих от libstdc++ смотрите пример команды revdep-rebuild в предыдущем разделе.
Смотрите также
- Обновление GCC до версии 4.1, предыдущая версия данного документа
- Обновление с gcc-4.x до gcc-5.x
- Fedora's 'Changes/GCC6' Wiki Page