Actualizar GCC
GCC upgrades should generally be handled gracefully with Portage and the usual Gentoo tools, see next section. If ever there are more involved updates that require user intervention, they should be accompanied by a corresponding news item, that should be read and followed.
Por favor, tenga en cuenta que desactualizar GCC podría suponer la aparición de efectos laterales no deseados. Eche un vistazo a la sección de resolución de problemas para ver más problemas de los que se informa habitualmente.
Quick guide to GCC upgrades
La mayoría de actualizaciones son tan sencillas de realizar como cambiar la versión del compilador (en este ejemplo lo hacemos de la 5.4.0 a la 6.4.0) y a continuación reconstruimos 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
Comprobar el número de la versión actual y a continuación desinstalar la versión antigua:
root #
gcc --version
root #
emerge --ask --depclean =sys-devel/gcc-5.4.0
¡Disfrute de su nuevo compilador!
Explicación de cómo actualizar GCC
La actualización de GCC siempre ha sido desconcertante, con sugerencias que van desde "los usuarios no necesitan hacer nada" hasta "los usuarios necesitarán reconstruir todo el sistema dos veces". La mayor parte de este miedo, incertidumbre y duda proviene de la confusión que rodea a la incompatibilidad ABI, algo que hoy en día rara vez ocurre (y cuando lo haga, se anunciará). Pero primero un apunte rápido sobrelibtool.
libtool
La razón por la cual necesitamos reconstruir libtool después de actualizar las versiones de gcc es debida a su función principal: libtool reúne un conjunto de herramientas que agregan código específico en un interfaz genérico permitiendo que las aplicaciones se construyan contra librerías compartidas sin tener que manejar aspectos específicos en cada plataforma de estas librerías. Para que realice su función correctamente, el guión libtool utiliza varias localizaciones en la librería con la versión de gcc previamente fijada dentro de ella.
See bug #88596.
ABI changes
Cambios en el ABI
Un ABI o ,Interfaz Binaria para Aplicaciones (en inglés Application Binary Interface), es un conjunto de convenciones usadas por todas las herramientas que manejan representaciones binarias de los programas, incluyendo compiladores, ensambladores, enlazadores y soporte en tiempo de ejecución (fuente: GCC Binary Compatibility). Al cambiar el ABI usado para aplicaciones binarias y librerías, existirá el riesgo de obtener errores de enlazado o programas funcionando incorrectamente si no se reconstruyen todas las librerías que usen el código C++.
Sí, C++, ya que la mayoría de las incompatibilidades ocurren dentro de la ABI de C++. Si está actualizando a GCC 4.1 o GCC 5.1, probablemente encontrará problemas de ABI. Para evitar esto, el comando revdep-rebuild debe ejecutarse sobre la biblioteca libstdc++.so.5 al pasar de GCC 3 a GCC 4.1, o libstdc++.so.6 al pasar de GCC 4 a GCC 5.1.
root #
revdep-rebuild --library 'libstdc++.so.6' -- --exclude gcc
Asi que, ¿Por qué se requiere esto para GCC hasta las versiones 4.1/5.1? A partir de estas versiones, GCC usa un ABI compatible a futuro, que elimina la necesidad de reconstruir las aplicaciones y librerías. Por supuesto que no se pueden dar garantía indefinidamente, pero cuando ocurra nuevamente una incompatibilidad, definitivamente la documentaremos aquí y publicaremos una noticia. En este caso la versión de la librería libstdc++.so probablemente será superior.
El caso especial C++11 (y C++14)
Aunque GCC (o más específicamente libstdc++) trata en la medida de lo posible de garantizar la estabilidad del ABI, esta garantía no se extiende a todas las partes de C++ dentro de libstdc++. Formalmente en las versiones a partir de la 3.4, GCC/libstdc++ únicamente garantiza la estabilidad del ABI de C++98/C++03 y ninguno más. Esto es crucial para los paquetes que dependen de C++11. GCC únicamente garantiza la estabilidad del ABI de C++11 a partir de la versión 5.1. Esto implica que el cambio (aunque sea mínimo) en una versión de gcc (digamos de la 4.7.3 a la 4.7.4) puede causar la ruptura del ABI para los binarios que se han construido con código de C++11.
Para obtener más información y ver algunos ejemplos, echar un vistazo a:
- 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
Downgrading GCC
For the aforementioned reasons, if downgrading GCC or choosing an older slot with gcc-config, it is necessary to run revdep-rebuild to catch libstdc++
consumers requiring newer symbols:
root #
revdep-rebuild --library 'libstdc++.so.6' -- --exclude gcc
¿Qué paquetes se sabe que deben reconstruirse?
La siguiente tabla indica los paquetes que si se instalan, se necesitarán reconstruir y el motivo por el cual se necesitan reconstruir.
Paquete | La reconstrucción es necesaria debido a ... |
---|---|
sys-devel/libtool | La aplicación libtool tiene las rutas definidas de forma inamovible hacia librerías internas de GCC |
sys-devel/llvm | Depende de la versión exacta de gcc, pueden aparecer errores en el enlazado con otros ebuilds que hagan uso de LLVM (por ejemplo media-libs/mesa) si no se reconstruye |
sys-devel/clang | Dependiendo de la versión exacta de gcc puede verse afectado por sys-devel/llvm. |
root #
emerge --ask --oneshot --usepkg=n --verbose sys-devel/libtool sys-devel/llvm sys-devel/clang
Algunas colecciones de paquetes deben construirse con el mismo compilador (por ejemplo, los distintos paquetes qt-*). Por lo general, los mantenedores de paquetes actualizan estos paquetes simultáneamente, por lo que siempre se compilarán con la misma versión de GCC. Las reinstalaciones selectivas de estos paquetes pueden resultar problemáticas.
Reconstruyendo todo
Algunos juran que al aparecer una nueva versión de GCC, se debe reconstruir hasta el último paquete del sistema. Por supuesto, esto no tiene sentido, ya que de todas formas hay muchas aplicaciones que no usan GCC en su proceso de construcción e instalación y por tanto nunca serían afectados por estos cambios.
This isn't necessary but is described here so people know how to do it thoroughly if they desire.
Some people swear that they need to rebuild every single package on their system when a new GCC version is made available. Of course, that doesn't make sense, since there are many applications that are not using GCC for their build and install process anyhow, so they would never be affected by such changes.
Sin embargo, esto no significa que estén completamente equivocados: las versiones recientes de GCC suelen incluir soporte mejorado para los conjuntos de instrucciones de los procesadores, lo que podría influir en el desempeño de algunas aplicaciones positivamente.
Aparte de estos benificios "benignos", reconstruir todo desde cero puede ser necesario en algunos casos para corregir problemas que no paracen tener ninguna causa obvia.
Algunos problemas de software son intrínsecamente difíciles de diagnosticar y, sin embargo, podrían resolverse simplemente reconstruyendo uno o más paquetes apropiados. Si tal problema ha surgido después de una actualización de GCC y persiste después de usar el método revdep-rebuild descrito anteriormente (y después de reconstruir cualquier otro paquete obviamente relevante), una reconstrucción completa del sistema puede ser la respuesta.
La forma más "segura" (pero también que consume más tiempo) de lograr esto es usar la opción --emptytree
(-e
) de emerge para reconstruir el conjunto system y luego el conjunto world:
root #
emerge --ask --emptytree --usepkg=n @system
root #
emerge --ask --emptytree --usepkg=n @world
Se recomienda encarecidamente a los usuarios que lo intenten de esta forma antes de informar de problemas que podrían ser causados por la actualización de GCC.
(Tenga en cuenta que los comandos anteriores harán que los paquetes en el conjunto "system" se reconstruyan dos veces, lo cual es necesario para estar absolutamente seguro de que todos los paquetes se compilan en el mismo entorno [presumiblemente] "libre de problemas". Cualquier problema que persista después de hacer esto se debe a "auténticos errores" que deben informarse o a una configuración deficiente del sistema).
Resolución de problemas
Reconstruir boost
Si se necesita reconstruir el paquete dev-libs/boost, se obtendrá el siguiente mensaje:
root #
emerge ...
checking for the Boost _____ library... no configure: error: cannot find the flags to link with Boost _____
Se puede reconstruir con:
root #
emerge --ask --oneshot --usepkg=n --verbose dev-libs/boost
libstdc++.so.6: version `GLIBCXX_3.4.15' not found
Durante las actualizaciones puede que obtenga un error como el siguiente:
cmake_bootstrap_28021_test: /usr/lib/gcc/i486-pc-linux-gnu/4.1.2/libstdc++.so.6:
version `GLIBCXX_3.4.11' not found
Esto significa que está intentando construir un paquete con una versión de GCC que es más antigua que la usada para construir algunas de sus librerías dependientes. ¿Recuerde cuando dijimos que el ABI C++ era compatible a futuro? Esto es cierto, pero segura solamente que versiones más recientes (o iguales) de GCC se pueden utilizar para construir aplicaciones y librerías enlazadas (en comparación con la versión de GCC usada para construir esas librerías).
Para reconstruir todos los paquetes que dependen de libstdc++, echar un vistazo a las instrucciones dadas por revdep-rebuild indicadas arriba.
undefined reference to `__cxa_call_terminate@CXXABI_1.3.15'
This is usually a result of compiling a package that had its dependencies built with a newer GCC version than with the current one selected. An example output might be:
/usr/lib/gcc/x86_64-pc-linux-gnu/13/../../../../x86_64-pc-linux-gnu/bin/ld: /usr/lib64/libgtest.so: undefined reference to `__cxa_call_terminate@CXXABI_1.3.15'
What this means is the package that is emerging is building with, for example, GCC 13 but the package that provides libgtest.so
was built with a newer version of GCC, 14 in this case.
The solution to this problem is rather simple but can be hard to figure out if the package providing the file is unknown. Portage supports emerging file paths directly so running emerge -1 /path/to/file.so might detect the file.
In the example, try emerging /usr/lib64/libgtest.so
root #
emerge -1a /usr/lib64/libgtest.so
Calculating dependencies - !!! '/usr/lib/libgtest.so' is not claimed by any package. ... done!
Unfortunately the file needed was not claimed, but another utility exists to find files installed by packages, Pfl. Using e-file, it is possible to find the package that installs the needed file.
user $
e-file libgtest.so
... [I] dev-cpp/gtest Seen Versions: 1.13.0 1.14.0 Portage Versions: 1.13.0 1.14.0 9999 Installed Versions: 1.14.0(Fri Nov 24 04:35:00 2023) Homepage: https://github.com/google/googletest Description: Google C++ Testing Framework Matched Files: /usr/lib/libgtest.so; /usr/lib64/libgtest.so ...
In this case, dev-cpp/gtest is causing the build issue, re-merging it with:
root #
emerge --ask --oneshot dev-cpp/gtest
should fix the issue and allow the continuation of emerging the original package.
For larger packages, it is likely to encounter this more than once while rebuilding a package with a lower version of GCC, keep following the above steps to eventually succeed in recompiling the package with GCC 13
Ver también
- Actualizar GCC hasta la versión 4.1, la versión anterior a este documento.
- Actualizar de gcc-4.x a gcc-5.x
- Página Wiki 'Changes/GCC6' de Fedora
External resources
- https://gcc.gnu.org/onlinedocs/gcc.pdf - Using the GNU Compiler Collection PDF.
- https://gcc.gnu.org/onlinedocs/gccint.pdf - GNU Compiler Collection Internals PDF.