如何选择默认的gcc和g ++版本?


206

所以我已经安装了gcc-4.4和gcc-4.3(与g ++相同)。现在,据我记得,Ubuntu中有一个工具可以为您设置符号链接(如果您只是告诉它想要哪个版本)。但是,它似乎不适用于最新版本,我对此感到失望。

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 '18

Answers:


271

首先删除gcc和g ++的当前更新替代设置:

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

安装套件

似乎在安装build-essential之后,同时安装了gcc-4.3和gcc-4.4。但是,我们可以显式安装以下软件包:

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

安装替代品

默认情况下会安装符号链接cc和c ++。我们将为gcc和g ++安装符号链接,然后分别将cc和c ++链接到gcc和g ++。(请注意102030选项是每个替代项的优先级。)

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
Thx,因此您必须手动将它们添加到更新替代项。.IIRC早期的Ubuntu版本会自动执行此操作。
尼尔斯

1
当为不同的内核编译nvidia模块时,这对我特别有用。非常感谢您解释更新替代方案
earthmeLon 2012年

1
谢谢!我用您的其他答案将4.6更新为4.7。我想用这个答案,但是我不确定为什么要在某些命令后加上数字10 20 30。你能解释一下吗?
马丁·德罗兹迪克

7
根据手册,事实证明,这些数字是优先事项。我想象在卸载其中一个版本的情况下,它将使用这些优先级来确定哪个应成为新的默认值。
Ibrahim

1
@易卜拉欣:不,当您选择自动模式时,它们会确定要选择的内容
Cookie

41

在终端执行:

gcc -v
g++ -v

好的,那部分很简单。棘手的是,当您发出命令GCC时,它实际上是所使用的GCC版本的符号链接。这意味着我们可以创建从GCC到我们想要的任何版本的GCC的符号链接。

  • 您可以看到符号链接:
ls -la /usr/bin | grep gcc-4.4
ls -la /usr/bin | grep g++-4.4
  • 因此,我们需要做的是删除GCC符号链接和G ++符号链接,然后重新创建链接到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

这真的可取吗?gcc版本之间存在ABI更改。使用一个版本(例如整个操作系统)进行编译,然后使用另一版本进行其他编译,则可能导致冲突。

例如,内核模块应始终gcc使用与编译内核相同的版本进行编译。考虑到这一点,如果您手动更改了/usr/bin/gccUbuntu版本中使用的版本之间的符号链接,则将来的DKMS构建模块可能会使用错误的gcc版本。

如果您只想使用其他版本的进行构建gcc,即使使用makescripts也很容易。例如,您可以gccCC环境变量中传入版本:

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

您可能不需要在make命令上使用它(配置脚本通常会将其拉入),但不会受到伤害。


1
感谢您的评论。我知道CC变量,但这并不是问题所在。
尼尔斯

2
的确如此,但是我已经解释了为什么gcc它不是alternatives系统的一部分,以及为什么它不是特别理想。如果这些都不改变主意,则只需手动进行即可。
奥利

1
是以前吗?现在他们刚刚将其删除了吗?编译(用户空间)软件与不同版本的GCC应该完全确定..这个讨论也越来越门槛..
尼尔斯

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确保您不会意外切换ABI。
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之前添加echo即可。为了完整起见,我还提供了检查行:

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每行匹配搜索正则表达式。o仅显示结果,而不显示整个匹配行。P告诉grep使用perl-regex。我不会在这里使用正则表达式,如果您愿意的话,请继续阅读。
  • 简而言之,xargs收集通过管道传递给它的结果,并将所有结果发送到最后。即到xargs之后的命令
  • 来砸好,它的庆典。该Ç标志告诉它要使用的字符串作为命令。在此示例中,它 通过跳过第一个(第0个)参数来循环从xargs发送的参数,在这种情况下,循环跳过4.9。在循环中使用第0个参数来更改链接。
  • LN -s -f小号标志的一个符号链接,˚F力量如果需要取消关联首。

2
很老的问题了,但是这个答案似乎是我们在审查旧帖子的答案时应该寻找的瑰宝之一……
mook765

辉煌!最好的答案放手!
加布里埃尔·斯台普斯

-1

临时目录中的符号链接如何:

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


我必须承认:这是一个很好的答案。
user643722
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.