Come scegliere la versione predefinita di gcc e g ++?


206

Quindi ho installato gcc-4.4 e gcc-4.3 (lo stesso per g ++). Ora, per quanto mi ricordo, c'è uno strumento in Ubuntu che imposta i collegamenti simbolici per te se gli dici semplicemente quale versione vuoi. Tuttavia non sembra funzionare nella versione più recente, che trovo deludente.

root@nexus:~# update-alternatives --config gcc
update-alternatives: error: no alternatives for gcc.
root@nexus:~# update-alternatives --config cc
There is only one alternative in link group cc: /usr/bin/gcc
Nothing to configure.


root@nexus:~# dpkg -l | grep gcc | awk '{print $2}'
gcc
gcc-4.3
gcc-4.3-base
gcc-4.3-multilib
gcc-4.4
gcc-4.4-base
gcc-4.4-multilib
gcc-4.5-base
gcc-multilib
lib32gcc1
libgcc1

Qualche idea?


1
Come ha spiegato @Oli, questa è una cattiva idea. Elenco di posta Debian-devel: "Non credo che le alternative debbano essere usate per il controllo delle versioni. Ad esempio, non usiamo alternative per gcc, né per Python." lists.debian.org/debian-devel/2014/06/msg00381.html
hmijail

1
OK, così che cosa fai che si utilizza per il controllo delle versioni?
WillC,

Risposte:


271

Per prima cosa abbiamo cancellato la configurazione delle alternative di aggiornamento correnti per gcc e g ++:

sudo update-alternatives --remove-all gcc 
sudo update-alternatives --remove-all g++

Installa i pacchetti

Sembra che sia gcc-4.3 che gcc-4.4 siano installati dopo l'installazione build-essential. Tuttavia, possiamo installare esplicitamente i seguenti pacchetti:

sudo apt-get install gcc-4.3 gcc-4.4 g++-4.3 g++-4.4

Installa alternative

I collegamenti simbolici cc e c ++ sono installati per impostazione predefinita. Installeremo i collegamenti dei simboli per gcc e g ++, quindi collegeremo cc e c ++ rispettivamente a gcc e g ++. (Nota che le opzioni 10, 20e 30sono le priorità per ogni alternativa.)

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.3 10
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.4 20

sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.3 10
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.4 20

sudo update-alternatives --install /usr/bin/cc cc /usr/bin/gcc 30
sudo update-alternatives --set cc /usr/bin/gcc

sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 30
sudo update-alternatives --set c++ /usr/bin/g++

Configura alternative

L'ultimo passaggio è la configurazione dei comandi predefiniti per gcc, g ++. È facile passare tra 4.3 e 4.4 in modo interattivo:

sudo update-alternatives --config gcc
sudo update-alternatives --config g++

O passa usando lo script:

#!/bin/sh

if [ -z "$1" ]; then
    echo "usage: $0 version" 1>&2
    exit 1
fi

if [ ! -f "/usr/bin/gcc-$1" ] || [ ! -f "/usr/bin/g++-$1" ]; then
    echo "no such version gcc/g++ installed" 1>&2
    exit 1
fi

update-alternatives --set gcc "/usr/bin/gcc-$1"
update-alternatives --set g++ "/usr/bin/g++-$1"

4
Grazie, quindi è necessario aggiungerli manualmente alle alternative di aggiornamento. Le versioni precedenti di Ubuntu di IIRC lo hanno fatto automaticamente.
Nils,

1
Questo è particolarmente utile per me durante la compilazione di moduli nvidia per kernel diversi. Grazie mille per aver spiegato le alternative di aggiornamento
earthmeLon

1
Grazie! Ho usato l'altra tua risposta per aggiornare dalla 4.6 alla 4.7. Volevo usare questa risposta, ma non ero sicuro del perché metti numeri come 10 20 30 dopo alcuni di voi comandi. Potresti spiegare per favore?
Martin Drozdik,

7
I numeri sono priorità come risulta, secondo la pagina di manuale. Immagino che nel caso in cui una versione venga disinstallata, verranno utilizzate quelle priorità per determinare quale dovrebbe diventare la nuova impostazione predefinita.
Ibrahim,

1
@Ibrahim: No, determinano ciò che viene scelto quando si seleziona la modalità automatica
Cookie

41

eseguire nel terminale:

gcc -v
g++ -v

Va bene, quindi quella parte è abbastanza semplice. La parte difficile è che quando si emette il comando GCC è in realtà un collegamento sbolico a quale versione di GCC si sta utilizzando. Ciò significa che possiamo creare un collegamento simbolico da GCC a qualsiasi versione di GCC che desideriamo.

  • Puoi vedere il link simbolico:
ls -la /usr/bin | grep gcc-4.4
ls -la /usr/bin | grep g++-4.4
  • Quindi quello che dobbiamo fare è rimuovere il symlink GCC e il symlink G ++ e quindi ricrearli collegati a GCC 4.3 e G ++ 4.3:
rm /usr/bin/gcc
rm /usr/bin/g++

ln -s /usr/bin/gcc-4.3 /usr/bin/gcc
ln -s /usr/bin/g++-4.3 /usr/bin/g++
  • Ora se controlliamo di nuovo i collegamenti simbolici vedremo che GCC e G ++ sono ora collegati a GCC 4.3 e G ++ 4.3:
ls -la /usr/bin/ | grep gcc
ls -la /usr/bin/ | grep g++
  • Finalmente possiamo controllare di nuovo il nostro GCC -v e assicurarci di usare la versione corretta:
gcc -v
g++ -v

1
Esattamente quello che stavo cercando! Ho dimenticato la possibilità di collegare simbolicamente "gcc" a qualsiasi versione che ho installato. Grazie!
CalebHC

metodo più semplice, più semplice e più sicuro!
sailfish009

21

È davvero desiderabile? Ci sono cambiamenti ABI tra le gccversioni. Compilare qualcosa con una versione (ad es. L'intero sistema operativo) e quindi compilare qualcos'altro con un'altra versione, può causare conflitti.

Ad esempio, i moduli del kernel devono sempre essere compilati con la stessa versione gccutilizzata per compilare il kernel. Con questo in mente, se hai modificato manualmente il collegamento simbolico tra /usr/bin/gcce la versione utilizzata nella tua versione di Ubuntu, i futuri moduli DKMS potrebbero utilizzare la gccversione sbagliata .

Se vuoi solo costruire cose con una versione diversa di gcc, è abbastanza facile, anche con i makescripts. Ad esempio, puoi passare la versione gccnella CCvariabile d'ambiente:

CC="gcc-4.5" ./configure
CC="gcc-4.5" make

Potresti non averne bisogno sul comando make (gli script di configurazione solitamente lo inseriscono) ma non fa male.


1
Grazie per il tuo commento. Sono a conoscenza della variabile CC, ma non era proprio questa la domanda.
Nils,

2
Abbastanza vero, ma ho spiegato perché gccnon fa parte del alternativessistema e perché questo non è particolarmente desiderabile. Se nessuno di questi cambierà idea, fallo manualmente.
Oli

1
Era prima? Ora l'hanno appena rimosso ?! Il software di compilazione (userspace) con diverse versioni di gcc dovrebbe essere perfettamente ok .. questa discussione si sta facendo strada ..
Nils,

1
Puoi spiegare perché le variabili di ambiente per invocazione sono preferibili a un'impostazione di configurazione a livello di sistema? $ sudo apt-get install gcc-6 gcc-7 $ CC="gcc-7" ./configure <much output> $ make # uses gcc-7 Considerando che sudo update-alternatives gcc gcc-7avrebbe fatto in modo di non cambiare accidentalmente ABI.
kfsone,

14

Modificare:

Ciò presuppone che tu abbia installato prima la versione, ad esempio con:

sudo apt install gcc-4.9 g++-4.9

Originale:

Ed ecco un one-liner per coloro che sono pigri, basta cambiare il numero alla fine per la versione desiderata. Apporterà la modifica per gcc e / o g ++

ls -la /usr/bin/ | grep -oP "[\S]*(gcc|g\+\+)(-[a-z]+)*[\s]" | xargs bash -c 'for link in ${@:1}; do sudo ln -s -f "/usr/bin/${link}-${0}" "/usr/bin/${link}"; done' 4.9

In questo esempio sono passato a 4.9

Non ci sono controlli di errore e cosa non in questo esempio, quindi potresti voler controllare cosa verrà eseguito prima di eseguirlo. Aggiungi l' eco prima di sudo . Per completezza fornisco anche la linea di controllo:

ls -la /usr/bin/ | grep -oP "[\S]*(gcc|g\+\+)(-[a-z]+)*[\s]" | xargs bash -c 'for link in ${@:1}; do echo sudo ln -s -f "/usr/bin/${link}-${0}" "/usr/bin/${link}"; done' 4.9

L'output del controllo dovrebbe essere simile a:

sudo ln -s -f /usr/bin/g++-4.9 /usr/bin/g++
sudo ln -s -f /usr/bin/gcc-4.9 /usr/bin/gcc
sudo ln -s -f /usr/bin/gcc-ar-4.9 /usr/bin/gcc-ar
sudo ln -s -f /usr/bin/gcc-nm-4.9 /usr/bin/gcc-nm
sudo ln -s -f /usr/bin/gcc-ranlib-4.9 /usr/bin/gcc-ranlib
sudo ln -s -f /usr/bin/x86_64-linux-gnu-g++-4.9 /usr/bin/x86_64-linux-gnu-g++
sudo ln -s -f /usr/bin/x86_64-linux-gnu-gcc-4.9 /usr/bin/x86_64-linux-gnu-gcc
sudo ln -s -f /usr/bin/x86_64-linux-gnu-gcc-ar-4.9 /usr/bin/x86_64-linux-gnu-gcc-ar
sudo ln -s -f /usr/bin/x86_64-linux-gnu-gcc-nm-4.9 /usr/bin/x86_64-linux-gnu-gcc-nm
sudo ln -s -f /usr/bin/x86_64-linux-gnu-gcc-ranlib-4.9 /usr/bin/x86_64-linux-gnu-gcc-ranlib

Puoi controllare la versione dopo con:

gcc --version

Spiegazione semi-dettagliata:

  • ls -la / usr / bin / elenca tutti i file in / usr / bin
  • | reindirizza (invia) l'output al comando successivo
  • grep -oP corrisponde alla regex di ricerca per riga. o mostra solo il risultato, non l'intera linea abbinata. P dice a grep di usare perl-regex. Non entrerò in regex qui, leggilo se vuoi.
  • xargs semplicemente, raccoglie i risultati che vengono inviati ad esso e li invia tutti alla fine. cioè al comando che segue xargs
  • bash bene, è bash. Il flag c gli dice di usare la stringa come comando. In questo esempio passa in rassegna gli argomenti inviati da xargs saltando il primo (0 °) argomento, in questo caso il ciclo salta 4.9 . Il 0 ° argomento viene utilizzato nel ciclo per modificare il collegamento.
  • ln -s -f Il s bandiera effettua un collegamento simbolico, f forze scollegamento primo luogo se necessario.

2
Domanda molto vecchia, ma questa risposta sembra essere una delle gemme che dovremmo cercare quando si esaminano le risposte ai vecchi post ...
mook765,

Brillante! La migliore risposta senza dubbio!
Gabriel Staples,

-1

Che ne dici di un link simbolico in una directory temporanea:

mkdir x && PATH=$PWD/x:$PATH && ln -s /usr/bin/g++-7 $PWD/x/g++


Devo ammetterlo: questa è una risposta eccellente.
user643722
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.