¿Cómo elegir la versión predeterminada de gcc y g ++?

206

Así que instalé gcc-4.4 y gcc-4.3 (lo mismo para g ++). Ahora, hasta donde recuerdo, hay una herramienta en Ubuntu que establece los enlaces simbólicos para usted si solo le dice qué versión desea. Sin embargo, no parece funcionar en la versión más reciente, lo que me parece 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

¿Algunas ideas?

Nils
fuente
1
Como explicó @Oli, esta es una mala idea. Lista de correo de Debian-devel: "No creo que se deban usar alternativas para el control de versiones. Por ejemplo, no usamos alternativas para gcc, ni para Python". lists.debian.org/debian-devel/2014/06/msg00381.html
hmijail
1
OK, entonces, ¿ qué usas para versionar?
WillC

Respuestas:

271

Primero borró la configuración actual de alternativas de actualización para gcc y g ++:

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

Instalar paquetes

Parece que tanto gcc-4.3 como gcc-4.4 se instalan después de instalar build-essential. Sin embargo, podemos instalar explícitamente los siguientes paquetes:

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

Instalar alternativas

Los enlaces simbólicos cc y c ++ se instalan por defecto. Instalaremos enlaces de símbolos para gcc y g ++, luego uniremos cc y c ++ a gcc y g ++ respectivamente. (Tenga en cuenta que las opciones 10, 20y 30son las 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

El último paso es configurar los comandos predeterminados para gcc, g ++. Es fácil cambiar entre 4.3 y 4.4 de forma interactiva:

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

O cambie usando 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
fuente
44
Thx, por lo que debe agregarlos manualmente a las alternativas de actualización. Las versiones anteriores de IIRC de Ubuntu lo hicieron automáticamente.
Nils
1
Esto es especialmente útil para mí cuando compilo módulos nvidia para diferentes núcleos. Muchas gracias por explicar las alternativas de actualización
earthmeLon
1
¡Gracias! Utilicé su otra respuesta para actualizar de 4.6 a 4.7. Quería usar esta respuesta, pero no estaba seguro de por qué pones números como 10 20 30 después de algunos de tus comandos. ¿Podría explicar por favor?
Martin Drozdik
77
Los números son prioridades, según la página de manual. Me imagino que en el caso de que una de las versiones se desinstale, usará esas prioridades para determinar cuál debería convertirse en el nuevo valor predeterminado.
Ibrahim
1
@Ibrahim: No, determinan qué se elige cuando selecciona el modo automático
Cookie
41

ejecutar en terminal:

gcc -v
g++ -v

Bien, esa parte es bastante simple. La parte difícil es que cuando emite el comando GCC, en realidad es un enlace simbólico a cualquier versión de GCC que esté utilizando. Lo que esto significa es que podemos crear un enlace simbólico de GCC a la versión de GCC que queramos.

  • Puedes ver el enlace simbólico:
ls -la /usr/bin | grep gcc-4.4
ls -la /usr/bin | grep g++-4.4
  • Entonces, lo que debemos hacer es eliminar el enlace simbólico GCC y el enlace simbólico G ++ y luego volver a crearlos vinculados a GCC 4.3 y 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++
  • Ahora, si volvemos a comprobar los enlaces simbólicos, veremos que GCC y G ++ ahora están vinculados a GCC 4.3 y G ++ 4.3:
ls -la /usr/bin/ | grep gcc
ls -la /usr/bin/ | grep g++
  • Finalmente, podemos verificar nuestro GCC -v nuevamente y asegurarnos de que estamos usando la versión correcta:
gcc -v
g++ -v
hhlp
fuente
1
¡Exactamente lo que estaba buscando! Olvidé la posibilidad de vincular "gcc" a cualquier versión que haya instalado. ¡Gracias!
CalebHC
¡Un método más simple, sencillo y seguro!
sailfish009
21

¿Es esto realmente deseable? Hay cambios ABI entre gccversiones. Compilar algo con una versión (por ejemplo, todo el sistema operativo) y luego compilar algo más con otra versión, puede causar conflictos.

Por ejemplo, los módulos del kernel siempre deben compilarse con la misma versión gccutilizada para compilar el kernel. Con eso en mente, si modifica manualmente el enlace simbólico entre /usr/bin/gccy la versión utilizada en su versión de Ubuntu, los futuros módulos construidos con DKMS podrían usar la gccversión incorrecta .

Si solo quiere construir cosas con una versión diferente de gcc, eso es bastante fácil, incluso con makecripts. Por ejemplo, puede pasar la versión de gccen la CCvariable de entorno:

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

Es posible que no lo necesite en el comando make (los scripts de configuración generalmente lo activan) pero no duele.

Oli
fuente
1
Gracias por tu comentario. Soy consciente de la variable CC, pero esta no era realmente la pregunta.
Nils
2
Es cierto, pero he explicado por qué gccno es parte del alternativessistema y por qué esto no es particularmente deseable. Si ninguno de los dos va a cambiar de opinión, simplemente hágalo manualmente.
Oli
1
¿Fue antes? ¿Ahora solo lo quitaron? La compilación de software (espacio de usuario) con diferentes versiones de gcc debería estar perfectamente bien ... esta discusión se está volviendo loca ...
Nils
1
¿Puede explicar por qué las variables de entorno por invocación son preferibles a una configuración de configuración de todo el sistema? $ sudo apt-get install gcc-6 gcc-7 $ CC="gcc-7" ./configure <much output> $ make # uses gcc-7 Mientras que sudo update-alternatives gcc gcc-7se habría asegurado de que no cambie accidentalmente ABI.
kfsone
14

Editar:

Esto supone que ha instalado la versión primero, por ejemplo, con:

sudo apt install gcc-4.9 g++-4.9

Original:

Y aquí hay una frase para aquellos que son flojos, solo cambie, cambie el número al final a la versión que desee. Hará el cambio para gcc y / 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

En este ejemplo, cambié a 4.9

No hay comprobaciones de errores y qué no en este ejemplo, por lo que es posible que desee comprobar qué se ejecutará antes de ejecutarlo. Solo agrega echo antes de sudo . Para completar, también proporciono una línea de verificación:

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

El resultado de la verificación debería 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

Puede verificar la versión después con:

gcc --version

Explicación semi detallada:

  • ls -la / usr / bin / enumera todos los archivos en / usr / bin
  • El | canalizar (enviar) la salida al siguiente comando
  • grep -oP coincide con la expresión regular de búsqueda por línea. o solo muestra el resultado, no toda la línea coincidente. P le dice a grep que use perl-regex. No entraré en regex aquí, léelo si quieres.
  • En pocas palabras, xargs reúne los resultados que se le envían y los envía al final. es decir, al comando siguiente xargs
  • Bash bien, es bash. La bandera c le dice que use la cadena como un comando. En este ejemplo, recorre los argumentos enviados desde xargs omitiendo el primer argumento (0º), en este caso el bucle omite 4.9 . El argumento 0 se usa en el bucle para cambiar el enlace.
  • ln -s -f La bandera s hace un enlace simbólico, f fuerza el desvío primero si es necesario.
Cerveza inglesa
fuente
2
Pregunta muy antigua, pero esta respuesta parece ser una de las gemas que debemos buscar al revisar las respuestas a las publicaciones antiguas ...
mook765
¡Brillante! ¡La mejor respuesta sin dudas!
Gabriel Staples
-1

¿Qué tal un enlace simbólico en un directorio temporal:

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

usuario643722
fuente
Tengo que admitir: esta es una excelente respuesta.
user643722