Компиля́тор —
Компиляция —
Компилировать — проводить трансляцию машинной программы с проблемно-ориентированного языка на машинно-ориентированный язык.[3]
Содержание
|
Большинство компиляторов переводит программу с некоторого высокоуровневого языка программирования в машинный код, который может быть непосредственно выполнен центральным процессором. Как правило, этот код также ориентирован на исполнение в среде конкретной операционной системы, поскольку использует предоставляемые ею возможности (системные вызовы, библиотеки функций). Архитектура (набор программно-аппаратных средств), для которой производится компиляция, называется целевой машиной.
Некоторые компиляторы (например, низкоуровневом языке. Такой язык — байт-код — также можно считать языком машинных команд, поскольку он подлежит интерпретации виртуальной машиной. Например, для языка Java это JVM (язык виртуальной машины Java), или так называемый байт-код Java (вслед за ним все промежуточные низкоуровневые языки стали называть байт-кодами). Для языков программирования на платформе .NET Framework (C#, Managed C++, Visual Basic .NET и другие) — это MSIL (Microsoft Intermediate Language).
Программа на байт-коде подлежит интерпретации виртуальной машиной, либо ещё одной компиляции уже в машинный код непосредственно перед исполнением. Последнее называется «Just-In-Time компиляция» (MSIL-код компилируется в код целевой машины также JIT-компилятором, а библиотеки .NET Framework компилируются заранее).
Для каждой целевой машины (Apple и т. д.) и каждой операционной системы или семейства операционных систем, работающих на целевой машине, требуется написание своего компилятора. Существуют также так называемые кросс-компиляторы, позволяющие на одной машине и в среде одной ОС получать код, предназначенный для выполнения на другой целевой машине и/или в среде другой ОС. Кроме того, компиляторы могут быть оптимизированы под разные типы процессоров из одного семейства (путём использования специфичных для этих процессоров инструкций). Например, код, скомпилированный под процессоры семейства MMX, SSE2.
Также существуют компиляторы, переводящие программу с языка высокого уровня на язык ассемблера.
Существуют программы, которые решают обратную задачу — перевод программы с низкоуровневого языка на высокоуровневый. Этот процесс называют декомпиляцией, а программы — декомпиляторами. Но поскольку компиляция — это процесс с потерями, точно восстановить исходный код, скажем, на C++, в общем случае невозможно. Более эффективно декомпилируются программы в байт-кодах — например, существует довольно надёжный декомпилятор для Flash. Сходным процессом является дизассемблирование машинного кода в код на языке ассемблера, который всегда выполняется успешно. Связано это с тем, что между кодами машинных команд и командами ассемблера имеется практически однозначное соответствие.
Процесс компиляции состоит из следующих этапов:
В конкретных реализациях компиляторов эти этапы могут быть раздельны или совмещены в том или ином виде.
Важной исторической особенностью компилятора, отражённой в его названии (англ. compile — собирать вместе, составлять), являлось то, что он мог производить и компоновку (то есть содержал две части — транслятор и компоновщик). Это связано с тем, что раздельная компиляция и компоновка как отдельная стадия сборки выделились значительно позже появления компиляторов, и многие популярные компиляторы (например, GCC) до сих пор физически объединены со своими компоновщиками. В связи с этим, вместо термина «компилятор» иногда используют термин «транслятор» как его синоним: либо в старой литературе, либо когда хотят подчеркнуть его способность переводить программу в машинный код (и наоборот, используют термин «компилятор» для подчёркивания способности собирать из многих файлов один).
Компиляция и установка программ из исходников
Распаковка
Сборка пакета
Установка
Правильная установка(Вариант №1)
Правильная установка(Вариант №2)
Установка (вариант №3)
Неправильная установка
Ошибки
Необходимое программное обеспечение
Ссылки
Не редко необходимые пакеты можно найти только в виде исходных текстов, в данной статье описывается метод установки пакета из исходных текстов.
Программы обычно распространяются в упакованных архивах, это файлы с расширениями
<some_app_name>.tar.gz (иногда .tgz) <some_app_name>.tar.bz2
Нужно понимать отличие между архиватором и упаковщиком.
Для архивации директорий и файлов используется программа tar; результатом её работы является файл с расширением .tar. Грубо говоря, это копия файловой системы — директорий и файлов с их атрибутами и правами доступа, помещённая в один файл.
Данный файл по размеру будет чуть больше, чем суммарный размер файлов, которые были архивированы. Поэтому (а может и по другой причине) используют упаковщики — программы, которые позволяют уменьшить размер файла без потери данных.
Программа tar умеет распаковывать, поэтому не нужно вызывать gunzip, а можно просто указать программе tar, что файл нужно cначала распаковать. Например, команда
tar -xvf <some_app_name>. tar.gz
сразу распакует и разархивирует. Отличие файлов с расширениями
<some_app_name>.tar.gz
и
<some_app_name>.tar.bz2
лишь в том, что использовались разные упаковщики, программа tar определяет метод сжатия автоматически и дополнительных опций в данном случае не требуется.
После распаковки необходимо перейти в полученный каталог, все описываемые ниже команды выполняются в каталоге с исходными текстами пакета.
cd <имя_пакета>*
Для сборки программ в GNU/Linux используется (в основном) программа make, которая запускает инструкции из Makefile, но поскольку дистрибутивов GNU/Linux много, и они все разные, то для того чтобы собрать программу, нужно для каждого дистрибутива отдельно прописывать пути,где какие лежат библиотеки и заголовочные файлы. Программисты не могут изучать каждый дистрибутив и для каждого отдельно создавать Makefile. Поэтому придумали конфигураторы, которые «изучают» систему, и в соответствии с полученными знаниями создают Makefile. Но на конфигураторе они не остановились и придумали конфигураторы конфигураторов …на этом они остановились
Для сборки нам нужны компиляторы: они прописаны в зависимостях пакета build-essential, так что достаточно установить его со всеми зависимостями. Ещё нужны autoconf и automake.
Итак, чтобы собрать что-то из исходников, нужно сначала собрать конфигуратор; как собрать конфигуратор, описано в файле configure.in. Для сборки конфигуратора необходимо выполнить
./bootstrap
или
./autogen.sh
Если таких скриптов в архиве не оказалось, то можно выполнить последовательно следующие команды:
aclocal autoheader automake --gnu --add-missing --copy --foreign autoconf -f -Wall
Все эти команды используют файл configure.in. После выполнения этих команд создастся файл configure. После этого необходимо запустить конфигуратор для проверки наличия всех зависимостей, а также установки дополнительных опций сборки (если возможно) и просмотра результата установки (опционально- может не быть)
. /configure
Конфигуратор построит Makefile основываясь на полученных знаниях и файле makefile.am. Можно передать конфигуратору опции, предусмотренные в исходниках программы, которые позволяют включать/отключать те или иные возможности программы, обычно узнать о них можно командой
./configure --help
Также есть набор стандартных опций, вроде
--prefix=
, которая указывает, какой каталог использовать для установки. Для Ubuntu обычно
--prefix=/usr
или
--prefix=/usr/local
БЕЗ слеша в конце! Теперь можно запустить процесс сборки самой программы командой
make
Для сборки достаточно привелегий обычного пользователя. Окончанием сборки можно считать момент, когда команды в консоли перестанут «беспорядочно» выполняться и не будет слова error. Теперь всё скомпилировано и готово для установки.
Усилия потраченные на Правильную установку
в последствии с лихвой окупятся в случае удаления или обновления устанавливаемого программного обеспечения.
Установка при помощи утилиты checkinstall. Для установки выполните
sudo apt-get install checkinstall
Минус данного способа: checkinstall понимает не все исходники, поскольку автор программы может написать особые скрипты по установке и checkinstall их не поймёт.
Для создания и установки deb-пакета необходимо выполнить
sudo checkinstall
Быстрое создание deb-пакета «вручную».
Основное отличие от предыдущего способа заключается в том, что в данном случае вы создаете пакет вручную и отслеживаете все вносимые изменения. Так же этот способ подойдет вам, если исходники не поддерживают сборку пакета с checkinstall.
Производим установку во временную директорию, где получаем весь набор устанавливаемых файлов:
fakeroot make install DESTDIR=`pwd`/tempinstall
Создадим в «корне пакета» директорию DEBIAN и сложим в DEBIAN/conffiles список всех файлов, которые должны попасть в /etc:
сd tempinstall mkdir DEBIAN find etc | sed "s/^/\//" > DEBIAN/conffiles
Package: имя_пакета Version: 1. 2.3 Architecture: amd64/i386/armel/all Maintainer: Можете вписать своё имя, можете дребедень, но если оставить пустым, то dpkg будет ругаться Depends: Тут можно вписать список пакетов через запятую. Priority: optional Description: Тоже надо что-нибудь вписать, чтобы не кидало предупреждения
При необходимости там же можно создать скрипты preinst, postinst, prerm и postrm.
Создаем deb-пакет, для чего выполняем:
dpkg -b tempinstall
Получаем на выходе tempinstall.deb, который и устанавливаем
sudo dpkg -i tempinstall.deb
Процедура создания deb-пакета подробно описана в данной статье.
Минус данного способа заключается в том, что если вы устанавливаете напрямую через make install, то нормально удалить или обновить пакет вы, скорее всего, не сможете. Более того, установка новой версии поверх старой, скорее всего, затрёт ваши изменения в конфигах. make install делает ровно то, что ему сказано — производит установку файлов в нужные места, игнорируя тот факт, что там что-то уже есть. После этого процесса совершенно никакой информации о том, что и куда ставилось, получить в удобоваримом виде невозможно. Иногда, конечно, Makefile поддерживает действие uninstall, но это встречается не так часто, да и не факт, что корректно работает. Кроме того, вам будет необходимо хранить для деинсталяции распакованное дерево исходников и правил сборки.
Для установки необходимо выполнить
sudo make install
Для удаления пакета, установленного данным способом необходимо выполнить в корневой директории исходников программы (там где вы запускали make install).
sudo make uninstall
Часто на этапе конфигурации конфигуратор сообщает, что нехватает той или иной библиотеки. Название библиотеки, которое он сообщает, не всегда соответствует названию пакета в Ubuntu. Из собственного опыта могу посоветовать поискать в Синаптике нужный пакет, исключив префикс lib, если нашлось несколько пакетов различающихся приставкой -dev в названии, то вам нужно установить именно -dev пакет (обычно он тянет за собой и не -dev пакет). Можно ещё поискать с помощью http://packages.ubuntu.com/, введя имя библиотеки в поиск по содержимому пакетов, аналогично, если найдётся dev и не dev, нужны оба . Ну или просто поискать в Google.
Пакеты с буквами mm в конце описания — это пакеты для C++ программ. Список для bmpx, но подойдёт почти для любой GTK2/Gnome программы. Так что если не получается собрать, то посмотрите на этот список и сверьте с тем что у вас установлено.
Compile: | Runtime: | |
---|---|---|
X | libx11-dev | libx11-6 |
GlibMM | libglibmm-2.4-dev | libglibmm-2.4-1c2a |
GTK+ | libgtk2.0-dev,gtk-doc-tools | libgtk2.0-0 |
GTKMM | libgtkmm-2.4-dev | libgtkmm-2.4-1c2a |
Glade | libglade2-dev | libglade2-0 |
GladeMM | libglademm-2.4-dev | libglademm-2.4-1c2a |
XML | libxml2-dev | libxml2 |
XML++ | libxml++2. 6-dev | libxml++2.6c2a |
DBus | libdbus-1-dev,libdbus-glib-1-dev | libdbus-1-2,libdbus-glib-1-2 |
Alsa | libasound2-dev | libasound2 |
HAL | libhal-dev,libhal-storage-dev | libhal1,libhal-storage1 |
Gamin | libgamin-dev | libgamin0 |
Neon | libneon25-dev | libneon25 |
TagLib | libtagc0-dev | libtagc0 |
Startup-Notify | libstartup-notification0-dev | libstartup-notification0 |
Boost | libboost-dev,libboost-filesystem-dev | libboost-filesystem1.33.1 |
MusicBrainz | libmusicbrainz4-dev | libmusicbrainz4c2a |
GStreamer | libgstreamer0.10-dev,libgstreamer-plugins-base0.10-dev | libgstreamer0.10-0,libgstreamer-plugins-base0.10-0 |
Обсуждение проблем с компиляцией и установкой программ в Ubuntu на форуме forum. ubuntu.ru
Внесены изменения по мотивам Хабрахабр
Подробной HowTo по сборке бинарных deb пакетов
Howto, установка, компиляция, программирование, исходники
Процесс компиляции исходного кода C представляет собой многоэтапный процесс, который включает предварительную обработку , компиляцию кода , связывание библиотек и т. д. В этом руководстве мы рассмотрим узнать, как код C компилируется в объектный код.
Процесс преобразования исходного кода, написанного на любом языке программирования (как правило, на языке среднего или высокого уровня) в язык машинного уровня , понятный компьютеру, известен как Компиляция . Программное обеспечение, используемое для этого преобразования, известно как компилятор .
В языке C посредством компиляции исходный код языка C преобразуется в объектный код .
Компилятор принимает вход , который является исходным кодом , и обеспечивает вывод в форме объектного кода . Полный процесс компиляции на языке C далее делится на четыре фазы:
Предварительная обработка ,
Компиляция ,
Сборка и
Связывание
Компилятор проверяет исходный код на наличие любых синтаксических или структурных ошибок и после проверки, если исходный код не содержит ошибок, генерирует объектный код с расширением .obj (для Windows) или .o (для Linux).
Давайте теперь посмотрим на различные этапы процесса компиляции на языке C.
Как упоминалось выше, различные этапы процесса компиляции следующие:
Предварительная обработка
Компиляция
Сборка
Связывание
В блок-схеме ниже мы объяснили, как работает процесс компиляции и каковы различные этапы компиляции исходного кода на языке C.
Рассмотрим все эти этапы компиляции исходного кода на языке Си в порядке их выполнения.
На этом этапе выполняется предварительная обработка исходного файла. Препроцессор — это программа, которая принимает файл исходного кода C, а затем выполняет следующие задачи:
Это удалит комментарии из исходного кода.
Он выполнит Расширение макроса , если используется какой-либо макрос (не беспокойтесь о макросах, мы узнаем о них позже)
Выполнит расширение включенных заголовочных файлов.
Это программа, которая обрабатывает исходную программу перед передачей ее компилятору. На этом этапе обрабатываются препроцессоры, используемые в любой программе на C, и исходный код подготавливается к компиляции.
Каждый оператор предварительной обработки должен начинаться с #
, где #
называется директивой препроцессора .
Каждая директива предварительной обработки представляет собой однострочный оператор кода.
Слово после #
называется командой препроцессора .
Вот некоторые из директив препроцессора:
1. #include
Чтобы включить конкретный заголовок, используя имя файла заголовка, в код программы на языке C.
2. #define
Используется для определения макроса на языке C.
3. #error
Эта команда препроцессора используется для печати сообщения об ошибке.
Как и в предыдущих трех, существует много других препроцессоров, мы подробно рассмотрим их в отдельном руководстве.
Следовательно, препроцессор расширяет исходный код (добавляет необходимую информацию), а затем этот расширенный исходный код передается компилятору.
Он дает расширение ( .i ) файлу исходного кода , который изначально имеет расширение ( . c ).
Расширенный код препроцессора затем передается компилятору. Как мы знаем, компилятор — это программа, которая преобразует код языка высокого уровня (или языка среднего уровня ) в ассемблерный код , который затем преобразуется в машинный код, понятный машине.
Таким образом, предварительно обработанный код, переданный препроцессором компилятору, затем преобразуется компилятором в ассемблерный код, который затем передается ассемблеру .
Исходный файл, получивший расширение ( .i ) на предыдущем шаге, преобразуется компилятором в расширение ( .s ).
Ассемблер преобразует ассемблерный код, полученный от компилятора, в объектный код . Расширение файла на этом шаге становится ( .obj ).
Не думайте, что Ассемблер — это отдельная программа, генерирующая объектный код. Ассемблер является частью процесса компиляции исходного кода языка C.
Когда на непрофессиональном языке мы говорим, что код C компилируется, это означает, что завершен полный процесс компиляции, охватывающий все эти шаги.
Компоновщик — это инструмент, который используется для связывания всех частей программы вместе в порядке выполнения. Код после этого этапа становится Код исполняемой машины .
Могут возникнуть ситуации, когда наша программа обращается к функциям, определенным в других файлах. Или, если код какой-то программы слишком велик, мы можем разбить его на два файла, которые будут компилироваться отдельно, а затем линковаться с помощью линкера.
В процессе компиляции языка C компоновщик играет очень важную роль.
Если ваша программа на языке C содержит заголовочный файл , и вы используете некоторую функцию, определенную в этом заголовочном файле, то компоновщик связать требуемый код объекта для функции в библиотеке с кодом объекта вашей программы и упаковать их вместе.
Аналогично, если код вашей программы слишком велик и вы разбиваете его на два файла, то оба файла с исходным кодом будут преобразованы в объектный код по отдельности, а затем компоновщик свяжет их и сделает код готовым к выполнению. Это также называется отдельной компиляцией .
Вот некоторые часто задаваемые вопросы, связанные с процессом компиляции языка C.
Это компьютерная программа, которая используется для преобразования исходного кода, написанного на языке программирования высокого или среднего уровня, в машинный код, который может быть выполнен, и машина может понять, что делать.
Препроцессор — это директива, используемая для указания компилятору предварительно обработать исходный код перед началом фактической компиляции. Есть некоторые части программы на языке C, которые можно указать с помощью препроцессора, который представляет собой не что иное, как операторы, которые должны выполняться в начале компиляции.
Файлы кода языка C с расширением .c также называются файлом исходного кода .
Компоновщик используется для связывания всех частей программы вместе для выполнения.
Если ваша программа на языке C содержит заголовочный файл , и вы используете некоторую функцию, определенную в этом заголовочном файле, то компоновщик свяжет требуемый код объекта для функции в библиотеке, в объектный код вашей программы и упаковать их вместе.
Аналогично, если код вашей программы слишком велик и вы разбиваете его на два файла, то оба файла с исходным кодом будут преобразованы в объектный код по отдельности, а затем компоновщик свяжет их и сделает код готовым к выполнению. Это также называется отдельной компиляцией .
Ниже приведены этапы компиляции на языке C:
Препроцессор (препроцессор)
Компилятор (компиляция)
Сборщик (сборка)
Линкер (связывание)
В этом уроке мы узнали, как компилируется код языка C, который мы будем писать в следующих уроках. Какие шаги выполняются при компиляции и что происходит на этих этапах?
Если после этого вы остались в замешательстве, не беспокойтесь, просто прочитайте его, и по мере того, как мы будем продвигаться по учебнику, вы все поймете.
Попробуйте наши интерактивные курсы бесплатно 🥳 😯 🤩
Подробнее →
Коллекция компиляторов GNU включает интерфейсы для С, С++, Objective-C, Фортран, Ada, Go и D, а также библиотеки для этих языков (libstdc++,…). GCC изначально был написан как компилятор для операционной системы GNU. Система GNU была разработана как 100% свободное программное обеспечение, свободное в том смысле, что что он уважает свобода пользователя. Мы стремимся предоставлять регулярные высококачественные релизы, над которыми мы хотим хорошо поработать нативных и перекрестных целей (включая GNU/Linux) и поощрять всех внести изменения или помочь тестирование ГЦК. Наши источники легко и бесплатно доступны через Git и еженедельно снимки. Основные решения о GCC принимаются руководящего комитета под руководством заявление о миссии.
|