Comment choisir la version par défaut de gcc et g ++?

206

J'ai donc installé gcc-4.4 et gcc-4.3 (idem pour g ++). Pour autant que je m'en souvienne, il existe un outil dans Ubuntu qui définit les liens symboliques pour vous si vous lui indiquez simplement la version de votre choix. Cependant, cela ne semble pas fonctionner dans la nouvelle version, ce qui me déçoit.

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

Des idées?

Nils
la source
1
Comme @Oli l'a expliqué, c'est une mauvaise idée. Liste de diffusion Debian-devel: "Je ne pense pas que des alternatives devraient être utilisées pour la gestion des versions. Par exemple, nous n'utilisons pas d'alternatives pour gcc, ni pour Python." lists.debian.org/debian-devel/2014/06/msg00381.html
hmijail
1
OK, qu'utilisez - vous pour la gestion des versions?
WillC

Réponses:

271

D'abord effacé la configuration actuelle des alternatives de mise à jour pour gcc et g ++:

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

Installer des paquets

Il semble que gcc-4.3 et gcc-4.4 sont tous deux installés après l'installation de build-essential. Cependant, nous pouvons installer explicitement les packages suivants:

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

Installer des alternatives

Les liens symboliques cc et c ++ sont installés par défaut. Nous installerons les liens de symboles pour gcc et g ++, puis lierons cc et c ++ à gcc et g ++ respectivement. (Notez que les options 10, 20et 30sont les priorités de chaque alternative.)

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++

Configurer les alternatives

La dernière étape consiste à configurer les commandes par défaut pour gcc, g ++. Il est facile de basculer de manière interactive entre 4.3 et 4.4:

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

Ou passez en utilisant le 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"
hhlp
la source
4
Thx, vous devez donc les ajouter manuellement pour mettre à jour des alternatives. Les versions antérieures d'IIPR Ubuntu le faisaient automatiquement.
Nils
1
Cela m’est particulièrement utile lors de la compilation de modules nvidia pour différents noyaux. Merci beaucoup d'avoir expliqué les alternatives de mise à jour
earthmeLon
1
Je vous remercie! J'ai utilisé votre autre réponse pour mettre à jour de 4.6 à 4.7. Je voulais utiliser cette réponse, mais je ne savais pas trop pourquoi vous mettez des chiffres comme 10 20 30 après certaines de vos commandes. Pourriez-vous s'il vous plaît expliquer?
Martin Drozdik
7
Selon la page de manuel, les chiffres sont prioritaires. J'imagine que dans le cas où l'une des versions est désinstallée, elle utilisera ces priorités pour déterminer celle qui doit devenir la nouvelle valeur par défaut.
Ibrahim
1
@ Ibrahim: Non, ils déterminent ce qui est choisi lorsque vous sélectionnez le mode automatique
Cookie
41

exécuter dans le terminal:

gcc -v
g++ -v

Ok, donc cette partie est assez simple. La difficulté réside dans le fait que lorsque vous exécutez la commande GCC, il s’agit en réalité d’un lien sybolique vers la version de GCC que vous utilisez. Cela signifie que nous pouvons créer un lien symbolique de GCC vers la version de GCC de notre choix.

  • Vous pouvez voir le lien symbolique:
ls -la /usr/bin | grep gcc-4.4
ls -la /usr/bin | grep g++-4.4
  • Nous devons donc supprimer le lien symbolique GCC et le lien symbolique G ++, puis les recréer liés à GCC 4.3 et 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++
  • Maintenant, si nous vérifions à nouveau les liens symboliques, nous verrons que GCC et G ++ sont maintenant liés à GCC 4.3 et G ++ 4.3:
ls -la /usr/bin/ | grep gcc
ls -la /usr/bin/ | grep g++
  • Enfin, nous pouvons vérifier à nouveau notre GCC -v et nous assurer que nous utilisons la version correcte:
gcc -v
g++ -v
hhlp
la source
1
Exactement ce que je cherchais! Oublié la possibilité de faire un lien symbolique "gcc" avec la version que j'ai installée. Merci!
CalebHC
méthode plus simple et plus facile et plus sûre!
sailfish009
21

Est-ce vraiment souhaitable? Il y a des changements ABI entre les gccversions. Compiler quelque chose avec une version (par exemple l’ensemble du système d’exploitation) puis compiler quelque chose d’autre avec une autre version peut être source de conflit.

Par exemple, les modules du noyau doivent toujours être compilés avec la même version que celle gccutilisée pour compiler le noyau. Dans cet esprit, si vous modifiez manuellement le lien symbolique entre /usr/bin/gccla version utilisée dans votre version d'Ubuntu et la version utilisée par celle-ci, les futurs modules construits par DKMS pourraient utiliser une gccversion incorrecte .

Si vous voulez juste construire des choses avec une version différente de gcc, c'est assez facile, même avec des scripts. Par exemple, vous pouvez transmettre la version de gccdans la CCvariable d’environnement:

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

Vous n’avez peut-être pas besoin de cela dans la commande make (les scripts de configuration le tirent habituellement) mais cela ne fait pas de mal.

Oli
la source
1
Merci pour votre commentaire. Je suis conscient de la variable CC, mais ce n'était pas vraiment la question.
Nils
2
C'est assez vrai, mais j'ai expliqué pourquoi il gccne fait pas partie du alternativessystème et pourquoi cela n'est pas particulièrement souhaitable. Si aucun de ceux-ci ne va changer d'avis, faites-le simplement manuellement.
Oli
1
C'était avant? Maintenant, ils viennent de l'enlever?! Compiler (un espace utilisateur) un logiciel avec différentes versions de gcc devrait parfaitement se dérouler .. cette discussion est de plus en plus sombre ..
Nils
1
Pouvez-vous expliquer pourquoi les variables d'environnement par appel sont préférables à un paramètre de configuration à l'échelle du système? $ sudo apt-get install gcc-6 gcc-7 $ CC="gcc-7" ./configure <much output> $ make # uses gcc-7 Considérant sudo update-alternatives gcc gcc-7que vous auriez fait en sorte de ne pas changer accidentellement d’ABI.
kfsone
14

Modifier:

Cela suppose que vous ayez d'abord installé la version, avec par exemple:

sudo apt install gcc-4.9 g++-4.9

Original:

Et voici une ligne pour ceux qui sont paresseux, il suffit de changer le numéro à la fin pour obtenir la version souhaitée. Cela fera le changement pour gcc et / ou 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

Dans cet exemple, je suis passé à 4.9

Il n'y a pas de vérification d'erreur et ce qui n'est pas dans cet exemple, vous voudrez peut-être vérifier ce qui sera exécuté avant de l'exécuter. Ajoutez juste echo avant sudo . Par souci d'exhaustivité, je fournis également une ligne de contrôle:

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

Le résultat de la vérification devrait être quelque chose comme:

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

Vous pouvez vérifier la version après avec avec:

gcc --version

Explication semi-détaillée:

  • ls -la / usr / bin / répertorie tous les fichiers de / usr / bin
  • | diriger (envoyer) la sortie vers la commande suivante
  • grep -oP correspond à l'expression rationnelle de recherche par ligne. o ne montre que le résultat, pas la totalité de la ligne correspondante. P dit à grep d'utiliser perl-regex. Je ne vais pas entrer dans l'expression régulière ici, lisez-le si vous le souhaitez.
  • xargs est simple: il rassemble les résultats qui y sont diffusés et les envoie tous à la fin. c'est-à-dire à la commande qui suit xargs
  • bash bien, c'est bash. L' indicateur c lui dit d'utiliser la chaîne en tant que commande. Dans cet exemple, il parcourt les arguments envoyés par xargs en ignorant le premier argument (0e), dans ce cas, la boucle ignore 4.9 . Le 0ème argument est utilisé dans la boucle pour changer le lien.
  • ln -s -f Le drapeau s établit un lien symbolique, f force la suppression de la liaison en premier si nécessaire.
Ale
la source
2
Très vieille question, mais cette réponse semble être l'un des joyaux que nous devrions rechercher lorsque nous examinons les réponses à d'anciens messages ...
mook765
Brillant! Meilleure réponse haut la main!
Gabriel Staples
-1

Que diriez-vous d'un lien symbolique dans un répertoire temporaire:

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

utilisateur643722
la source
Je dois admettre que c'est une excellente réponse.
user643722