297

So I have installed gcc-4.4 and gcc-4.3 (same for g++). Now as far as I remember there is a tool in Ubuntu which sets the symlinks for you if you just tell it which version you want. However it does not seem to work in the newest version, which I find disappointing.

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

Any ideas?

3
  • 2
    As @Oli explained, this is a bad idea. Debian-devel mail list: "I don't think alternatives should be used for versioning. For example, we don't use alternatives for gcc, neither for Python." lists.debian.org/debian-devel/2014/06/msg00381.html
    – hmijail
    Aug 18, 2016 at 20:39
  • 3
    OK, so what do you use for versioning?
    – WillC
    Nov 28, 2018 at 8:34
  • Users can use whatever they want for userspace code: They can put gcc et.al. links/executables in their $HOME/bin, they can put them into projectx/bin and alter their PATH with a script to put the project/bin before the system locations. Slipping an untested/unvalidated compiler into the kernel module build stack can cause problems: 25 million+ Google hits on Ubuntu update broke my pc.
    – ubfan1
    Jan 29, 2023 at 22:43

10 Answers 10

393

First erase the current update-alternatives setup for gcc and g++:

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

Install Packages

It seems that both gcc-4.3 and gcc-4.4 are installed after install build-essential. However, we can explicitly install the following packages:

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

Install Alternatives

Symbolic links cc and c++ are installed by default. We will install symbol links for gcc and g++, then link cc and c++ to gcc and g++ respectively. (Note that the 10, 20 and 30 options are the priorities for each alternative, where a bigger number is a higher priority.)

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

Configure Alternatives

The last step is configuring the default commands for gcc, g++. It's easy to switch between 4.3 and 4.4 interactively:

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

Or switch using script:

#!/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"
12
  • 7
    Thx, so you have to add them manually to update-alternatives.. IIRC earlier Ubuntu versions did that automatically.
    – Nils
    Feb 15, 2011 at 19:33
  • 1
    This is especially useful to me when compiling nvidia modules for different kernels. Thank you so much for explaining update-alternatives
    – earthmeLon
    Apr 15, 2012 at 10:57
  • 1
    Thank you! I used your other answer to update from 4.6 to 4.7. I wanted to use this answer, but I was not sure why do you put numbers like 10 20 30 after some of you commands. Could you please explain? Dec 28, 2012 at 22:02
  • 7
    The numbers are priorities as it turns out, according to the manpage. I imagine in the case that one of the version is uninstalled it will use those priorities to determine which one should become the new default.
    – Ibrahim
    Jan 14, 2013 at 20:04
  • 2
    You also need ar, nm, ranlib, gcov, gcov-dump, gcov-tool from the corresponding version of gcc. May 26, 2019 at 16:37
60

execute in terminal :

gcc -v
g++ -v

Okay, so that part is fairly simple. The tricky part is that when you issue the command GCC it is actually a sybolic link to which ever version of GCC you are using. What this means is we can create a symbolic link from GCC to whichever version of GCC we want.

  • You can see the symbolic link :
ls -la /usr/bin | grep gcc-4.4
ls -la /usr/bin | grep g++-4.4
  • So what we need to do is remove the GCC symlink and the G++ symlink and then recreate them linked to GCC 4.3 and 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++
  • Now if we check the symbolic links again we will see GCC & G++ are now linked to GCC 4.3 and G++ 4.3:
ls -la /usr/bin/ | grep gcc
ls -la /usr/bin/ | grep g++
  • Finally we can check our GCC -v again and make sure we are using the correct version:
gcc -v
g++ -v
4
  • 1
    Exactly what I was looking for! Forgot about the ability to symlink "gcc" to whatever version I have installed. Thanks!
    – CalebHC
    Mar 1, 2019 at 18:01
  • more simpler and easier and safer method! Jul 17, 2019 at 1:16
  • instead of ls -la /usr/bin | grep g++-4.4 use ls -la /usr/bin/g++4.4* which is shorter, faster and safer
    – phuclv
    Oct 27, 2020 at 8:19
  • Best answer on here. Explained how it works etc.
    – user997112
    Aug 17, 2022 at 5:52
29

Is this really desirable? There are ABI changes between gcc versions. Compiling something with one version (eg the entire operating system) and then compiling something else with another version, can cause conflict.

For example, kernel modules should always be compiled with the same version of gcc used to compile the kernel. With that in mind, if you manually altered the symlink between /usr/bin/gcc and the version used in your version of Ubuntu, future DKMS-built modules might use the wrong gcc version.

If you just want to build things with a different version of gcc, that's easy enough, even with makescripts. For example, you can pass in the version of gcc in the CC environment variable:

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

You might not need it on the make command (configure scripts usually pull it in) but it doesn't hurt.

4
  • 2
    Thx for your comment. I'm aware of the CC variable, but this was not really the question.
    – Nils
    Feb 15, 2011 at 16:31
  • 2
    True enough but I have explained why gcc isn't part of the alternatives system and why this isn't particularly desirable. If neither of those are going to change your mind, just do it manually.
    – Oli
    Feb 15, 2011 at 16:43
  • 1
    It was before? Now they just removed it?! Compiling (userspace) software with different gcc versions should be perfectly ok.. this discussion is getting sill..
    – Nils
    Feb 15, 2011 at 18:12
  • 2
    Can you explain why per-invocation environment variables are preferable to a system-wide configuration setting? $ sudo apt-get install gcc-6 gcc-7 $ CC="gcc-7" ./configure <much output> $ make # uses gcc-7 Whereas sudo update-alternatives gcc gcc-7 would have made sure that you don't accidentally switch ABIs.
    – kfsone
    Jun 12, 2017 at 22:01
18

Edit:

This assumes that you have installed the version first, with e.g.:

sudo apt install gcc-4.9 g++-4.9

Original:

And here is a one-liner for those who are lazy, just change change the number at the end to the version you want. It will make the change for gcc and/or 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

In this example I switched to 4.9

There are no error checks and what not in this example, so you might want to check what will be run before you run it. Just add echo before sudo. For completeness I provide check line as well:

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

The output from the check should be something like:

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

You can check the version after with:

gcc --version

Semi-detailed explanation:

  • ls -la /usr/bin/ lists all files in /usr/bin
  • | pipe (send) the output to the next command
  • grep -oP matches the search regex per line. o only shows the result not the entire matched line. P tells grep to use perl-regex. I will not go into regex here, read up on it if you want to.
  • xargs simply put, it gathers the results that are piped to it and send all of them to the end. i.e. to the command following xargs
  • bash well, it's bash. The c flag tells it to use the string as a command. In this example it loops over the arguments sent from xargs by skipping the first (0th) argument, in this case the loop skips 4.9. The 0th argument is used in the loop to change the link.
  • ln -s -f The s flag makes a symbolic link, f forces unlinking first if needed.
0
18

I was looking to switch from gcc/g++ 9.x (was installed) to 10.x:

  1. Installed the new desired version:
sudo apt install gcc-10
sudo apt install g++-10
  1. Switch to the new version:
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 10
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 10
  1. Test with:
gcc --version
g++ --version

The old version is still installed in case you need to switch back, just use the commands form 2. with your old version!

1
  • 1
    it works, tks!!
    – Dan D.
    Oct 25, 2022 at 8:05
12

I usually configure also related gcc tools (gcc-ar, ...) as slaves, so you can switch all of them at once:

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.3 10 \
    --slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-4.3 \
    --slave /usr/bin/gcc-nm gcc-nm /usr/bin/gcc-nm-4.3 \
    --slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-4.3

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.4 20 \
    --slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-4.4 \
    --slave /usr/bin/gcc-nm gcc-nm /usr/bin/gcc-nm-4.4 \
    --slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-4.4
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

Then to select the default one:

sudo update-alternatives --config gcc
sudo update-alternatives --config g++
1
  • 1
    this helped me switch between 11 and GCC 12
    – JAMSHAID
    Oct 25, 2022 at 16:52
1

How about a symbolic link in a temporary directory:

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

0
0

Using update-alternatives will introduce numerous small files and links into /etc/alternatives. Moreover, you have to do the selection for every compiler slave (i.e, gcc cpp g++ gcc-ar gcc-nm gcc-ranlib gcov gcov-dump gcov-tool lto-dump) in update-alternatives. For a cleaner and more straight-forward solution, just use bash for loop:

cd /usr/bin
for f in gcc cpp g++ gcc-ar gcc-nm gcc-ranlib gcov gcov-dump gcov-tool lto-dump; do
    ln -vsf $f-12 $f
done

Change 12 into any version that you intend to use by default.

By right, the g++ compiler package should contain package configuration for dpkg-reconfigure to select the default compiler version when multiple versions of compilers are present on the system, like when you install gdm, sddm, lightdm, it prompts to select the default display manager.

-1

You can use the alternatives command I hope it helps!

sudo apt install build-essential

sudo apt install gcc-8 g++-8 gcc-9 g++-9 gcc-10 g++-10

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 --slave /usr/bin/gcov gcov /usr/bin/gcov-10

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 90 --slave /usr/bin/g++ g++ /usr/bin/g++-9 --slave /usr/bin/gcov gcov /usr/bin/gcov-9

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 80 --slave /usr/bin/g++ g++ /usr/bin/g++-8 --slave /usr/bin/gcov gcov /usr/bin/gcov-8

sudo update-alternatives --config gcc

https://snipboard.io/zE4B9D.jpg

0
-1

Complete set (I hope) of update-alternatives commands for gcc with slave entries for cpp, g++, gcc-ar, gcc-nm, gcc-ranlib, gcov, gcov-dump, gcov-tool, lto-dump & matching x86_64-linux-gnu- links! Implemented / tested on Debian bookworm (testing) Obviously, double-check before copy/pasting and hitting ⮐Enter

BACKGROUND

I'm not a programmer or coder or anything, but I do admin a number of Linux servers (CentOS and Debian) and run Debian testing at home.  Usually I just apt install something.  Rarely do I have to ./configure && make && make install so beyond that I don't have much knowledge.  Before this, I only knew of gcc and g++, but have discovered at least 15 other links associated with the GNU Compiler Collection on my system, each pointing to a corresponding binary or other link.

Today, I have GCC 12 installed and trying to build something, but it's some older code so GCC 12 is too new.  Time sure does fly, I remember when GCC 4 was common!  When I checked, my system has versions 8, 9, 10, and 11 also.  Yet when I updated GCC to point to the version 11 binaries, it didn't change anything.  I realized gcc-11 wasn't even a binary anymore.  It's a link now too, to x86_64-linux-gnu-gcc-11 which is the target binary.  In fact, all of the binaries now start with a x86_64-linux-gnu- and end with a -vers and have a corresponding generic link starting with x86_64-linux-gnu-.

I came up with this command then, to install the alternatives that can be switched with update-alternatives command.  Just replace the value of the vers variable in the beginning to correspond to the version you have installed, the priority will be based on the version, so version 12 has 120 priority, 11 has 110, and so on.  In the end, 20 links are updated for each version!

Multi-line:

vers=<vers>; update-alternatives \
  --install /usr/bin/gcc gcc /usr/bin/gcc-"${vers}" "${vers}"0 \
  --slave /usr/bin/x86_64-linux-gnu-gcc x86_64-linux-gnu-gcc /usr/bin/x86_64-linux-gnu-gcc-"${vers}" \
  --slave /usr/bin/g++ g++ /usr/bin/g++-"${vers}" \
  --slave /usr/bin/x86_64-linux-gnu-g++ x86_64-linux-gnu-g++ /usr/bin/x86_64-linux-gnu-g++-"${vers}" \
  --slave /usr/bin/cpp cpp /usr/bin/cpp-"${vers}" \
  --slave /usr/bin/x86_64-linux-gnu-cpp x86_64-linux-gnu-cpp /usr/bin/x86_64-linux-gnu-cpp-"${vers}" \
  --slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-"${vers}" \
  --slave /usr/bin/x86_64-linux-gnu-gcc-ar x86_64-linux-gnu-gcc-ar /usr/bin/x86_64-linux-gnu-gcc-ar-"${vers}" \
  --slave /usr/bin/gcc-nm gcc-nm /usr/bin/gcc-nm-"${vers}" \
  --slave /usr/bin/x86_64-linux-gnu-gcc-nm x86_64-linux-gnu-gcc-nm /usr/bin/x86_64-linux-gnu-gcc-nm-"${vers}" \
  --slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-"${vers}" \
  --slave /usr/bin/x86_64-linux-gnu-gcc-ranlib x86_64-linux-gnu-gcc-ranlib /usr/bin/x86_64-linux-gnu-gcc-ranlib-"${vers}" \
  --slave /usr/bin/gcov gcov /usr/bin/gcov-"${vers}" \
  --slave /usr/bin/x86_64-linux-gnu-gcov x86_64-linux-gnu-gcov /usr/bin/x86_64-linux-gnu-gcov-"${vers}" \
  --slave /usr/bin/gcov-dump gcov-dump /usr/bin/gcov-dump-"${vers}" \
  --slave /usr/bin/x86_64-linux-gnu-gcov-dump x86_64-linux-gnu-gcov-dump /usr/bin/x86_64-linux-gnu-gcov-dump-"${vers}" \
  --slave /usr/bin/gcov-tool gcov-tool /usr/bin/gcov-tool-"${vers}" \
  --slave /usr/bin/x86_64-linux-gnu-gcov-tool x86_64-linux-gnu-gcov-tool /usr/bin/x86_64-linux-gnu-gcov-tool-"${vers}" \
  --slave /usr/bin/lto-dump lto-dump /usr/bin/lto-dump-"${vers}" \
  --slave /usr/bin/x86_64-linux-gnu-lto-dump x86_64-linux-gnu-lto-dump /usr/bin/x86_64-linux-gnu-lto-dump-"${vers}"

Single line:
vers=<vers>; update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-"${vers}" "${vers}"0 --slave /usr/bin/x86_64-linux-gnu-gcc x86_64-linux-gnu-gcc /usr/bin/x86_64-linux-gnu-gcc-"${vers}" --slave /usr/bin/g++ g++ /usr/bin/g++-"${vers}" --slave /usr/bin/x86_64-linux-gnu-g++ x86_64-linux-gnu-g++ /usr/bin/x86_64-linux-gnu-g++-"${vers}" --slave /usr/bin/cpp cpp /usr/bin/cpp-"${vers}" --slave /usr/bin/x86_64-linux-gnu-cpp x86_64-linux-gnu-cpp /usr/bin/x86_64-linux-gnu-cpp-"${vers}" --slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-"${vers}" --slave /usr/bin/x86_64-linux-gnu-gcc-ar x86_64-linux-gnu-gcc-ar /usr/bin/x86_64-linux-gnu-gcc-ar-"${vers}" --slave /usr/bin/gcc-nm gcc-nm /usr/bin/gcc-nm-"${vers}" --slave /usr/bin/x86_64-linux-gnu-gcc-nm x86_64-linux-gnu-gcc-nm /usr/bin/x86_64-linux-gnu-gcc-nm-"${vers}" --slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-"${vers}" --slave /usr/bin/x86_64-linux-gnu-gcc-ranlib x86_64-linux-gnu-gcc-ranlib /usr/bin/x86_64-linux-gnu-gcc-ranlib-"${vers}" --slave /usr/bin/gcov gcov /usr/bin/gcov-"${vers}" --slave /usr/bin/x86_64-linux-gnu-gcov x86_64-linux-gnu-gcov /usr/bin/x86_64-linux-gnu-gcov-"${vers}" --slave /usr/bin/gcov-dump gcov-dump /usr/bin/gcov-dump-"${vers}" --slave /usr/bin/x86_64-linux-gnu-gcov-dump x86_64-linux-gnu-gcov-dump /usr/bin/x86_64-linux-gnu-gcov-dump-"${vers}" --slave /usr/bin/gcov-tool gcov-tool /usr/bin/gcov-tool-"${vers}" --slave /usr/bin/x86_64-linux-gnu-gcov-tool x86_64-linux-gnu-gcov-tool /usr/bin/x86_64-linux-gnu-gcov-tool-"${vers}" --slave /usr/bin/lto-dump lto-dump /usr/bin/lto-dump-"${vers}" --slave /usr/bin/x86_64-linux-gnu-lto-dump x86_64-linux-gnu-lto-dump /usr/bin/x86_64-linux-gnu-lto-dump-"${vers}"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .