Jak wybrać domyślną wersję gcc i g ++?

206

Więc zainstalowałem gcc-4.4 i gcc-4.3 (to samo dla g ++). Teraz, o ile pamiętam, w Ubuntu jest narzędzie, które ustawia dla ciebie dowiązania symboliczne, jeśli tylko powiesz mu, jakiej wersji chcesz. Wydaje się jednak, że nie działa w najnowszej wersji, co mnie rozczarowuje.

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

Jakieś pomysły?

Nils
źródło
1
Jak wyjaśnił @Oli, to zły pomysł. Lista mailowa dian-devel: „Nie sądzę, że do wersjonowania należy używać alternatyw. Na przykład nie używamy alternatyw dla gcc, ani dla Pythona.” list.debian.org/debian-devel/2014/06/msg00381.html
hmijail
1
OK, więc co należy użyć dla kontroli wersji?
WillC

Odpowiedzi:

271

Najpierw usunąłem bieżącą konfigurację aktualizacji alternatyw dla gcc i g ++:

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

Zainstaluj pakiety

Wygląda na to, że zarówno gcc-4.3, jak i gcc-4.4 są instalowane po instalacji niezbędnej do kompilacji. Możemy jednak wyraźnie zainstalować następujące pakiety:

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

Zainstaluj alternatywy

Dowiązania symboliczne cc i c ++ są instalowane domyślnie. Zainstalujemy łącza symboliczne dla gcc i g ++, a następnie połączymy cc i c ++ odpowiednio z gcc i g ++. (Zauważ, że 10, 20i 30opcje są priorytety dla każdej alternatywy).

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

Skonfiguruj alternatywy

Ostatnim krokiem jest skonfigurowanie domyślnych poleceń dla gcc, g ++. Łatwo jest interaktywnie przełączać się między 4.3 a 4.4:

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

Lub przełącz za pomocą skryptu:

#!/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
źródło
4
Dzięki, więc musisz dodać je ręcznie do alternatywnych aktualizacji .. IIRC wcześniejsze wersje Ubuntu zrobiły to automatycznie.
Nils
1
Jest to szczególnie przydatne przy kompilowaniu modułów nvidia dla różnych jąder. Bardzo dziękuję za wyjaśnienie alternatywnych aktualizacji
earthmeLon
1
Dziękuję Ci! Użyłem twojej drugiej odpowiedzi do aktualizacji z 4.6 do 4.7. Chciałem użyć tej odpowiedzi, ale nie byłem pewien, dlaczego po niektórych z was podajecie liczby takie jak 10 20 30. Czy mógłbyś wyjaśnić?
Martin Drozdik,
7
Jak się okazuje, liczby są priorytetami, zgodnie ze stroną podręcznika. Wyobrażam sobie, że w przypadku odinstalowania jednej wersji użyje tych priorytetów, aby ustalić, która z nich powinna stać się nową domyślną.
Ibrahim
1
@Ibrahim: Nie, określają, co zostanie wybrane po wybraniu trybu automatycznego
Cookie
41

wykonać w terminalu:

gcc -v
g++ -v

Okej, więc ta część jest dość prosta. Trudna część polega na tym, że po wydaniu polecenia GCC jest to w rzeczywistości syboliczny link, do którego używasz dowolnej wersji GCC. Oznacza to, że możemy utworzyć symboliczne łącze z GCC do dowolnej wersji GCC, którą chcemy.

  • Możesz zobaczyć symboliczny link:
ls -la /usr/bin | grep gcc-4.4
ls -la /usr/bin | grep g++-4.4
  • Musimy więc usunąć dowiązanie symboliczne GCC i dowiązanie symboliczne G ++, a następnie odtworzyć je połączone z GCC 4.3 i 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++
  • Teraz, jeśli ponownie sprawdzimy dowiązania symboliczne, zobaczymy, że GCC i G ++ są teraz połączone z GCC 4.3 i G ++ 4.3:
ls -la /usr/bin/ | grep gcc
ls -la /usr/bin/ | grep g++
  • Wreszcie możemy ponownie sprawdzić GCC -v i upewnić się, że korzystamy z poprawnej wersji:
gcc -v
g++ -v
hhlp
źródło
1
Dokładnie tego szukałem! Zapomniałem o możliwości dowiązania „gcc” do dowolnej zainstalowanej wersji. Dzięki!
CalebHC
prostsza, łatwiejsza i bezpieczniejsza metoda!
sailfish009
21

Czy to jest naprawdę pożądane? Istnieją zmiany ABI między gccwersjami. Kompilowanie czegoś w jednej wersji (np. Całego systemu operacyjnego), a następnie kompilowanie czegoś w innej wersji może powodować konflikty.

Na przykład, moduły jądra powinny zawsze być kompilowane z tą samą wersją, której gccużyto do kompilacji jądra. Mając to na uwadze, jeśli ręcznie zmieniłeś dowiązanie symboliczne /usr/bin/gcci wersję używaną w twojej wersji Ubuntu, przyszłe moduły zbudowane przez DKMS mogą używać niewłaściwej gccwersji.

Jeśli chcesz po prostu budować rzeczy z inną wersją gcc, jest to dość łatwe, nawet przy użyciu skryptów. Na przykład, można przekazać w wersji gccw CCzmiennej środowiskowej:

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

Możesz go nie potrzebować w komendzie make (skrypty konfiguracyjne zwykle go przyciągają), ale to nie boli.

Oli
źródło
1
Dziękujemy za komentarz. Zdaję sobie sprawę ze zmiennej CC, ale tak naprawdę to nie było pytanie.
Nils
2
To prawda, ale wyjaśniłem, dlaczego gccnie jest częścią alternativessystemu i dlaczego nie jest to szczególnie pożądane. Jeśli żadne z nich nie zmieni zdania, po prostu zrób to ręcznie.
Oli
1
To było wcześniej? Teraz to usunęli ?! Kompilowanie oprogramowania (przestrzeni użytkownika) z różnymi wersjami gcc powinno być całkowicie w porządku. Ta dyskusja robi się coraz bardziej…
Nils,
1
Czy możesz wyjaśnić, dlaczego zmienne środowiskowe dla poszczególnych wywołań są lepsze niż ustawienie konfiguracji dla całego systemu? $ sudo apt-get install gcc-6 gcc-7 $ CC="gcc-7" ./configure <much output> $ make # uses gcc-7 Podczas gdy sudo update-alternatives gcc gcc-7upewniłbyś się, że nie zmienisz przypadkowo ABI.
kfsone
14

Edytować:

Zakłada się, że najpierw zainstalowałeś wersję, np. Z:

sudo apt install gcc-4.9 g++-4.9

Oryginał:

A tutaj jest jeden linijka dla tych, którzy są leniwi, po prostu zmień zmień numer na końcu na żądaną wersję. Wprowadzi zmianę dla gcc i / lub 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

W tym przykładzie zmieniłem na 4.9

Nie ma sprawdzania błędów i nie ma tego w tym przykładzie, więc możesz chcieć sprawdzić, co zostanie uruchomione przed jego uruchomieniem. Po prostu dodaj echo przed sudo . Dla kompletności podaję również linię kontrolną:

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

Wynik kontroli powinien być podobny do:

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

Możesz sprawdzić wersję później za pomocą:

gcc --version

Częściowo szczegółowe wyjaśnienie:

  • ls -la / usr / bin / wyświetla wszystkie pliki w / usr / bin
  • | potok (wyślij) dane wyjściowe do następnego polecenia
  • grep -oP dopasowuje wyrażenie regularne wyszukiwania dla wiersza. o pokazuje tylko wynik, a nie całą dopasowaną linię. P mówi grepowi, aby używał perl-regex. Nie będę wchodził w wyrażenia regularne tutaj, czytaj dalej, jeśli chcesz.
  • po prostu xargs , zbiera wyniki, które są do niego przesyłane i wysyłane do końca. tzn. do polecenia następującego po xargs
  • bash dobrze, to bash. C Flaga informuje go używać ciąg jako polecenia. W tym przykładzie zapętla on argumenty wysłane z xargs , pomijając pierwszy (0) argument, w tym przypadku pętla przeskakuje 4,9 . Argument 0 służy do zmiany łącza w pętli.
  • ln -s -f s flag sprawia dowiązania symbolicznego, f sił rozłączaniu pierwszym razie potrzeby.
Ale
źródło
2
Bardzo stare pytanie, ale ta odpowiedź wydaje się być jednym z klejnotów, na który powinniśmy zwrócić uwagę, przeglądając odpowiedzi na stare posty ...
mook765,
Znakomity! Najlepsza odpowiedź bez dwóch zdań!
Gabriel Staples
-1

A co z dowiązaniem symbolicznym w katalogu tymczasowym:

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

użytkownik643722
źródło
Muszę przyznać, że to doskonała odpowiedź.
user643722