Bagaimana cara memilih versi gcc dan g ++ default?

206

Jadi saya telah menginstal gcc-4.4 dan gcc-4.3 (sama untuk g ++). Sejauh yang saya ingat ada alat di Ubuntu yang mengatur symlink untuk Anda jika Anda hanya mengatakannya versi yang Anda inginkan. Namun sepertinya itu tidak berfungsi di versi terbaru, yang menurut saya mengecewakan.

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

Ada ide?

Nils
sumber
1
Seperti yang dijelaskan oleh @Oli, ini adalah ide yang buruk. Daftar surat Debian-devel: "Saya tidak berpikir alternatif harus digunakan untuk versi. Misalnya, kami tidak menggunakan alternatif untuk gcc, juga untuk Python." lists.debian.org/debian-devel/2014/06/msg00381.html
hmijail
1
OK, jadi apa yang Anda gunakan untuk versi?
WillC

Jawaban:

271

Pertama menghapus pengaturan alternatif-pembaruan saat ini untuk gcc dan g ++:

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

Instal Paket

Tampaknya kedua gcc-4.3 dan gcc-4.4 diinstal setelah menginstal build-essential. Namun, kami dapat menginstal paket berikut secara eksplisit:

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

Instal Alternatif

Tautan simbolik cc dan c ++ diinstal secara default. Kami akan memasang tautan simbol untuk gcc dan g ++, lalu menghubungkan cc dan c ++ ke gcc dan g ++. (Perhatikan bahwa 10, 20dan 30opsi adalah prioritas untuk setiap alternatif.)

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

Konfigurasikan Alternatif

Langkah terakhir adalah mengkonfigurasi perintah default untuk gcc, g ++. Sangat mudah untuk beralih antara 4.3 dan 4.4 secara interaktif:

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

Atau beralih menggunakan skrip:

#!/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
sumber
4
Thx, jadi Anda harus menambahkannya secara manual ke pembaruan-alternatif .. IIRC versi Ubuntu sebelumnya melakukan itu secara otomatis.
Nils
1
Ini sangat berguna bagi saya ketika mengkompilasi modul nvidia untuk kernel yang berbeda. Terima kasih banyak untuk menjelaskan pembaruan-alternatif
earthmeLon
1
Terima kasih! Saya menggunakan jawaban Anda yang lain untuk memperbarui dari 4,6 ke 4,7. Saya ingin menggunakan jawaban ini, tetapi saya tidak yakin mengapa Anda memasukkan angka seperti 10 20 30 setelah beberapa dari Anda memberi perintah. Bisakah Anda jelaskan?
Martin Drozdik
7
Ternyata angka-angka itu adalah prioritas, menurut halaman manual. Saya membayangkan jika salah satu versi di-uninstall, akan menggunakan prioritas tersebut untuk menentukan mana yang harus menjadi default baru.
Ibrahim
1
@Ibrahim: Tidak, mereka menentukan apa yang dipilih ketika Anda memilih mode otomatis
Cookie
41

jalankan di terminal:

gcc -v
g++ -v

Oke, jadi bagian itu cukup sederhana. Bagian yang sulit adalah ketika Anda mengeluarkan perintah GCC itu sebenarnya adalah tautan simbolis ke versi GCC yang pernah Anda gunakan. Artinya, kita dapat membuat tautan simbolik dari GCC ke versi GCC mana pun yang kita inginkan.

  • Anda dapat melihat tautan simbolis:
ls -la /usr/bin | grep gcc-4.4
ls -la /usr/bin | grep g++-4.4
  • Jadi yang perlu kita lakukan adalah menghapus symlink GCC dan G ++ symlink dan kemudian membuatnya kembali yang terhubung ke GCC 4.3 dan 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++
  • Sekarang jika kita periksa lagi tautan simbolik, kita akan melihat GCC & G ++ sekarang terhubung ke GCC 4.3 dan G ++ 4.3:
ls -la /usr/bin/ | grep gcc
ls -la /usr/bin/ | grep g++
  • Akhirnya kita dapat memeriksa GCC -v kita lagi dan memastikan kita menggunakan versi yang benar:
gcc -v
g++ -v
hhlp
sumber
1
Persis apa yang saya cari! Lupa tentang kemampuan untuk menghubungkan "gcc" ke versi apa pun yang saya instal. Terima kasih!
CalebHC
metode yang lebih sederhana dan lebih mudah dan lebih aman!
sailfish009
21

Apakah ini benar-benar diinginkan? Ada perubahan ABI antara gccversi. Mengkompilasi sesuatu dengan satu versi (mis. Seluruh sistem operasi) dan kemudian mengkompilasi sesuatu yang lain dengan versi lain, dapat menyebabkan konflik.

Sebagai contoh, modul kernel harus selalu dikompilasi dengan versi yang sama gccdigunakan untuk mengkompilasi kernel. Dengan mengingat hal itu, jika Anda secara manual mengubah symlink antara /usr/bin/gccdan versi yang digunakan dalam versi Ubuntu Anda, modul-modul yang dibuat DKMS di masa depan mungkin menggunakan gccversi yang salah .

Jika Anda hanya ingin membangun sesuatu dengan versi yang berbeda gcc, itu cukup mudah, bahkan dengan skrip make. Misalnya, Anda bisa memasukkan versi gccdalam CCvariabel lingkungan:

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

Anda mungkin tidak memerlukannya di perintah make (konfigurasikan skrip biasanya menariknya) tetapi tidak sakit.

Oli
sumber
1
Terima kasih atas komentar Anda. Saya mengetahui variabel CC, tapi ini bukan pertanyaan sebenarnya.
Nils
2
Cukup benar tetapi saya telah menjelaskan mengapa gccbukan bagian dari alternativessistem dan mengapa ini tidak terlalu diinginkan. Jika tidak satu pun dari mereka akan berubah pikiran, lakukan saja secara manual.
Oli
1
Itu sebelumnya? Sekarang mereka baru saja menghapusnya ?! Mengkompilasi perangkat lunak (userspace) dengan versi gcc yang berbeda harusnya benar-benar baik-baik saja .. diskusi ini masih berjalan ..
Nils
1
Bisakah Anda menjelaskan mengapa variabel lingkungan per-doa lebih disukai daripada pengaturan konfigurasi sistem? $ sudo apt-get install gcc-6 gcc-7 $ CC="gcc-7" ./configure <much output> $ make # uses gcc-7 Padahal sudo update-alternatives gcc gcc-7akan memastikan bahwa Anda tidak sengaja mengganti ABI.
kfsone
14

Sunting:

Ini mengasumsikan bahwa Anda telah menginstal versi pertama, dengan misalnya:

sudo apt install gcc-4.9 g++-4.9

Asli:

Dan di sini adalah satu-liner untuk mereka yang malas, cukup ubah ganti nomor di akhir ke versi yang Anda inginkan. Ini akan membuat perubahan untuk gcc dan / atau 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

Dalam contoh ini saya beralih ke 4.9

Tidak ada pemeriksaan kesalahan dan apa yang tidak ada dalam contoh ini, jadi Anda mungkin ingin memeriksa apa yang akan dijalankan sebelum Anda menjalankannya. Cukup tambahkan gema sebelum sudo . Untuk kelengkapan saya sediakan juga baris cek:

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

Output dari cek harus berupa:

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

Anda dapat memeriksa versi setelahnya dengan:

gcc --version

Penjelasan semi-detail:

  • ls -la / usr / bin / daftar semua file di / usr / bin
  • | pipa (kirim) output ke perintah selanjutnya
  • grep -oP cocok dengan regex pencarian per baris. o hanya menunjukkan hasilnya bukan seluruh baris yang cocok. P memberitahu grep untuk menggunakan perl-regex. Saya tidak akan masuk ke regex di sini, baca di atasnya jika Anda mau.
  • xargs sederhananya, ia mengumpulkan hasil yang disalurkan ke sana dan mengirim semuanya ke akhir. yaitu untuk perintah berikut xargs
  • bash well, ini bash. The c bendera mengatakan itu untuk menggunakan string sebagai perintah. Dalam contoh ini ia mengulangi argumen yang dikirim dari xargs dengan melewatkan argumen pertama (ke-0), dalam hal ini loop dilewati 4,9 . Argumen 0 digunakan dalam loop untuk mengubah tautan.
  • ln -s -f The s bendera membuat symbolic link, f pasukan membatalkan tautan pertama jika diperlukan.
Ale
sumber
2
Pertanyaan yang sangat lama, tetapi jawaban ini tampaknya menjadi salah satu permata yang harus kita cari ketika meninjau jawaban untuk posting lama ...
mook765
Cemerlang! Jawaban terbaik dijatuhkan!
Gabriel Staples
-1

Bagaimana dengan tautan simbolis di direktori sementara:

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

pengguna643722
sumber
Saya harus mengakui: ini adalah jawaban yang sangat baik.
user643722