GNU Compiler Collection ( GCC ) — это коллекция компиляторов из проекта GNU , которые поддерживают различные языки программирования , аппаратные архитектуры и операционные системы . Free Software Foundation (FSF) распространяет GCC как свободное программное обеспечение под лицензией GNU General Public License (GNU GPL). GCC является ключевым компонентом цепочки инструментов GNU , которая используется для большинства проектов, связанных с GNU и ядром Linux . Имея примерно 15 миллионов строк кода в 2019 году, GCC является одной из крупнейших свободных программ из существующих. [4] Он сыграл важную роль в развитии свободного программного обеспечения , как инструмент, так и пример.
Когда он был впервые выпущен в 1987 году Ричардом Столлманом , GCC 1.0 был назван компилятором GNU C , поскольку он обрабатывал только язык программирования C. [1] В декабре того же года он был расширен для компиляции C++ . Позже были разработаны интерфейсы для Objective-C , Objective-C++ , Fortran , Ada , D , Go и Rust , [6] и других. [7] Спецификации OpenMP и OpenACC также поддерживаются в компиляторах C и C++. [8] [9]
GCC был портирован на большее количество платформ и архитектур наборов инструкций , чем любой другой компилятор, и широко используется в качестве инструмента для разработки как свободного, так и проприетарного программного обеспечения . GCC также доступен для многих встраиваемых систем , включая чипы на базе ARM и Power ISA .
Помимо того, что он является официальным компилятором операционной системы GNU , GCC был принят в качестве стандартного компилятора многими другими современными Unix-подобными компьютерными операционными системами , включая большинство дистрибутивов Linux . Большинство операционных систем семейства BSD также перешли на GCC вскоре после его выпуска, хотя с тех пор FreeBSD и Apple macOS перешли на компилятор Clang , [10] в основном из-за лицензионных соображений. [11] [12] [13] GCC также может компилировать код для Windows , Android , iOS , Solaris , HP-UX , AIX и DOS . [14]
В конце 1983 года, пытаясь запустить операционную систему GNU , Ричард Столлман попросил Эндрю С. Таненбаума , автора Amsterdam Compiler Kit (также известного как Free University Compiler Kit ), разрешить использовать это программное обеспечение для GNU. Когда Таненбаум сообщил ему, что компилятор не является бесплатным, и что свободным является только университет, Столлман решил работать над другим компилятором. [15] Его первоначальный план состоял в том, чтобы переписать существующий компилятор из Lawrence Livermore National Laboratory с Pastel на C с некоторой помощью от Len Tower и других. [16] [17] Столлман написал новый C-фронтенд для компилятора Livermore, но затем понял, что для этого требуются мегабайты стекового пространства, что невозможно на системе Unix 68000 с всего лишь 64 КБ, и пришел к выводу, что ему придется написать новый компилятор с нуля. [16] Ни один из кодов компилятора Pastel не попал в GCC, хотя Столлман использовал написанный им интерфейс на языке C. [16] [18]
GCC был впервые выпущен 22 марта 1987 года, доступен по FTP из MIT . [19] Столлман был указан как автор, но цитировал и других за их вклад, включая Tower за «части синтаксического анализатора, генератора RTL, определения RTL и описание машины Vax», Джека Дэвидсона и Кристофера В. Фрейзера за идею использования RTL в качестве промежуточного языка, а также Пола Рубина за написание большей части препроцессора. [20] Описанный Питером Х. Салусом как «первый хит свободного программного обеспечения» , компилятор GNU появился как раз в то время, когда Sun Microsystems отделяла свои инструменты разработки от своей операционной системы , продавая их отдельно по более высокой общей цене, чем предыдущий пакет, что заставило многих пользователей Sun покупать или загружать GCC вместо инструментов поставщика. [21] Хотя Столлман считал GNU Emacs своим основным проектом, к 1990 году GCC поддерживал тринадцать компьютерных архитектур, превосходил по производительности несколько компиляторов других поставщиков и использовался в коммерческих целях несколькими компаниями. [22]
Поскольку GCC лицензировался по GPL, программисты, желающие работать в других направлениях — в частности, те, кто писал интерфейсы для языков, отличных от C, — могли свободно разрабатывать свои собственные ответвления компилятора, при условии, что они соответствуют условиям GPL, включая ее требования по распространению исходного кода . Однако множественные ответвления оказались неэффективными и громоздкими, а сложность в принятии работы официальным проектом GCC была для многих весьма разочаровывающей, поскольку проект отдавал предпочтение стабильности, а не новым функциям. [23] FSF так пристально контролировал то, что добавлялось в официальную версию GCC 2.x (разрабатывавшуюся с 1992 года), что GCC был использован в качестве одного из примеров «соборной» модели разработки в эссе Эрика С. Рэймонда «Собор и базар» .
В 1997 году группа разработчиков сформировала Experimental/Enhanced GNU Compiler System (EGCS) для объединения нескольких экспериментальных форков в один проект. [23] [18] Основой слияния стал снимок разработки GCC (сделанный около 2.7.2 и позже продолженный до релиза 2.8.1). Слияния включали g77 (Fortran), PGCC ( P5 Pentium -оптимизированный GCC), [18] множество улучшений C++ и множество новых архитектур и вариантов операционных систем . [24]
Хотя оба проекта внимательно следили за изменениями друг друга, разработка EGCS оказалась значительно более энергичной, настолько, что FSF официально остановил разработку своего компилятора GCC 2.x, благословил EGCS как официальную версию GCC и назначил проект EGCS в качестве сопровождающих GCC в апреле 1999 года. С выпуском GCC 2.95 в июле 1999 года два проекта снова объединились. [25] [18] С тех пор GCC поддерживается разнообразной группой программистов со всего мира под руководством руководящего комитета. [26]
GCC 3 (2002) удалил интерфейс для CHILL из- за отсутствия поддержки. [27]
До версии 4.0 интерфейс Fortran был g77
, который поддерживал только FORTRAN 77 , но позже от него отказались в пользу нового интерфейса GNU Fortran , который также поддерживает Fortran 95 и большую часть Fortran 2003 и Fortran 2008. [28] [29]
Начиная с версии 4.8, GCC реализован на языке C++. [30]
Поддержка Cilk Plus существовала с GCC 5 по GCC 7. [31] [32]
GCC был портирован на широкий спектр архитектур наборов инструкций и широко используется в качестве инструмента при разработке как свободного, так и проприетарного программного обеспечения . GCC также доступен для многих встраиваемых систем , включая Symbian (называемый gcce ), [33] чипы на базе ARM и Power ISA . [34] Компилятор может быть ориентирован на широкий спектр платформ, включая игровые консоли , такие как PlayStation 2 , [35] Cell SPE PlayStation 3, [36] и Dreamcast . [37] Он был портирован на большее количество типов процессоров и операционных систем, чем любой другой компилятор. [38] [ самостоятельно опубликованный источник? ] [ необходим лучший источник ]
Начиная с версии 13.1, [обновлять]GCC включает интерфейсы для языков программирования C ( gcc
), C++ ( g++
), Objective-C и Objective-C++ , Fortran ( gfortran
), Ada ( GNAT ), Go ( gccgo
), D ( gdc
, начиная с версии 9.1), [39] [40] и Modula-2 ( gm2
, начиная с версии 13.1) [41] [42] , [43] с параллельными языковыми расширениями OpenMP и OpenACC, поддерживаемыми с версии GCC 5.1. [9] [44] Версии до GCC 7 также поддерживали Java ( gcj
), позволяя компилировать Java в машинный код. [45]
Что касается поддержки версий языка для C++ и C, начиная с GCC 11.1 целью по умолчанию является gnu++17 , надмножество C++17 , и gnu11 , надмножество C11 , с также доступной строгой стандартной поддержкой. GCC также обеспечивает экспериментальную поддержку для C++20 и C++23 . [46]
Существуют сторонние интерфейсы для многих языков, таких как Pascal ( gpc
), Modula-3 и VHDL ( GHDL
). [43] Существует несколько экспериментальных ветвей для поддержки дополнительных языков, таких как компилятор GCC UPC для Unified Parallel C [47] или Rust . [48] [49] [50] [ требуется лучший источник ]
Внешний интерфейс GCC следует соглашениям Unix . Пользователи вызывают программу драйвера, специфичную для языка ( gcc
для C, g++
для C++ и т. д.), которая интерпретирует аргументы команды , вызывает фактический компилятор, запускает ассемблер на выходе, а затем опционально запускает компоновщик для создания полного исполняемого двоичного файла.
Каждый из компиляторов языка представляет собой отдельную программу, которая считывает исходный код и выводит машинный код . Все они имеют общую внутреннюю структуру. Интерфейс для каждого языка анализирует исходный код на этом языке и создает абстрактное синтаксическое дерево (сокращенно «дерево»).
Они, при необходимости, преобразуются в представление ввода среднего конца, называемое формой GENERIC ; затем средний конец постепенно преобразует программу в ее окончательную форму. Оптимизации компилятора и методы статического анализа кода (такие как FORTIFY_SOURCE, [51] директива компилятора, которая пытается обнаружить некоторые переполнения буфера ) применяются к коду. Они работают с несколькими представлениями, в основном с архитектурно-независимым представлением GIMPLE и архитектурно-зависимым представлением RTL . Наконец, машинный код создается с использованием архитектурно-специфического сопоставления шаблонов , изначально основанного на алгоритме Джека Дэвидсона и Криса Фрейзера.
GCC был написан в основном на языке C, за исключением частей интерфейса Ada . Дистрибутив включает стандартные библиотеки для Ada и C++ , код которых в основном написан на этих языках. [52] [ требуется обновление ] На некоторых платформах дистрибутив также включает низкоуровневую библиотеку времени выполнения libgcc , написанную в сочетании машинно-независимого C и процессорно-специфического машинного кода , предназначенную в первую очередь для обработки арифметических операций, которые целевой процессор не может выполнять напрямую. [53]
GCC использует множество дополнительных инструментов в своей сборке, многие из которых устанавливаются по умолчанию многими дистрибутивами Unix и Linux (но которые, как правило, отсутствуют в установках Windows), включая Perl , [ необходимо дополнительное объяснение ] Flex , Bison и другие распространенные инструменты. Кроме того, в настоящее время для сборки требуется наличие трех дополнительных библиотек: GMP , MPC и MPFR . [54]
В мае 2010 года руководящий комитет GCC решил разрешить использование компилятора C++ для компиляции GCC. [55] Компилятор должен был быть написан в основном на C плюс подмножество функций из C++. В частности, это было решено для того, чтобы разработчики GCC могли использовать деструкторы и функции generics из C++. [56]
В августе 2012 года руководящий комитет GCC объявил, что теперь GCC использует C++ в качестве языка реализации. [57] Это означает, что для сборки GCC из исходников требуется компилятор C++, который понимает стандарт ISO/IEC C++03 .
18 мая 2020 года GCC перешел от стандарта ISO/IEC C++03 к стандарту ISO/IEC C++11 (то есть необходимому для компиляции, начальной загрузки самого компилятора; однако по умолчанию он компилирует более поздние версии C++). [58]
Каждый фронтенд использует парсер для создания абстрактного синтаксического дерева заданного исходного файла . Благодаря абстракции синтаксического дерева исходные файлы любого из различных поддерживаемых языков могут обрабатываться одним и тем же бэкендом . GCC начинал с использования парсеров LALR, сгенерированных с помощью Bison , но постепенно перешел на написанные вручную парсеры рекурсивного спуска для C++ в 2004 году [59] и для C и Objective-C в 2006 году [60]. С 2021 года все фронтенды используют написанные вручную парсеры рекурсивного спуска.
До GCC 4.0 древовидное представление программы не было полностью независимым от целевого процессора. Значение дерева несколько различалось для разных языковых интерфейсов, и интерфейсы могли предоставлять свои собственные коды деревьев. Это было упрощено с введением GENERIC и GIMPLE, двух новых форм языково-независимых деревьев, которые были введены с появлением GCC 4.0. GENERIC более сложен, основан на промежуточном представлении интерфейса Java GCC 3.x. GIMPLE — это упрощенный GENERIC, в котором различные конструкции сведены к нескольким инструкциям GIMPLE. Интерфейсы C , C++ и Java создают GENERIC непосредственно во внешнем интерфейсе. Другие интерфейсы вместо этого имеют другие промежуточные представления после синтаксического анализа и преобразуют их в GENERIC.
В любом случае так называемый «гимплификатор» затем преобразует эту более сложную форму в более простую форму GIMPLE на основе SSA , которая является общим языком для большого количества мощных независимых от языка и архитектуры глобальных (область действия функции) оптимизаций.
GENERIC — это промежуточный язык представления , используемый в качестве «среднего конца» при компиляции исходного кода в исполняемые двоичные файлы . Подмножество, называемое GIMPLE , предназначено для всех фронтендов GCC.
Средний этап GCC выполняет весь анализ и оптимизацию кода , работая независимо как от скомпилированного языка, так и от целевой архитектуры, начиная с представления GENERIC [61] и расширяя его до языка передачи регистров (RTL). Представление GENERIC содержит только подмножество императивных программных конструкций, оптимизированных средним этапом.
При преобразовании исходного кода в GIMPLE [62] сложные выражения разбиваются на трехадресный код с использованием временных переменных . Это представление было вдохновлено представлением SIMPLE, предложенным в компиляторе McCAT [63] Лори Дж. Хендрен [64] для упрощения анализа и оптимизации императивных программ .
Оптимизация может происходить на любом этапе компиляции; однако основная часть оптимизаций выполняется после синтаксического и семантического анализа передней части и до генерации кода задней части; поэтому общепринятое, хотя и несколько противоречивое, название этой части компилятора — «средняя часть».
Точный набор оптимизаций GCC меняется от версии к версии по мере его развития, но включает стандартные алгоритмы, такие как оптимизация циклов , потоковая передача скачков , устранение общих подвыражений , планирование инструкций и т. д. Оптимизации RTL имеют меньшее значение с добавлением глобальных оптимизаций на основе SSA в деревьях GIMPLE [65] , поскольку оптимизации RTL имеют гораздо более ограниченную область действия и содержат меньше высокоуровневой информации.
Некоторые из этих оптимизаций, выполняемых на этом уровне, включают устранение мертвого кода , устранение частичной избыточности , глобальную нумерацию значений , распространение разреженных условных констант и скалярную замену агрегатов. Также выполняются оптимизации на основе зависимости массива, такие как автоматическая векторизация и автоматическое распараллеливание . Также возможна оптимизация на основе профиля . [66]
Проект GCC включает реализацию стандартной библиотеки C++ под названием libstdc++ [67], лицензированной по лицензии GPLv3 с исключением для связывания не-GPL-приложений, когда исходники собираются с помощью GCC. [68]
Некоторые особенности GCC включают в себя:
-fgnu-tm
. [8] [73]typeof
выражения. [77]Основными поддерживаемыми (и наиболее протестированными) семействами процессоров являются 64- и 32-битные ARM, 64- и 32-битные x86_64 и x86 и 64-битные PowerPC и SPARC . [78]
Семейства целевых процессоров GCC начиная с версии 11.1 включают: [79]
Менее известные целевые процессоры, поддерживаемые в стандартной версии, включают:
Дополнительные процессоры поддерживаются версиями GCC, которые поддерживаются отдельно от версии FSF:
Компилятор GCJ Java может быть нацелен либо на архитектуру машинного языка, либо на байт-код Java виртуальной машины Java . [ 82] При перенацеливании GCC на новую платформу часто используется самозагрузка . Motorola 68000, Zilog Z80 и другие процессоры также нацелены на версии GCC, разработанные для различных программируемых графических калькуляторов Texas Instruments, Hewlett Packard, Sharp и Casio. [83]
GCC лицензирован в соответствии с GNU General Public License версии 3. [84] Исключение времени выполнения GCC позволяет компилировать проприетарные программы (в дополнение к свободному программному обеспечению) с заголовками GCC и библиотеками времени выполнения. Это не влияет на условия лицензии исходного кода GCC. [85]
Поэтому он написал автору VUCK, спрашивая, может ли GNU использовать его. Очевидно, разработчик VUCK отказался сотрудничать, ответив, что университет был свободен, но компилятор — нет.
был портирован (т. е. модифицирован для работы) на более чем 60 платформах, что больше, чем для любого другого компилятора.
{{cite web}}
: CS1 maint: бот: исходный статус URL неизвестен ( ссылка )