Como escolher a versão padrão do gcc e g ++?

206

Então eu instalei o gcc-4.4 e o gcc-4.3 (o mesmo para o g ++). Agora, tanto quanto me lembro, existe uma ferramenta no Ubuntu que define os links simbólicos para você, se você apenas disser qual versão deseja. No entanto, ele não parece funcionar na versão mais recente, o que acho decepcionante.

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

Alguma ideia?

Nils
fonte
11
Como o @Oli explicou, esta é uma má ideia. Lista de e-mail do Debian-devel: "Não acho que alternativas devam ser usadas para versionamento. Por exemplo, não usamos alternativas para o gcc, nem para o Python." lists.debian.org/debian-devel/2014/06/msg00381.html
hmijail
11
OK, então o que você usa para versionar?
WillC

Respostas:

271

Primeiro, apagou a configuração atual de alternativas de atualização para gcc e g ++:

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

Instalar pacotes

Parece que o gcc-4.3 e o gcc-4.4 são instalados após a instalação essencial da compilação. No entanto, podemos instalar explicitamente os seguintes pacotes:

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

Instalar alternativas

Os links simbólicos cc e c ++ são instalados por padrão. Instalaremos links de símbolos para gcc e g ++ e, em seguida, vincularemos cc e c ++ a gcc e g ++, respectivamente. (Note que a 10, 20e 30as opções são as prioridades para cada 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++

Configurar alternativas

A última etapa é configurar os comandos padrão para gcc, g ++. É fácil alternar entre 4,3 e 4,4 interativamente:

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

Ou alterne usando o 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
fonte
4
Thx, então você precisa adicioná-los manualmente para atualizar as alternativas. As versões anteriores do IIRC do Ubuntu faziam isso automaticamente.
Nils
11
Isso é especialmente útil para mim ao compilar módulos da nvidia para diferentes kernels. Muito obrigado por explicar update-alternatives
earthmeLon
11
Obrigado! Eu usei sua outra resposta para atualizar de 4.6 para 4.7. Eu queria usar esta resposta, mas não sabia ao certo por que você coloca números como 10 20 30 após alguns de vocês comandarem. Você poderia explicar?
Martin Drozdik
7
Os números são prioridades, de acordo com a página de manual. Imagino que no caso de uma das versões ser desinstalada, essas prioridades serão usadas para determinar qual delas deve se tornar o novo padrão.
Ibrahim
11
@Ibrahim: Não, eles determinam o que é escolhido quando você seleciona o modo automático
Cookies
41

executar no terminal:

gcc -v
g++ -v

Ok, então essa parte é bastante simples. A parte complicada é que, quando você emite o comando GCC, na verdade é um link simbólico para qualquer versão do GCC em uso. O que isso significa é que podemos criar um link simbólico do GCC para a versão que desejamos.

  • Você pode ver o link simbólico:
ls -la /usr/bin | grep gcc-4.4
ls -la /usr/bin | grep g++-4.4
  • Portanto, o que precisamos fazer é remover o link simbólico do GCC e o link simbólico do G ++ e, em seguida, recriá-los vinculados ao GCC 4.3 e ao 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++
  • Agora, se verificarmos novamente os links simbólicos, veremos que o GCC e o G ++ estão agora vinculados ao GCC 4.3 e ao G ++ 4.3:
ls -la /usr/bin/ | grep gcc
ls -la /usr/bin/ | grep g++
  • Finalmente, podemos verificar nosso GCC -v novamente e garantir que estamos usando a versão correta:
gcc -v
g++ -v
hhlp
fonte
11
Exatamente o que eu estava procurando! Esqueci a capacidade de vincular "gcc" a qualquer versão que eu instalei. Obrigado!
CalebHC
método mais simples, fácil e seguro!
sailfish009 17/07
21

Isso é realmente desejável? Existem alterações ABI entre gccversões. Compilar algo com uma versão (por exemplo, todo o sistema operacional) e, em seguida, compilar algo com outra versão, pode causar conflito.

Por exemplo, os módulos do kernel devem sempre ser compilados com a mesma versão gccusada para compilar o kernel. Com isso em mente, se você alterou manualmente o link simbólico entre /usr/bin/gcce a versão usada na sua versão do Ubuntu, futuros módulos criados pelo DKMS podem usar a gccversão errada .

Se você apenas deseja criar coisas com uma versão diferente gcc, isso é fácil, mesmo com makecripts. Por exemplo, você pode passar na versão do gccna CCvariável de ambiente:

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

Você pode não precisar dele no comando make (os scripts de configuração geralmente o puxam), mas não faz mal.

Oli
fonte
11
Obrigado pelo seu comentário. Estou ciente da variável CC, mas essa não era realmente a questão.
Nils
2
É verdade, mas expliquei por que gccnão faz parte do alternativessistema e por que isso não é particularmente desejável. Se nenhum deles mudar de idéia, faça-o manualmente.
Oli
11
Foi antes? Agora eles apenas removeram ?! Compilando (userspace) software com diferentes versões do GCC deve ser perfeitamente ok .. essa discussão está ficando peitoril ..
Nils
11
Você pode explicar por que as variáveis ​​de ambiente por chamada são preferíveis a uma configuração do sistema? $ sudo apt-get install gcc-6 gcc-7 $ CC="gcc-7" ./configure <much output> $ make # uses gcc-7 Considerando sudo update-alternatives gcc gcc-7que teria garantido que você não alternasse acidentalmente as ABIs.
Kfsone
14

Editar:

Isso pressupõe que você instalou a versão primeiro, com, por exemplo:

sudo apt install gcc-4.9 g++-4.9

Original:

E aqui está uma linha para quem é preguiçoso, basta alterar, alterar o número no final para a versão desejada. Ele fará a alteração para gcc e / 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

Neste exemplo, mudei para 4.9

Não há verificações de erro e o que não está neste exemplo; portanto, convém verificar o que será executado antes de executá-lo. Basta adicionar eco antes do sudo . Para completar, também forneço linha de verificação:

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

A saída da verificação deve ser algo como:

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

Você pode verificar a versão depois com:

gcc --version

Explicação semi-detalhada:

  • ls -la / usr / bin / lista todos os arquivos em / usr / bin
  • | canalizar (enviar) a saída para o próximo comando
  • grep -oP corresponde ao regex de pesquisa por linha. o mostra apenas o resultado, não toda a linha correspondente. P diz ao grep para usar o perl-regex. Eu não vou entrar em regex aqui, leia se quiser.
  • xargs, simplesmente, reúne os resultados direcionados a ele e envia todos eles até o fim. ou seja, ao comando após xargs
  • bash bem, é bash. O sinalizador c diz para ele usar a string como um comando. Neste exemplo, ele faz um loop sobre os argumentos enviados a partir de xargs pulando o primeiro (0º) argumento; nesse caso, o loop ignora 4,9 . O argumento 0 é usado no loop para alterar o link.
  • ln -s -f O sinalizador s cria um link simbólico; f força a desvinculação primeiro, se necessário.
Ale
fonte
2
Questão muito antiga, mas esta resposta parece ser uma das jóias que deve procurar ao analisar respostas para posts antigos ...
mook765
Brilhante! Melhor resposta mãos para baixo!
Gabriel Staples
-1

Que tal um link simbólico em um diretório temporário:

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

user643722
fonte
Eu tenho que admitir: esta é uma excelente resposta.
user643722 25/09