Wie wählt man die Standardversion von gcc und g ++ aus?

206

Also habe ich gcc-4.4 und gcc-4.3 installiert (dasselbe für g ++). Soweit ich mich erinnere, gibt es in Ubuntu ein Tool, das die Symlinks für Sie festlegt, wenn Sie nur angeben, welche Version Sie möchten. Allerdings scheint es in der neuesten Version nicht zu funktionieren, was ich enttäuschend finde.

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

Irgendwelche Ideen?

Nils
quelle
1
Wie @Oli erklärte, ist dies eine schlechte Idee. Debian-Entwickler-Mailingliste: "Ich denke nicht, dass Alternativen für die Versionierung verwendet werden sollten. Zum Beispiel verwenden wir weder für gcc noch für Python Alternativen." lists.debian.org/debian-devel/2014/06/msg00381.html
hmijail
1
OK, was verwenden Sie für die Versionierung?
WillC

Antworten:

271

Zuerst wurden die aktuellen Update-Alternativen für gcc und g ++ gelöscht:

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

Installieren Sie Pakete

Es scheint, dass sowohl gcc-4.3 als auch gcc-4.4 nach der Installation von build-essential installiert werden. Wir können jedoch die folgenden Pakete explizit installieren:

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

Installieren Sie Alternativen

Symbolische Links cc und c ++ werden standardmäßig installiert. Wir werden Symbollinks für gcc und g ++ installieren und dann cc und c ++ mit gcc bzw. g ++ verknüpfen. (Beachten Sie, dass die 10, 20und 30Optionen sind die Prioritäten für jede 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++

Alternativen konfigurieren

Der letzte Schritt ist die Konfiguration der Standardbefehle für gcc, g ++. Es ist einfach, interaktiv zwischen 4.3 und 4.4 zu wechseln:

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

Oder wechseln Sie mit Skript:

#!/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
quelle
4
Thx, also musst du sie manuell zu Update-Alternativen hinzufügen. IIRC frühere Ubuntu-Versionen haben das automatisch gemacht.
Nils
1
Dies ist besonders nützlich für mich, wenn ich nvidia-Module für verschiedene Kernel kompiliere. Vielen Dank für die Erklärung der Update-Alternativen
earthmeLon
1
Danke! Ich habe Ihre andere Antwort verwendet, um von 4.6 auf 4.7 zu aktualisieren. Ich wollte diese Antwort verwenden, war mir aber nicht sicher, warum Sie nach einigen Befehlen Zahlen wie 10 20 30 eingeben. Könntest du bitte erklären?
Martin Drozdik
7
Die Zahlen sind Prioritäten, wie sich herausstellt, entsprechend der Manpage. Ich stelle mir vor, dass in dem Fall, dass eine der Versionen deinstalliert wird, diese Prioritäten verwendet werden, um zu bestimmen, welche die neue Standardversion werden soll.
Ibrahim
1
@ Ibrahim: Nein, sie bestimmen, was ausgewählt wird, wenn Sie den automatischen Modus auswählen
Cookie
41

im Terminal ausführen:

gcc -v
g++ -v

Okay, dieser Teil ist ziemlich einfach. Der schwierige Teil ist, dass wenn Sie den Befehl GCC eingeben, es sich tatsächlich um eine sybolische Verknüpfung zu der Version von GCC handelt, die Sie verwenden. Dies bedeutet, dass wir eine symbolische Verbindung von GCC zu jeder gewünschten Version von GCC herstellen können.

  • Sie können den symbolischen Link sehen:
ls -la /usr/bin | grep gcc-4.4
ls -la /usr/bin | grep g++-4.4
  • Wir müssen also den GCC-Symlink und den G ++ - Symlink entfernen und sie dann neu erstellen, die mit GCC 4.3 und G ++ 4.3 verknüpft sind:
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++
  • Wenn wir nun die symbolischen Links erneut überprüfen, werden wir sehen, dass GCC & G ++ jetzt mit GCC 4.3 und G ++ 4.3 verknüpft sind:
ls -la /usr/bin/ | grep gcc
ls -la /usr/bin/ | grep g++
  • Schließlich können wir unser GCC -v noch einmal überprüfen und sicherstellen, dass wir die richtige Version verwenden:
gcc -v
g++ -v
hhlp
quelle
1
Genau das, wonach ich gesucht habe! Ich habe vergessen, "gcc" mit einer von mir installierten Version zu verknüpfen. Vielen Dank!
CalebHC
einfachere und einfachere und sicherere Methode!
sailfish009
21

Ist das wirklich wünschenswert? Es gibt ABI-Änderungen zwischen den gccVersionen. Das Kompilieren von etwas mit einer Version (z. B. dem gesamten Betriebssystem) und das anschließende Kompilieren von etwas anderem mit einer anderen Version kann zu Konflikten führen.

Beispielsweise sollten Kernelmodule immer mit derselben Version gcckompiliert werden, die zum Kompilieren des Kernels verwendet wurde. Wenn Sie den Symlink zwischen /usr/bin/gccund der in Ihrer Ubuntu-Version verwendeten Version manuell geändert haben , verwenden zukünftige DKMS-Module möglicherweise die falsche gccVersion.

Wenn Sie nur Dinge mit einer anderen Version von gccerstellen möchten, ist das auch mit make-skripten einfach genug. Beispielsweise können Sie die Version von gccin der CCUmgebungsvariablen übergeben:

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

Sie benötigen es möglicherweise nicht für den Befehl make (Configure-Skripte ziehen es normalerweise ein), aber es tut nicht weh.

Oli
quelle
1
Danke für deinen Kommentar. Mir ist die Variable CC bekannt, aber das war nicht wirklich die Frage.
Nils
2
Es stimmt, aber ich habe erklärt, warum gcces nicht Teil des alternativesSystems ist und warum dies nicht besonders wünschenswert ist. Wenn keiner von beiden Ihre Meinung ändern wird, tun Sie es einfach manuell.
Oli
1
Es war davor? Jetzt haben sie es einfach entfernt ?! Kompilieren (User - Space) Software mit verschiedenen gcc Versionen sollte vollkommen ok .. diese Diskussion Brett wird immer ..
Nils
1
Können Sie erklären, warum Umgebungsvariablen pro Aufruf einer systemweiten Konfigurationseinstellung vorzuziehen sind? $ sudo apt-get install gcc-6 gcc-7 $ CC="gcc-7" ./configure <much output> $ make # uses gcc-7 Wobei sudo update-alternatives gcc gcc-7sichergestellt hätte, dass Sie nicht versehentlich ABIs wechseln.
kfsone
14

Bearbeiten:

Dies setzt voraus, dass Sie zuerst die Version installiert haben, zB mit:

sudo apt install gcc-4.9 g++-4.9

Original:

Und hier ist ein Einzeiler für diejenigen, die faul sind, ändern Sie einfach die Nummer am Ende auf die gewünschte Version. Es wird die Änderung für gcc und / oder g ++ vornehmen

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 diesem Beispiel habe ich auf 4.9 umgestellt

Es gibt keine Fehlerprüfungen und was nicht in diesem Beispiel. Daher möchten Sie möglicherweise überprüfen, was ausgeführt wird, bevor Sie es ausführen. Fügen Sie einfach Echo vor sudo hinzu . Der Vollständigkeit halber stelle ich auch folgende Checkline zur Verfügung:

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

Die Ausgabe der Prüfung sollte ungefähr so ​​aussehen:

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

Sie können die Version danach überprüfen mit:

gcc --version

Halb detaillierte Erklärung:

  • ls -la / usr / bin / listet alle Dateien in / usr / bin auf
  • | Leiten Sie die Ausgabe an den nächsten Befehl weiter
  • grep -oP entspricht dem Suchausdruck pro Zeile. o zeigt nur das Ergebnis, nicht die gesamte übereinstimmende Zeile. P weist grep an, Perl-Regex zu verwenden. Ich werde hier nicht auf reguläre Ausdrücke eingehen, sondern es nachlesen, wenn Sie wollen.
  • xargs sammelt einfach die Ergebnisse, die an xargs weitergeleitet werden, und sendet sie alle bis zum Ende. dh zum Befehl nach xargs
  • Schlag gut, es ist Schlag. Das c- Flag weist es an, die Zeichenfolge als Befehl zu verwenden. In diesem Beispiel werden die von xargs gesendeten Argumente durch Überspringen des ersten (0ten) Arguments durchlaufen . In diesem Fall überspringt die Schleife 4.9 . Das 0-te Argument wird in der Schleife verwendet, um die Verknüpfung zu ändern.
  • ln -s -f Das Flag s stellt eine symbolische Verknüpfung her. f erzwingt bei Bedarf zuerst das Aufheben der Verknüpfung .
Ale
quelle
2
Sehr alte Frage, aber diese Antwort scheint eines der
Juwelen zu
Brillant! Beste Antwort, zweifellos!
Gabriel Staples
-1

Wie wäre es mit einem symbolischen Link in einem temporären Verzeichnis:

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

user643722
quelle
Ich muss zugeben: Das ist eine hervorragende Antwort.
user643722