- Как установить GCC (необходимое для сборки) на Ubuntu 20.04
- Установка GCC в Ubuntu 20.04
- Компиляция примера Hello World
- Установка нескольких версий GCC
- Выводы
- Линукс что такое gcc
- Подопытная крыса
- Если ты не умеешь читать
- Если ты так ничего и не понял
- Сравнение работы gcc и g++
- gcc и g++ по косточкам
- Ну и какие выводы?
- История GCC
- Особенность G++
Как установить GCC (необходимое для сборки) на Ubuntu 20.04
Коллекция компиляторов GNU (GCC) — это набор компиляторов и библиотек для языков программирования C, C ++, Objective-C, Fortran, Ada, Go и D. Многие проекты с открытым исходным кодом, включая ядро Linux и инструменты GNU, скомпилированы с использованием GCC.
В этой статье объясняется, как установить GCC в Ubuntu 20.04.
Установка GCC в Ubuntu 20.04
Репозитории Ubuntu по умолчанию содержат метапакет с именем «build-essential», который включает коллекцию компиляторов GNU, отладчик GNU и другие библиотеки и инструменты разработки, необходимые для компиляции программного обеспечения.
Чтобы установить пакеты средств разработки, выполните следующую команду от имени пользователя root или пользователя с правами sudo :
Команда устанавливает множество пакетов, включая gcc , g++ и make .
Вы также можете установить справочные страницы об использовании GNU / Linux для разработки:
Убедитесь, что компилятор GCC успешно установлен, выполнив следующую команду, которая выводит версию GCC:
Репозитории Ubuntu 20.04 предоставляют GCC версии 9.3.0 :
Вот и все. В вашей системе Ubuntu установлены инструменты и библиотеки GCC.
Компиляция примера Hello World
Скомпилировать базовую программу на C или C ++ с помощью GCC довольно просто. Откройте текстовый редактор и создайте следующий файл:
Сохраните файл и скомпилируйте его в исполняемый файл:
Это создает двоичный файл с именем hello в том же каталоге, где вы запускаете команду.
Запустите программу hello с помощью:
Программа должна напечатать:
Установка нескольких версий GCC
В этом разделе приведены инструкции по установке и использованию нескольких версий GCC в Ubuntu 20.04. Новые версии компилятора GCC включают новые функции и улучшения оптимизации.
На момент написания этой статьи репозитории Ubuntu по умолчанию включают несколько версий GCC, от 7.xx до 10.xx
В следующем примере мы установим последние три версии GCC и G ++.
Установите нужные версии GCC и G ++, набрав:
Приведенные ниже команды настраивают альтернативу для каждой версии и связывают с ней приоритет. Версия по умолчанию — это версия с наивысшим приоритетом, в нашем случае это gcc-10 .
Позже, если вы захотите изменить версию по умолчанию, используйте команду update-alternatives :
Вам будет представлен список всех установленных версий GCC в вашей системе Ubuntu. Введите номер версии, которую вы хотите использовать по умолчанию, и нажмите Enter .
Команда создаст символические ссылки на определенные версии GCC и G ++.
Выводы
Мы показали вам, как установить GCC в Ubuntu 20.04. Теперь вы можете посетить официальную страницу документации GCC и узнать, как использовать GCC и G ++ для компиляции программ на C и C ++.
Если вы столкнулись с проблемой или хотите оставить отзыв, оставьте комментарий ниже.
Источник
Линукс что такое gcc
Что такое gcc и g++? Если задать этот вопрос людям, которые хотя бы отдаленно знакомы с Linux, то наверняка можно получить следующий ответ: «gcc — это компилятор языка Си, а g++ — компилятор С++». В каком-то смысле это будет правильный ответ. А если этим же людям задать другой вопрос: «А вы знаете, что на самом деле не существует компилятора g++, а gcc — это не Си-компилятор?» Бьюсь об заклад, что в 99% случаев можно услышать в ответ обвинения в ламерстве, дебилизме, параличе мозга, врожденной болезнью Дауна и пр. Ты тоже входишь в эти 99%? Тогда читай ниже.
Повсеместно читая мессаги в форумах или во время личного общения, я встречаю полное непонимание со стороны людей (среди которых попадаются и уже состоявшиеся программисты) того, как на самом деле работают gcc и g++. Этой статьей я попытаюсь открыть глаза на многие не простые вещи (а что вообще просто в мире *nix?) связанные с этими «компиляторами». Кто бы ты ни был: администратор, скрипт-кидди, кодер или простой юзер никс-системы — ты используешь gcc/g++, а значит должен понимать принципы их работы.
Несмотря на то, что на момент написания этой статьи уже появилась версия GCC 3.3.2, речь однако пойдет о версии 2.96. Именно эта версия установлена на моем стареньком Red Hat 7.1 и меня совершенно не втыкает выкачивать около 30 МБ (если не ошибаюсь, именно столько весит архив GCC 3.3.2), т. к. 2.96 меня пока что полностью устраивает. Я просмотрел список изменений и дополнений, прошедших с версии 2.96 и не заметил ни чего существенного, чтобы могло бы повлиять на ход этой статьи. Но в качестве домашнего задания, я оставляю тебе проверить все сказанное здесь для других версий компилятора и сообщить о результатах мне.
Подопытная крыса
Создадим простейшую тестовую программку на С++ и сохраним ее под именем hello.cpp:
Выполним сначала компиляцию с помощью g++:
g++ -o hello hello.cpp
Все проходит без ошибок, в текущей директории образуется выполняемый файл hello. Теперь попробуем произвести компиляцию этой же программы с помощью gcc:
gcc -o hello hello.cpp
Компиляция не проходит, на экран вываливаются ошибки вроде тех, что показаны на скриншоте (см. рис. 1).
Рис.1. gcc отказывается компилить CPP-программу
Между тем gcc отлично справляется с любой Си-прогой. Так, значит, gcc не понимает программ на C++, а только Си-программы? Значит g++ и gcc два разных компилятора? Зачем же я тогда завел весь этот разговор? Подожди, подожди, давай обратимся к man.
Если ты не умеешь читать
Откроем man g++. Прямо с первых строк, в разделе описания читаем (я привожу сразу перевод):
«Компиляторы Си и Си++ объединены; g++ — это скрипт, который вызывает gcc с опциями языка С++. gcc пропускает входные файлы через одну или более из четырех стадий: препроцессирование, компиляцию, ассемблирование и линковку».
Нечто подобное можно найти и в man gcc. Продолжая дальше изучать эти маны, можно узнать, что, например, расширения исходных файлов .cc, .cpp, .C (прописная буква) и пр. зарезервированы для языка С++, а .c (строчная буква) — для языка Си. Именно по расширению компилятор определяет, на каком языке составлена программа.
К сожалению, у меня man g++ датируется аж апрелем 1993 года (спасибо компании Red Hat, чей дистрибутив я купил в 2001 году)! Поэтому он может не отражать современной действительности. Так g++ на самом деле ни какой не скрипт и gcc он не вызывает. Это легко проверить, удалив/переместив файл gcc (у меня он расположен в папке /usr/bin/gcc) и повторно скомпилировав hello.cpp с помощью g++. Компиляция пройдет на ура, а это значит, что gcc для его работы не требуется.
Поэтому обратимся лучше к самому свежему мануалу, а именно к «GCC 3.3.2 Manual», который можно найти на официальном сайте http://gcc.gnu.org/onlinedocs/. Вот что там можно прочитать (далее перевод):
«Несколько версий компиляторов объединены (C, C++, Objective-C, Ada, Fortran, Java). Вот почему мы используем название «GNU Compiler Collection». GCC может компилировать программы написанные на любом из этих языков. Ada, Fortran, Java описаны в отдельных мануалах.
«GCC» — общее стандартное обозначение от «GNU Compiler Collection». Это как общее название компилятора, так и название, используемое, когда акцент делается на компиляции C программ (как прежде это сокращение обозначало «GNU C
Compiler»).
Когда ссылаются на C++ компиляцию, обычно называют компилятор «G++». Поскольку есть только один компилятор, будет точным называть его «GCC» вне зависимости от языка; однако термин «G++» более полезен, когда ударение стоит на компиляции С++ программ».
Если ты так ничего и не понял
Как же так, мы ведь вначале статьи на эксперименте убедились, что gcc и g++ работают по-разному, а в мануале сказано, что есть только один компилятор GCC? Давай не будем делать поспешных выводов, а лучше снова обратимся к man. В разделе FILES обоих манов («man gcc» и «man g++») мы обнаружим интересную деталь (см. рис. 2), оказывается, что для компиляции Си-программ используется компилятор cc1, а для программ на C++ как gcc, так и g++ вызывают cc1plus! Так вот они настоящие компиляторы! Там же мы увидим имена файлов препроцессора, линкера и пр., причем все эти файлы являются составной частью пакета GCC! Значит, gcc и g++ просто вызывают указанные файлы, выполняя поочередно все этапы создания бинарника (препроцессирование, компиляцию, ассемблирование и линковку)!
Рис.2. Вот они настоящие компиляторы!
Но почему gcc отказался компилировать программу на C++? Дело в том, что gcc по умолчанию подключает к программе стандартную библиотеку языка C: libc, а g++ стандартную библиотеку языка C++: lstdc++. Таким образом, перед компиляцией программы на языке С++ достаточно принудительно указать gcc библиотеку lstdc++ и он откомпилирует программу не хуже g++. Т. е. для того чтобы gcc скомпилил нашу программу hello.cpp достаточно указать в командной строке следующее: gcc -o hello hello.cpp -lstdc++.
Сравнение работы gcc и g++
Хорошо, мы убедились, что gcc и g++ одинаково смогли справиться с задачей, но может быть на внутреннем уровне они отличаются? Может быть процесс создания исполняемого файла в них идет по-разному, а ведь это в свою очередь может свидетельствовать о том, что это совершенно независимые компиляторы? Что ж попытаемся выяснить и это. Естественно мы не будем рыться в исходниках GCC, т. к. компилятор это не программка в сотню строк и одной бутылочки, чтобы разобраться, явно не хватит. Для того чтобы увидеть, что происходит в действительности, существует замечательный ключик –v. Результат компиляции с использованием этого ключа показан на рисунке 3.
Рис.3. Результат компиляции с опцией –v
Чтобы сравнить выходные данные gcc и g++, я сохранил результаты вывода в текстовые файлы:
gcc –v –o hello hello.cpp 2>tmp_gcc.txt
g++ -v –o hello hello.cpp 2>tmp_g++.txt
И воспользовавшись утилитой diff, выяснил, что выходные данные оказались практически одинаковыми. Отличие заключается лишь в именах темповых файлов, например в одном случае: /tmp/cczEKZcb.ii, а в другом: /tmp/ccdVfS2M.ii — но это само собой разумеющиеся отличия! Следовательно, процесс создания исполняемого файла на «внутреннем» уровне в обоих случаях протекает совершенно одинаково. Давай рассмотрим этот процесс в деталях.
gcc и g++ по косточкам
Далее я привожу пошаговый разбор той информации, которую выводят gcc и g++ с использованием ключа –v (tmp_gcc.txt или tmp_g++):
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs
gcc version 2.96 20000731 (Red Hat Linux 7.1 2.96-81)
Эти строки говорят о том, что происходит чтение файла specs, на основании которого будет строиться дальнейшая компиляция, а также показывается номер версии компилятора gcc. Еще раз отмечаю: gcc и g++ выводят совершенно идентичную информацию!
/usr/lib/gcc-lib/i386-redhat-linux/2.96/cpp0 -lang-c++ -D__GNUG__=2 -D__EXCEPTIONS -v -D__GNUC__=2 -D__GNUC_MINOR__=96 -D__GNUC_PATCHLEVEL__=0 -D__ELF__ -Dunix -Dlinux -D__ELF__ -D__unix__ -D__linux__ -D__unix -D__linux -Asystem(posix) -Acpu(i386) -Amachine(i386) -Di386 -D__i386 -D__i386__ -D__tune_i386__ hello.cpp /tmp/cczEKZcb.ii
GNU CPP version 2.96 20000731 (Red Hat Linux 7.1 2.96-81) (cpplib) (i386 Linux/ELF)
Первым вызывается препроцессор cpp0, он заменяет в программе комментарии пробелами, вставляет файлы #include, преобразует директивы #define, #ifdef, #undef и пр. В результате препроцессирования образуется темповый файл /tmp/cczEKZcb.ii, необходимый для дальнейшей компиляции.
ignoring nonexistent directory «/usr/local/include»
ignoring nonexistent directory «/usr/i386-redhat-linux/include»
#include «. » search starts here:
#include search starts here:
End of search list.
Здесь мы видим, что препроцессор ищет необходимые include-файлы, указанные в двойных кавычках — в текущей директории, а заключенные в угловые скобки — по указанным трем путям.
/usr/lib/gcc-lib/i386-redhat-linux/2.96/cc1plus /tmp/cczEKZcb.ii -quiet -dumpbase hello.cpp -version -o /tmp/ccw4l1Ud.s
GNU C++ version 2.96 20000731 (Red Hat Linux 7.1 2.96-81) (i386-redhat-linux) compiled by GNU C version 2.96 20000731 (Red Hat Linux 7.1 2.96-81).
Теперь в работу вступает компилятор С++: cc1plus, который на основании файла /tmp/cczEKZcb.ii, полученного на этапе препроцессирования, создает исходник на ассемблере /tmp/ccw4l1Ud.s.
as -V -Qy -o /tmp/cc5T4w7y.o /tmp/ccw4l1Ud.s
GNU assembler version 2.10.91 (i386-redhat-linux) using BFD version 2.10.91.0.2
Далее наступает этап ассемблирования, для чего вызывается стандартный ассемблер as, который создает объектный файл /tmp/cc5T4w7y.o.
/usr/lib/gcc-lib/i386-redhat-linux/2.96/collect2 -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o hello /usr/lib/gcc-lib/i386-redhat-linux/2.96/../../../crt1.o /usr/lib/gcc-lib/i386-redhat-linux/2.96/../../../crti.o /usr/lib/gcc-lib/i386-redhat-linux/2.96/crtbegin.o -L/usr/lib/gcc-lib/i386-redhat-linux/2.96 -L/usr/lib/gcc-lib/i386-redhat-linux/2.96/../../.. /tmp/cc5T4w7y.o -lstdc++ -lgcc -lc -lgcc /usr/lib/gcc-lib/i386-redhat-linux/2.96/crtend.o /usr/lib/gcc-lib/i386-redhat-linux/2.96/../../../crtn.o
Завершается все линковкой. Линковщик collect2 объединяет объектные файлы с необходимыми разделяемыми библиотеками и создает исполняемый файл. Ключ –L показывает, в каких директориях происходит поиск библиотек.
Ну и какие выводы?
Мы наглядно убедились, что gcc и g++ компилируют CPP-программы совершено одинаково, причем их основная роль в этом процессе заключается в вызове необходимых утилит (препроцессора, компилятора, ассемблера, линковщика). Точно также, к примеру, работает Microsoft Visual C++, который для того, чтобы создать исполняемый файл вызывает cl.exe, link.exe, lib.exe и пр. Т. е. gcc — это уже давно не Си-компилятор, а «GNU Compiler Collection», а g++ лишь одна из его составных частей, оставленная скорее для удобства (чтобы не терзать gcc левыми ключами), чем для каких-то реально необходимых целей. G++ как отдельный компилятор просто отсутствует в природе! На сервере ftp://ftp.gnu.org/ можно скачать лишь обновления библиотеки libstdc++. Но как сказано в мануалах, gcc можно называть С-компилятором, когда речь идет о компилировании С-программ, а g++, соответственно, можно называть CPP-компилятором, когда акцент ставится на CPP-программах. Тут терминология не особенно важна, главное понимать, что происходит в действительности, но как раз этого понимания большинству nix-men и не хватает.
История GCC
Первая версия gcc была создана основателем «Free Software Foundation» Ричардом Столманом в 1987 году. Первоначально аббревиатура GCC означала «GNU C Compiler», т. к. gcc тогда компилировал только Си-программы. Теперь GCC расшифровывается, как «GNU Compiler Collection», т. к. включает в себя множество компиляторов: C, C++, Objective-C, Ada, Java и пр. Огромный вклад в развитие GCC внесла компания Cygnus под руководством Майкла Тиманна (Michael Tiemann). В 1997 между Cygnus и «Free Software Foundation», из-за некоторых разногласий произошел раскол, и Cygnus создала свою версию компилятора EGCS. Однако в 1999 году конфликт был исчерпан и проект EGCS слился с GCC. Последнюю версию компилятора GCC всегда можно найти на официальном FTP-сервере: ftp://ftp.gnu.org/gnu/gcc/.
Особенность G++
В статье я не сказал об одной мелкой детали. G++ всегда по умолчанию линкует библиотеку математических подпрограмм libm (по крайней мере, версия GCC 2.96). По этой причине программы скомпилированные g++ получаются всегда немного большего размера, чем те же программы полученные с помощью gcc. Если при компиляции с помощью gcc в командной строке указать флаг –lm будет получен тот же эффект.
Источник