จะเลือกรุ่น gcc และ g ++ เริ่มต้นได้อย่างไร


206

ดังนั้นฉันได้ติดตั้ง gcc-4.4 และ gcc-4.3 (เหมือนกันสำหรับ g ++) ตอนนี้เท่าที่ฉันจำได้ว่ามีเครื่องมือใน Ubuntu ที่ตั้ง symlink ให้คุณถ้าคุณแค่บอกเวอร์ชันที่คุณต้องการ อย่างไรก็ตามมันดูเหมือนจะไม่ทำงานในเวอร์ชั่นใหม่ล่าสุดซึ่งฉันรู้สึกผิดหวัง

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

ความคิดใด ๆ


1
ตามที่ @Oli อธิบายนี่เป็นความคิดที่ไม่ดี รายการจดหมาย Debian-devel: "ฉันไม่คิดว่าควรใช้ตัวเลือกอื่นสำหรับการกำหนดเวอร์ชันตัวอย่างเช่นเราไม่ใช้ตัวเลือกอื่นสำหรับ gcc ไม่ใช่สำหรับ Python" lists.debian.org/debian-devel/2014/06/msg00381.html
hmijail

1
ตกลงดังนั้นสิ่งที่ทำคุณใช้สำหรับเวอร์ชัน?
WillC

คำตอบ:


271

ขั้นแรกให้ลบการตั้งค่าทางเลือกการอัปเดตปัจจุบันสำหรับ gcc และ g ++:

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

ติดตั้งแพคเกจ

ดูเหมือนว่าติดตั้งทั้ง gcc-4.3 และ gcc-4.4 หลังจากติดตั้ง build-essential อย่างไรก็ตามเราสามารถติดตั้งแพ็คเกจต่อไปนี้ได้อย่างชัดเจน:

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

ติดตั้งทางเลือก

ลิงก์สัญลักษณ์ซีซีและ c ++ จะถูกติดตั้งตามค่าเริ่มต้น เราจะติดตั้งลิงก์สัญลักษณ์สำหรับ gcc และ g ++ จากนั้นลิงก์ cc และ c ++ ไปยัง gcc และ g ++ ตามลำดับ (หมายเหตุที่10, 20และ30ตัวเลือกลำดับความสำคัญของแต่ละทางเลือก.)

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

กำหนดค่าทางเลือก

ขั้นตอนสุดท้ายคือการกำหนดค่าคำสั่งเริ่มต้นสำหรับ gcc, g ++ ง่ายต่อการสลับระหว่าง 4.3 และ 4.4 แบบโต้ตอบ:

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

หรือสลับการใช้สคริปต์:

#!/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
ขอบคุณดังนั้นคุณต้องเพิ่มด้วยตนเองเพื่ออัปเดตทางเลือก .. IIRC เวอร์ชันก่อนหน้าของ Ubuntu นั้นทำโดยอัตโนมัติ
นิลส์

1
สิ่งนี้มีประโยชน์เป็นพิเศษสำหรับฉันเมื่อทำการรวบรวมโมดูล nvidia สำหรับเมล็ดที่แตกต่างกัน ขอบคุณมากที่อธิบายการปรับปรุงทางเลือก
earthmeLon

1
ขอขอบคุณ! ฉันใช้คำตอบอื่นเพื่ออัปเดตจาก 4.6 เป็น 4.7 ฉันต้องการใช้คำตอบนี้ แต่ฉันไม่แน่ใจว่าทำไมคุณถึงใส่ตัวเลขเช่น 10 20 30 หลังจากคำสั่งบางอย่างของคุณ คุณช่วยอธิบายได้มั้ย
Martin Drozdik

7
ตัวเลขมีความสำคัญตามที่ปรากฎตาม manpage ฉันจินตนาการในกรณีที่ถอนการติดตั้งเวอร์ชันใดรุ่นหนึ่งมันจะใช้ลำดับความสำคัญเหล่านั้นเพื่อพิจารณาว่าควรจะเลือกรุ่นใดเป็นค่าเริ่มต้นใหม่
อิบราฮิม

1
@ อิบราฮิม: ไม่พวกเขาเป็นตัวกำหนดสิ่งที่ได้รับเลือกเมื่อคุณเลือกโหมดอัตโนมัติ
คุกกี้

41

ดำเนินการใน terminal:

gcc -v
g++ -v

ตกลงดังนั้นส่วนนั้นค่อนข้างง่าย ส่วนที่ยุ่งยากคือเมื่อคุณออกคำสั่ง GCC จริง ๆ แล้วมันคือการเชื่อมโยง sybolic ที่ GCC เวอร์ชันที่คุณใช้อยู่ สิ่งนี้หมายความว่าเราสามารถสร้างลิงก์สัญลักษณ์จาก GCC ไปยัง GCC เวอร์ชันใดก็ได้ที่เราต้องการ

  • คุณสามารถดูลิงก์สัญลักษณ์:
ls -la /usr/bin | grep gcc-4.4
ls -la /usr/bin | grep g++-4.4
  • ดังนั้นสิ่งที่เราต้องทำคือลบ GCC symlink และ G ++ symlink ออกแล้วสร้างใหม่ที่เชื่อมโยงกับ GCC 4.3 และ 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++
  • ตอนนี้ถ้าเราตรวจสอบลิงก์สัญลักษณ์อีกครั้งเราจะเห็น GCC & G ++ เชื่อมโยงกับ GCC 4.3 และ G ++ 4.3:
ls -la /usr/bin/ | grep gcc
ls -la /usr/bin/ | grep g++
  • ในที่สุดเราสามารถตรวจสอบ GCC-v ของเราอีกครั้งและตรวจสอบให้แน่ใจว่าเราใช้รุ่นที่ถูกต้อง:
gcc -v
g++ -v

1
สิ่งที่ฉันกำลังมองหา! ลืมเกี่ยวกับความสามารถในการเชื่อมโยง "gcc" กับรุ่นที่ฉันติดตั้งไว้ ขอบคุณ!
CalebHC

ง่ายกว่าและง่ายกว่าและปลอดภัยกว่า!
sailfish009

21

สิ่งนี้เป็นที่พึงปรารถนาจริงเหรอ? มีการเปลี่ยนแปลง ABI ระหว่างgccรุ่นต่าง ๆ การคอมไพล์บางสิ่งด้วยหนึ่งเวอร์ชัน (เช่นระบบปฏิบัติการทั้งหมด) จากนั้นการคอมไพล์อย่างอื่นกับเวอร์ชั่นอื่นอาจทำให้เกิดข้อขัดแย้งได้

ตัวอย่างเช่นโมดูลเคอร์เนลควรรวบรวมด้วยรุ่นเดียวกันที่gccใช้ในการรวบรวมเคอร์เนล หากคุณปรับเปลี่ยน symlink ระหว่าง/usr/bin/gccและเวอร์ชันที่ใช้ในอูบุนตูเวอร์ชันของคุณเองโมดูลในอนาคตที่สร้างโดย DKMS อาจใช้gccเวอร์ชันที่ไม่ถูกต้อง

หากคุณต้องการสร้างสิ่งต่าง ๆ ด้วยรุ่นที่แตกต่างgccนั่นเป็นเรื่องง่ายพอแม้จะเป็นบทสรุป ตัวอย่างเช่นคุณสามารถส่งผ่านในรุ่นของgccในCCตัวแปรสภาพแวดล้อม:

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

คุณอาจไม่จำเป็นต้องใช้มันในคำสั่ง make (กำหนดค่าสคริปต์มักจะดึงเข้าไป) แต่ก็ไม่ได้ทำให้เจ็บ


1
ขอบคุณสำหรับความคิดเห็นของคุณ ฉันตระหนักถึงตัวแปร CC แต่นี่ไม่ใช่คำถาม
นิลส์

2
จริงพอ แต่ฉันได้อธิบายว่าทำไมgccไม่เป็นส่วนหนึ่งของalternativesระบบและทำไมสิ่งนี้จึงไม่เป็นที่ต้องการโดยเฉพาะ หากไม่มีสิ่งใดที่จะเปลี่ยนความคิดของคุณเพียงแค่ทำด้วยตนเอง
Oli

1
เมื่อก่อน? ตอนนี้พวกเขาเพิ่งลบออก! ซอฟต์แวร์คอมไพล์ (userspace) ที่มีเวอร์ชัน gcc ที่แตกต่างกันน่าจะโอเคอย่างสมบูรณ์ .. การสนทนานี้เริ่มขึ้นแล้ว ..
Nils

1
คุณสามารถอธิบายได้หรือไม่ว่าทำไมตัวแปรสภาพแวดล้อมต่อการเรียกใช้จึงเหมาะสำหรับการตั้งค่าการกำหนดค่าทั้งระบบ $ sudo apt-get install gcc-6 gcc-7 $ CC="gcc-7" ./configure <much output> $ make # uses gcc-7 ในขณะที่sudo update-alternatives gcc gcc-7ตรวจสอบให้แน่ใจว่าคุณไม่ได้เปลี่ยน ABIs โดยไม่ตั้งใจ
kfsone

14

แก้ไข:

สิ่งนี้จะถือว่าคุณได้ติดตั้งเวอร์ชันก่อนเช่น:

sudo apt install gcc-4.9 g++-4.9

เดิม:

และนี่คือหนึ่งซับสำหรับผู้ที่ขี้เกียจเพียงแค่เปลี่ยนเปลี่ยนหมายเลขในตอนท้ายของเวอร์ชั่นที่คุณต้องการ มันจะทำการเปลี่ยนแปลงสำหรับgccและ / หรือ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

ในตัวอย่างนี้ฉันเปลี่ยนเป็น 4.9

ไม่มีการตรวจสอบข้อผิดพลาดและไม่มีอะไรในตัวอย่างนี้ดังนั้นคุณอาจต้องการตรวจสอบสิ่งที่จะทำงานก่อนที่จะเรียกใช้ เพียงแค่เพิ่มก้องก่อนsudo เพื่อความสมบูรณ์ฉันมีบรรทัดตรวจสอบเช่นกัน:

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

ผลลัพธ์จากการตรวจสอบควรเป็นดังนี้:

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

คุณสามารถตรวจสอบรุ่นหลังจากด้วย:

gcc --version

คำอธิบายรายละเอียดกึ่ง:

  • ls -la / usr / bin /แสดงรายการไฟล์ทั้งหมดใน/ usr / bin
  • | ไพพ์ (ส่ง) เอาต์พุตไปยังคำสั่งถัดไป
  • grep -oPตรงกับ regex การค้นหาต่อบรรทัด oแสดงเฉพาะผลลัพธ์ที่ไม่ตรงกับบรรทัดทั้งหมด Pบอก grep ให้ใช้ perl-regex ฉันจะไม่เข้าสู่ regex ที่นี่อ่านมันถ้าคุณต้องการ
  • xargsใส่เพียงมันรวบรวมผลลัพธ์ที่ถูกส่งไปยังมันและส่งทั้งหมดไปยังจุดสิ้นสุด คือคำสั่งดังต่อไปนี้ xargs
  • ทุบตีดีมันทุบตี ธงบอกให้ใช้สตริงเป็นคำสั่ง ในตัวอย่างนี้มันลูปมากกว่าการขัดแย้งที่ส่งมาจากxargs โดยการกระโดดข้ามแรก (0) โต้แย้งในกรณีนี้ห่วงข้าม4.9 อาร์กิวเมนต์ที่ 0 ถูกใช้ในลูปเพื่อเปลี่ยนลิงค์
  • คำสั่ง ln -s -f sธงทำให้การเชื่อมโยงสัญลักษณ์กองกำลังยกเลิกการเชื่อมโยงแรกหากมีความจำเป็น

2
คำถามที่เก่ามาก แต่คำตอบนี้ดูเหมือนจะเป็นหนึ่งในอัญมณีที่เราควรมองหาเมื่อตรวจสอบคำตอบสำหรับการโพสต์เก่า ...
mook765

ยอดเยี่ยม! คำตอบที่ดีที่สุดมือลง!
Gabriel Staples

-1

วิธีการเกี่ยวกับลิงค์สัญลักษณ์ในไดเรกทอรีชั่วคราว:

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


ฉันต้องยอมรับ: นี่เป็นคำตอบที่ยอดเยี่ยม
user643722
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.