Aggiornare 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.
Si prega di notare che effettuare il "downgrade" di GCC potrebbe avere degli effetti indesiderati. Riferisciti a troubleshooting per i problemi riportati di frequente
Quick guide to GCC upgrades
Molti aggiornamenti di GCC sono semplici come cambiare la versione del compilatore (qui dalla 5.4.0 alla 6.4.0) e ricompilare/ricostruire 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
Controllare la versione corrente e disinstallare la vecchia:
root #
gcc --version
root #
emerge --ask --depclean =sys-devel/gcc-5.4.0
Godetevi il nuovo compilatore!
Spiegazioni sull'aggiornamento di GCC
L'aggiornamento di GCC è sempre stato disorientato, con suggerimenti che vanno da "gli utenti non devono fare niente" a "gli utenti dovrebbero ricostruire l'intero sistema due volte". Molte paure, incertezze e dubbi vengono dalla confusione che circonda l'incompatibilità di ABI, una cosa che ai giorni nostri raramente succede (e quando succede, verrà annunciata). Ma prima di tutto diamo uno sguardo veloce a libtool.
libtool
La ragione per cui noi dobbiamo ricostruire/ricompilare libtool dopo l'aggiornamento della versione di gcc è causato dal suo scopo principale: "libtool" è un set di attrezzi che aggregano codici specifici della piattaforma in una interfaccia generale, permettendo alle applicazioni di compilare contro le librerie condivise senza dover affrontare gli aspetti specifici della piattaforma delle librerie condivise. Per svolgere correttamente la sua funzione, la libtool script utilizza varie locazioni di libreria che hanno hard-coded informazioni sulla versione di gcc dentro di loro.
See bug #88596.
ABI changes
Cambiamenti ABI
Un ABI, o Application Binary Interface (Interfaccia Binaria dell'Applicazione), è un set di convenzioni usate da tutti i tool che si occupano della rappresentazione binaria dei programmi, includendo compilatori, assemblers, linkers, e supporto per il language runtime (source: GCC Binary Compatibility). Quando l'ABI utilizzato per le applicazioni binarie e le librerie viene modificato, rischierai di ottenere errori di linker o programmi malfunzionanti a meno che tu non ricostruisca tutte le librerie che usano il codice C++.
Sì, C++, poiché la maggior parte delle incompatibilità si verificano all'interno dell'ABI C++. Se stai aggiornando da GCC 4.1 o GCC 5.1, probabilmente incontreresti problemi con l'ABI. Per prevenire questo, il comando revdep-rebuild dovrebbe essere eseguito contro la libreria libstdc++.so.5 quando aggiornando da GCC 3 a GCC 4.1, o libstdc++.so.6 quando aggiornando da GCC 4 a GCC 5.1.
root #
revdep-rebuild --library 'libstdc++.so.6' -- --exclude gcc
Allora perché è necessario solo con GCC 4.1/5.1? Questo perché da quella versione in poi, GCC usa una forward-compatible ABI, che rimuove la necessità di ricostruire/ricompilare le applicazioni e le librerie. Ovviamente, le garanzie non possono mai essere date a tempo indeterminato, ma quando una incompatibilità avviene di nuovo, lo documenteremo sicuramente qui e pubblicheremo una notizia. In questo caso, la versione della libreria libstdc++.so sarà probabilmente incrementata.
Il caso speciale di C++11 (e C++14)
Mentre GCC (o più specificamente, libstdc++) fa di tutto per garantire la stabilità dell'ABI, questa garanzia non si estende a tutte le parti di C++ all'interno di libstdc++. Formalmente, con le versioni a partire dalla 3.4, GCC/libstdc++ garantisce solo stabilità ABI C++98/C++03 e non di più. Questo è cruciale per pacchetti che dipendono su C++11. GCC fornisce solo garanzie di stabilità ABI C++ 11 a partire dalla versione 5.1. Ciò significa che il passaggio di versioni (anche minori) di gcc (ad esempio 4.7.3 -> 4.7.4) potrebbe causare la rottura di ABI per i binari compilati dal codice C++11.
Per ulteriori informazioni e alcuni esempi, vedere:
- 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
Quali pacchetti sono noti per aver bisogno di una ricostruzione?
La tabella seguente fornisce i pacchetti che, se installati, devono essere ricostruiti e perché.
Pacchetto | Ricompilazione necessaria perché ... |
---|---|
sys-devel/libtool | libtool ha percorsi codificati verso le librerie interne di GCC. |
sys-devel/llvm | dipende dalla versione esatta di gcc, potrebbe verificarsi errori di collegamento con altri ebuild che utilizzano LLVM (ad es. media-libs/mesa) se non ricostruito. |
sys-devel/clang | a seconda della versione esatta di gcc, potrebbe essere influenzato da sys-devel/llvm. |
root #
emerge --ask --oneshot --usepkg=n --verbose sys-devel/libtool sys-devel/llvm sys-devel/clang
Qualche collezione di pacchetti necessita di essere costruita/compilata con lo stesso compilatore (per esempio, i vari pacchetti qt-*). Questi pacchetti sono solitamente aggiornati simultaneamente dai mantenitori dei pacchetti, quindi saranno sempre compilati con la stessa versione di GCC. Re-installazioni cherry-picking su questi pacchetti potrebbero rivelarsi problematiche.
Ricostruire/Ricompilare tutto
Alcune persone giurano di dover ricostruire ogni singolo pacchetto sul proprio sistema quando viene resa disponibile una nuova versione di GCC. Ovviamente, questo non ha senso, poiché ci sono molte applicazioni che non utilizzano GCC per il processo di costruzione/compilazione e installazione in ogni caso, quindi non sarebbero mai stati interessati da tali cambiamenti.
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.
Ciò, tuttavia, non significa che siano completamente errati: nuove versioni di GCC spesso includono un miglior supporto per le Instruction set del processore, che potrebbero influenzare positivamente le prestazioni di alcune applicazioni.
A parte tali benefici, ricostruire/ricompilare tutto da capo potrebbe essere necessario in qualche caso per correggere problemi che non sembrerebbero avere una causa evidente.
Alcuni problemi software sono intrinsecamente difficili da diagnosticare e tuttavia potrebbero essere risolti semplicemente ricostruendo uno o più pacchetti appropriati. Se un tale problema è sorto a seguito di un aggiornamento GCC e persiste dopo aver utilizzato l'approccio revdep-rebuild descritto sopra (e dopo aver ricostruito qualsiasi altro pacchetto ovviamente rilevante), una ricostruzione/ricompilazione completa del sistema potrebbe essere la risposta.
Il modo "più sicuro" (ma anche più dispendioso in termini di tempo) per farlo è usare l'opzione --emptytree
(-e
) di emerge per ricompilare/ricostruire il system set e quindi il world set:
root #
emerge --ask --emptytree --usepkg=n @system
root #
emerge --ask --emptytree --usepkg=n @world
Gli utenti sono invitati a provare questo approccio prima di segnalare eventuali bug che potrebbero essere stati causati da un aggiornamento GCC.
(Nota che i comandi sopra faranno sì che i pacchetti nel set "sistema" vengano ricostruiti/ricompilati due volte, che è necessario per essere "assolutamente certi" che ogni pacchetto venga compilato nello stesso ambiente [presumibilmente] "senza problemi". Eventuali problemi che rimangono dopo aver fatto ciò sono dovuti a "bug originali" che dovrebbero essere segnalati o a una cattiva configurazione del sistema.)
Risoluzione dei problemi
ricostruzione del boost
Se dev-libs/boost necessita di essere ricostruito/ricompilato, si riceverà il seguente messaggio di errore:
root #
emerge ...
checking for the Boost _____ library... no configure: error: cannot find the flags to link with Boost _____
Si può ricostruire con:
root #
emerge --ask --oneshot --usepkg=n --verbose dev-libs/boost
libstdc++.so.6: versione `GLIBCXX_3.4.15' non trovata
Durante gli aggiornamenti, potresti riscontrare un errore come il seguente:
cmake_bootstrap_28021_test: /usr/lib/gcc/i486-pc-linux-gnu/4.1.2/libstdc++.so.6:
version `GLIBCXX_3.4.11' not found
Ciò significa che stai cercando di costruire/compilare un pacchetto con una versione GCC "vecchia" rispetto a quella con cui sono state create alcune librerie dipendenti. Ricordi quando abbiamo detto che l'ABI C++ è forward-compatible? Questo è vero, ma garantisce solo che le versioni GCC "più recenti" (o uguali) possano essere utilizzate durante la costruzione/compilazione di applicazioni e il collegamento di librerie (rispetto alla versione GCC utilizzata per creare tali librerie).
Per ricostruire tutti i pacchetti che dipendono da libstdc++, vedere le istruzioni per revdep-rebuild sopra
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
Vedere anche
- Upgrade GCC up to 4.1, la versione precedente di questo documento
- Upgrading from gcc-4.x to gcc-5.x
- Fedora 'Changes/GCC6' Wiki Page
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.