Làm thế nào để chọn phiên bản gcc và g ++ mặc định?


206

Vì vậy, tôi đã cài đặt gcc-4.4 và gcc-4.3 (tương tự cho g ++). Bây giờ theo tôi nhớ có một công cụ trong Ubuntu thiết lập các liên kết tượng trưng cho bạn nếu bạn chỉ cho nó biết phiên bản nào bạn muốn. Tuy nhiên, nó dường như không hoạt động trong phiên bản mới nhất, điều mà tôi thấy thất vọng.

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

Có ý kiến ​​gì không?


1
Như @Oli đã giải thích, đây là một ý tưởng tồi. Danh sách thư của Debian-devel: "Tôi không nghĩ các giải pháp thay thế nên được sử dụng cho phiên bản. Ví dụ: chúng tôi không sử dụng các lựa chọn thay thế cho gcc, cũng không phải cho Python." lists.debian.org/debian-devel/2014/06/msg00381.html
hmijail

1
OK, vì vậy những gì làm bạn sử dụng cho versioning?
WillC

Câu trả lời:


271

Đầu tiên đã xóa thiết lập thay thế cập nhật hiện tại cho gcc và g ++:

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

Cài đặt gói

Có vẻ như cả gcc-4.3 và gcc-4.4 đều được cài đặt sau khi cài đặt bản dựng. Tuy nhiên, chúng tôi có thể cài đặt rõ ràng các gói sau:

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

Cài đặt thay thế

Liên kết tượng trưng cc và c ++ được cài đặt theo mặc định. Chúng tôi sẽ cài đặt các liên kết biểu tượng cho gcc và g ++, sau đó liên kết cc và c ++ với gcc và g ++ tương ứng. (Lưu ý rằng 10, 2030các tùy chọn là các ưu tiên cho mỗi phương án.)

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

Cấu hình thay thế

Bước cuối cùng là cấu hình các lệnh mặc định cho gcc, g ++. Thật dễ dàng để chuyển đổi giữa 4.3 và 4.4 tương tác:

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

Hoặc chuyển đổi bằng cách sử dụng tập lệnh:

#!/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"

4
Thx, vì vậy bạn phải thêm chúng theo cách thủ công để cập nhật các lựa chọn thay thế .. Các phiên bản Ubuntu trước đó của IIRC đã tự động làm điều đó.
Nils

1
Điều này đặc biệt hữu ích với tôi khi biên dịch các mô-đun nvidia cho các hạt nhân khác nhau. Cảm ơn bạn rất nhiều vì đã giải thích các lựa chọn thay thế cập nhật
earthmeLon

1
Cảm ơn bạn! Tôi đã sử dụng câu trả lời khác của bạn để cập nhật từ 4.6 đến 4.7. Tôi muốn sử dụng câu trả lời này, nhưng tôi không chắc tại sao bạn lại đặt các số như 10 20 30 sau một số lệnh của bạn. Bạn có thể vui lòng giải thích?
Martin Drozdik

7
Các con số là ưu tiên khi nó bật ra, theo manpage. Tôi tưởng tượng trong trường hợp một trong những phiên bản được gỡ cài đặt, nó sẽ sử dụng các ưu tiên đó để xác định cái nào sẽ trở thành mặc định mới.
Ibrahim

1
@Ibrahim: Không, họ xác định những gì được chọn khi bạn chọn chế độ tự động
Cookie

41

thực hiện trong thiết bị đầu cuối:

gcc -v
g++ -v

Được rồi, vì vậy phần đó khá đơn giản. Phần khó khăn là khi bạn ban hành lệnh GCC, nó thực sự là một liên kết sybolic mà phiên bản GCC bạn đang sử dụng. Điều này có nghĩa là chúng ta có thể tạo một liên kết tượng trưng từ GCC tới bất kỳ phiên bản GCC nào chúng ta muốn.

  • Bạn có thể thấy liên kết tượng trưng:
ls -la /usr/bin | grep gcc-4.4
ls -la /usr/bin | grep g++-4.4
  • Vì vậy, những gì chúng ta cần làm là loại bỏ liên kết tượng trưng GCC và liên kết tượng trưng G ++ và sau đó tạo lại chúng được liên kết với GCC 4.3 và 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++
  • Bây giờ nếu chúng ta kiểm tra các liên kết tượng trưng một lần nữa, chúng ta sẽ thấy GCC & G ++ hiện được liên kết với GCC 4.3 và G ++ 4.3:
ls -la /usr/bin/ | grep gcc
ls -la /usr/bin/ | grep g++
  • Cuối cùng, chúng tôi có thể kiểm tra lại GCC -v của mình và đảm bảo rằng chúng tôi đang sử dụng phiên bản chính xác:
gcc -v
g++ -v

1
Chính xác những gì tôi đang tìm kiếm! Quên về khả năng symlink "gcc" với bất kỳ phiên bản nào tôi đã cài đặt. Cảm ơn!
CalebHC

phương pháp đơn giản hơn và dễ dàng hơn và an toàn hơn!
cá cờ009

21

Đây có thực sự là mong muốn? Có những thay đổi ABI giữa gcccác phiên bản. Biên dịch một cái gì đó với một phiên bản (ví dụ: toàn bộ hệ điều hành) và sau đó biên dịch một cái gì đó với một phiên bản khác, có thể gây ra xung đột.

Ví dụ, các mô-đun hạt nhân phải luôn được biên dịch với cùng một phiên bản gccđược sử dụng để biên dịch kernel. Với ý nghĩ đó, nếu bạn thay đổi thủ công liên kết tượng trưng giữa /usr/bin/gccvà phiên bản được sử dụng trong phiên bản Ubuntu của bạn, các mô-đun do DKMS xây dựng trong tương lai có thể sử dụng gccphiên bản sai .

Nếu bạn chỉ muốn xây dựng mọi thứ với một phiên bản khác gcc, điều đó đủ dễ dàng, ngay cả với các bản mô tả. Ví dụ, bạn có thể vượt qua trong các phiên bản của gcctrong CCbiến môi trường:

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

Bạn có thể không cần nó trên lệnh make (cấu hình tập lệnh thường kéo nó vào) nhưng nó không bị tổn thương.


1
Thx cho ý kiến ​​của bạn. Tôi biết về biến CC, nhưng đây không thực sự là câu hỏi.
Nils

2
Đúng như vậy nhưng tôi đã giải thích tại sao gcckhông phải là một phần của alternativeshệ thống và tại sao điều này không đặc biệt mong muốn. Nếu cả hai sẽ không thay đổi suy nghĩ của bạn, chỉ cần làm điều đó bằng tay.
Oli

1
Đó là trước kia? Bây giờ họ mới gỡ bỏ nó?! Phần mềm biên dịch (không gian người dùng) với các phiên bản gcc khác nhau sẽ hoàn toàn ổn .. cuộc thảo luận này sẽ bắt đầu ..
Nils

1
Bạn có thể giải thích tại sao các biến môi trường theo yêu cầu lại thích hợp hơn với cài đặt cấu hình trên toàn hệ thống không? $ sudo apt-get install gcc-6 gcc-7 $ CC="gcc-7" ./configure <much output> $ make # uses gcc-7 Trong khi đó, sudo update-alternatives gcc gcc-7chắc chắn rằng bạn không vô tình chuyển ABI.
kfsone

14

Biên tập:

Điều này giả định rằng bạn đã cài đặt phiên bản đầu tiên, ví dụ:

sudo apt install gcc-4.9 g++-4.9

Nguyên:

Và đây là một lót cho những người lười biếng, chỉ cần thay đổi thay đổi số ở cuối phiên bản bạn muốn. Nó sẽ tạo ra sự thay đổi cho gcc và / hoặc 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

Trong ví dụ này tôi đã chuyển sang 4.9

Không có kiểm tra lỗi và những gì không có trong ví dụ này, vì vậy bạn có thể muốn kiểm tra những gì sẽ được chạy trước khi bạn chạy nó. Chỉ cần thêm tiếng vang trước khi sudo . Để hoàn thiện tôi cũng cung cấp dòng kiểm tra:

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

Đầu ra từ kiểm tra phải là một cái gì đó như:

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

Bạn có thể kiểm tra phiên bản sau với:

gcc --version

Giải thích bán chi tiết:

  • ls -la / usr / bin / liệt kê tất cả các tệp trong / usr / bin
  • | ống (gửi) đầu ra cho lệnh tiếp theo
  • grep -oP phù hợp với biểu thức tìm kiếm trên mỗi dòng. o chỉ hiển thị kết quả không phải là toàn bộ dòng phù hợp. P bảo grep sử dụng perl-regex. Tôi sẽ không đi vào regex ở đây, đọc nó nếu bạn muốn.
  • xargs chỉ đơn giản là đặt nó, nó tập hợp các kết quả được dẫn đến nó và gửi tất cả chúng đến cuối cùng. tức là vào lệnh sau xargs
  • Bash tốt, đó là bash. Các c cờ nói với nó để sử dụng chuỗi như một lệnh. Trong ví dụ này, nó lặp lại các đối số được gửi từ xargs bằng cách bỏ qua đối số (0th) đầu tiên, trong trường hợp này, vòng lặp bỏ qua 4.9 . Đối số 0 được sử dụng trong vòng lặp để thay đổi liên kết.
  • ln -s -f Các s cờ tạo ra một liên kết tượng trưng, f lực lượng bỏ liên kết đầu tiên nếu cần thiết.

2
Câu hỏi rất cũ, nhưng câu trả lời này dường như là một trong những viên ngọc chúng ta nên tìm kiếm khi xem lại câu trả lời cho bài viết cũ ...
mook765

Xuất sắc! Trả lời tốt nhất xuống tay!
Gabriel Staples

-1

Làm thế nào về một liên kết tượng trưng trong một thư mục tạm thời:

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


Tôi phải thừa nhận: đây là một câu trả lời tuyệt vời.
dùng643722
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.