Открыть сервисСервис

Компиляция — процесс перевода программного кода

Компиляция — процесс перевода исходного кода компьютерной программы, написанного на языке программирования высокого уровня, в эквивалентный программный код на более низком уровне (обычно в машинный код), пригодный для выполнения процессором. Программа, выполняющая эту функцию, называется компилятором. Термин происходит от англ. to compile — «составлять, собирать».

Принцип работы

Компилятор осуществляет последовательное преобразование текста программы. На вход подаётся исходный файл (или набор файлов) с кодом на исходном языке, на выходе — объектный модуль, содержащий машинные инструкции, либо исполняемый файл. Между этими точками выполняется ряд стадий:

  1. Лексический анализ — исходный текст разбивается на лексемы (токены): идентификаторы, ключевые слова, операторы, константы.
  2. Синтаксический анализ — построение синтаксического дерева (AST) на основе грамматики языка; проверка соответствия кода синтаксическим правилам.
  3. Семантический анализ — проверка типов, области видимости переменных, корректности ссылок на функции и переменные.
  4. Оптимизация — преобразования, улучшающие эффективность результирующего кода: удаление недостижимого кода, свёртка констант, разворачивание циклов, инлайнизация функций.
  5. Генерация кода — трансляция оптимизированного представления в машинный код целевой архитектуры (x86, ARM, RISC-V и др.).

Однопроходные и многопроходные компиляторы

Однопроходные компиляторы обрабатывают исходный текст за один проход, преобразуя его фрагменты по мере чтения. Такой подход прост и экономит память, но ограничивает возможности оптимизации и требует, чтобы объявления предшествовали использованию. Многопроходные компиляторы строят внутреннее представление программы и работают с ним на нескольких этапах, что позволяет выполнять более сложные преобразования. Большинство современных компиляторов — многопроходные.

JIT-компиляция

Компиляция во время выполнения (JIT, от англ. just-in-time) — метод, при котором отдельные фрагменты программы компилируются непосредственно в момент исполнения. Используется в виртуальных машинах Java (JVM), .NET CLR, в интерпретаторах JavaScript (V8, SpiderMonkey). JIT-компилятор сочетает преимущества интерпретации (портабельность, отсутствие стадии предварительной сборки) и компиляции (высокая скорость выполнения), компилируя «горячие» участки кода — те, которые выполняются наиболее часто.

Компиляция и интерпретация

Альтернатива компиляции — интерпретация, при которой исходный код выполняется построчно без предварительного перевода в машинный код. Интерпретатор проще в реализации и удобен для отладки, однако программы, как правило, работают медленнее. На практике часто используются гибридные схемы: код компилируется в промежуточное байт-кодное представление, которое затем исполняется интерпретатором или JIT-компилятором. Примеры таких языков — Python, Ruby, PHP.

Компиляторы и транспайлеры

Не все инструменты, переводящие код с одного языка на другой, являются классическими компиляторами. Транспайлер (компилятор с исходного языка на другой язык высокого уровня) генерирует читаемый код, а не машинный: например, TypeScript компилируется в JavaScript, CoffeeScript — также в JavaScript, Emscripten транслирует C и C++ в WebAssembly. Результат работы транспайлера обычно подвергается дальнейшей обработке стандартным компилятором целевого языка.

Известные компиляторы

КомпиляторЯзыкРазработчик
GCCC, C++, Fortran, AdaПроект GNU
Clang / LLVMC, C++, Objective-CLLVM Project, Apple
MSVCC, C++Microsoft
rustcRustMozilla, сообщество Rust
javacJavaOracle
Go compilerGoGoogle

Стандарты и спецификации

Для ряда языков существуют официальные спецификации, которым обязаны следовать все компиляторы. Например, стандарт ISO C++ определяет семантику языка, а тестовый набор test suite (например, «Abi Tests» и «Compile Fail Tests») позволяет проверить корректность реализации. Отклонения от стандарта считаются ошибками компилятора, хотя на практике существуют расширения и диалекты (GNU C++, MSVC extensions).

Перекрёстная компиляция

Перекрёстная компиляция — создание исполняемых файлов для одной платформы (целевой) с использованием инструментов другой (хостовой). Широко применяется при разработке встраиваемых систем, прошивок, а также при сборке программ для ARM-устройств на x86-компьютерах. Кросс-компилятор содержит генератор кода, настроенный на целевую архитектуру, и набор библиотек целевой среды.

Роль в разработке ПО

Компиляция — ключевой этап процесса сборки (build) программного проекта. Системы сборки (Make, CMake, Ninja, Bazel) отслеживают зависимости между файлами и запускают компилятор только для изменившихся модулей, после чего линковщик объединяет объектные файлы в единый исполняемый модуль. Скорость компиляции крупных проектов — важная практическая проблема: например, полная сборка Chromium или LLVM занимает десятки минут даже на мощных машинах, что стимулирует разработку инкрементальных и распределённых систем сборки.

История

Первым работающим компилятором считается A-0, созданный Грейс Хоппер в 1952 году для машины UNIVAC I. Он переводил символический код в машинный. Развитие компиляторов тесно связано с созданием языков Fortran (1957, IBM), COBOL, ALGOL, что заложило основы современного понимания структуры компилятора и методов оптимизации.

Источники

  • Дональд Кнут. «Основы программирования» (Том 1–3)
  • Альфред Ахо, Мони Лам, Рави Сети, Jeffrey Ullman. «Компиляторы: принципы, технологии и инструменты»
  • Steven Muchnick. «Advanced Compiler Design and Implementation»
  • Спецификации языков C++, Rust, Java (официальные документации)
Заметили ошибку или не согласны с информацией в статье? Напишите нам support@bfometr.ru