Как выбрать версию 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

Есть идеи?

Nils
источник
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

Установить альтернативы

Символические ссылки cc и 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"
hhlp
источник
4
Спасибо, так что вы должны добавить их вручную в update-альтернативы. IIRC более ранние версии Ubuntu делали это автоматически.
Нильс
1
Это особенно полезно для меня при компиляции модулей nvidia для разных ядер. Большое спасибо за объяснение альтернатив обновления
earthmeLon
1
Спасибо! Я использовал ваш другой ответ для обновления с 4.6 до 4.7. Я хотел использовать этот ответ, но я не был уверен, почему вы ставите числа, такие как 10 20 30 после некоторых из ваших команд. Не могли бы вы объяснить?
Мартин Дроздик
7
Числа являются приоритетами, как выясняется, согласно man-странице. Я предполагаю, что в случае удаления одной из версий она будет использовать эти приоритеты, чтобы определить, какая из них должна стать новой по умолчанию.
Ибрагим
1
@Ibrahim: Нет, они определяют, что выбирается, когда вы выбираете автоматический режим
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
hhlp
источник
1
Именно то, что я искал! Забыл о возможности символической ссылки "gcc" на любую версию, которую я установил. Спасибо!
CalebHC
более простой и легкий и безопасный метод!
sailfish009
21

Это действительно желательно? Есть изменения ABI между gccверсиями. Компиляция чего-либо с одной версией (например, всей операционной системы), а затем компиляция чего-то другого с другой версией может вызвать конфликт.

Например, модули ядра всегда должны быть скомпилированы с той же версией, которая gccиспользовалась для компиляции ядра. Помня об этом, если вы вручную изменили символическую ссылку между /usr/bin/gccверсией Ubuntu и версией, используемой в вашей версии, будущие модули, созданные в DKMS, могут использовать неправильную gccверсию.

Если вы просто хотите создавать вещи с другой версией gcc, это достаточно просто, даже с makecripts. Например, вы можете передать версию gccв CCпеременной среды:

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

Вам может не понадобиться это в команде make (обычно это настраивают скрипты configure), но это не повредит.

Оли
источник
1
Спасибо за ваш комментарий. Я знаю о переменной CC, но это был не совсем вопрос.
Нильс
2
Правда, но я объяснил, почему gccне является частью alternativesсистемы и почему это не особенно желательно. Если ни один из них не передумает, просто сделайте это вручную.
Оли
1
Это было раньше? Теперь они просто удалили это ?! Компиляция (пользовательского пространства) программного обеспечения с различными версиями 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, что вы бы случайно не переключили 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 . Для полноты картины я также предоставлю строку проверки:

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
  • Баш ну, это баш. С флагом говорит его использовать строку в качестве команды. В этом примере он перебирает аргументы, отправленные из xargs , пропуская первый (0-й) аргумент, в этом случае цикл пропускает 4.9 . 0-й аргумент используется в цикле для изменения ссылки.
  • пер -s -f s флаг имеет символическую ссылку, ф сил удалить связь первым , если это необходимо.
эль
источник
2
Очень старый вопрос, но этот ответ, по-видимому, является одной из жемчужин, которую мы должны искать при просмотре ответов на старые сообщения ...
mook765
Brilliant! Лучший ответ руки вниз!
Габриэль Стейплс
-1

Как насчет символической ссылки во временном каталоге:

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

user643722
источник
Я должен признать: это отличный ответ.
user643722