Что такое компилятор
Содержание:
Microsoft Visual Studio Community
Для индивидуальных или начинающих программистов Microsoft Visual Studio Community включает в себя много важных инструментов из коммерческих версий проекта. Вы получите в свое распоряжение IDE, отладчик, оптимизирующий компилятор, редактор, средства отладки и профилирования. С помощью этого пакета можно разрабатывать программы для настольных и мобильных версий Windows, а также Android. Компилятор C++ поддерживает большинство функций ISO C++ 11, некоторые из ISO C++ 14 и C++ 17. В то же время компилятор C уже безнадежно устарел и не имеет даже надлежащей поддержки C99.
Программное обеспечение также поставляется с поддержкой построения программ на C#, Visual Basic, F# и Python. В то время, когда я писал эту статью, на сайте проекта утверждалось, что Visual Studio Community 2015 «бесплатный инструмент для индивидуальных разработчиков, проектов с открытым исходным кодом, научных исследований, образовательных проектов и небольших профессиональных групп».
Общие принципы
п.5.1.1.2п.5.2здесьздесь
- Фаза I — исходный файл поступает на вход препроцессора. Препроцессор делает подстановку содержимого указанных в #include файлов и раскрывает макросы. Соответствует фазам 1 — 4 драфтов C11 и C++17.
- Фаза II — препроцессированный файл поступает на вход компилятора и преобразуется в объектный. Соответствует фазам 5 — 7 драфта C11 и 5 — 8 драфта C++17.
- Фаза III — компоновщик связывает объектные файлы и предоставленные статические библиотеки, формируя исполняемую программу. Соответствует фазе 8 и 9 драфтов C11 и C++17 соответственно.
extern
#includeMSBuildMakeCMake
Зависимости при компиляции
#includeinclude-what-you-useReSharper C++CppCleanDoxygen + Graphviz
Foo.hBar.hobj Bar.h
iostreamiosfwdPimpliosfwd
/MPprocessMax -jNN обширного списка сборочных систем-G/MPCMakeLists.txt
/MP
Распределенная компиляция
- Масштабируемость — подцепляем машину, и теперь она может помогать в сборке.
- Эффективность распределенной компиляции зависит от производительности сети и каждой машины. Крайне рекомендуется схожая производительность каждой машины.
- Необходимость в идентичности окружения на всех машинах (версии компиляторов, библиотек и т.д.). Это особенно необходимо, если препроцессирование происходит на всех машинах.
- IncrediBuild
- distcc
- Icecream
Кэш компилятора
- Для Unix-подобных: ccache (GCC, Clang), cachecc1 (GCC).
- Для Windows: clcache (MSVC), cclash (MSVC).
CCACHE_PREFIX
Предварительно откомпилированные заголовочные файлы
iostreamсамым первымstdafx.hstdafx.cppstdafx.cpp/Yc«path-to-stdafx.h».pch/Yu«path-to-stdafx.h»/Yc/Yu/Fp«path-to-pch».pch#include «path-to-stdafx.h»/FI«path-to-stdafx.h».gchc-headerc++-header#include-includeздесьcotirestdafx.h
Single Compilation Unit
- Число компилируемых файлов заметно уменьшается, а значит, и число дисковых операций. Компилятор гораздо меньше обрабатывает одни и те же файлы и инстанцирует шаблоны. Это заметно отражается на времени сборки.
- Компилятор теперь может выполнять оптимизации, доступные компоновщику (Link time optimization/Whole program optimization).
- Несколько ухудшается инкрементальная сборка, поскольку изменение одного файла в составе Single Compilation Unit приводит к его перекомпиляции.
- При применении Unity Build становится невозможным использовать распределенную сборку.
- Нарушение ODR (совпадение имен макросов, локальных статических функций, глобальных статических переменных, переменных в анонимных пространствах имен).
- Коллизии имен вследствие применения using namespace.
- параллельной компиляции нескольких Single Compilation Unit с применением предкомпилированного заголовка;
- распределенной компиляции нескольких Single Compilation Unit с применением кэша компилятора.
этого
ZapccBoost.Math
Здесь
-fuse-ld=gold
Terminology
Well, if you’re still up to it, let’s now look at how compilers work:
Terminology:
- The «Host» is the environment where the compiler itself runs.
- The «Target» is where the compiled program is meant to run.
- The «run-time» is a set resources (libraries, processes, etc) that exist on the Target. Two machines with identical hardware that differ in availability of run-time resources are sometimes thought of as different targets, as a program might run on one but not the other.
- The «executable» is a file containing information necessary for the Target to launch the program. It can be a flat binary, but is usually more elaborate, containing for example linking and re-location information.
- The «link» signifies that the program knows how to interface with the run-time, and relies on the run-time for some of it’s functionality. It is created by the linker, and does not exist in free-standing programs (i.e. OS kernel).
If the host and the target are the same the product is a «native executable». This is what you see 99% of the time.
If the compiler is capable of producing an executable for a target different from the host, it’s a «cross-compiler».
If the compiler is capable of compiling itself, it’s «self-hosting».
Компилятор GCC. Первая программа на Windows
Последнее обновление: 18.05.2017
Для создания программ на Си необходим текстовый редактор, с помощью которого можно набрать исходный код. И также необходим компилятор,
который принимает файл с исходным кодом на Си и компилирует его в исполняемый файл.
При запуске установщика откроется следующее окно:
Нажмем на кнопку Next > и перейдем к следующему шагу:
Если версия ОС 64-битная, то в поле следует выбрать пункт x86_64. Остальные настройки
оставим по умолчанию и нажмем на кнопку Next >. На следующем шаге укажем путь, по которому будет устанавливаться пакет:
Можно оставить настройки по умолчанию. И после перехода к следующему шагу собственно начнется установка.
После завершения установки на жестком диске по пути, которое было выбрано для установки, появятся все необходимые файлы компиляторов.
В моем случае они находятся по пути C:\Program Files (x86)\mingw-w64\i686-7.1.0-posix-dwarf-rt_v5-rev0\mingw32\bin:
В зависимости от версии пакета точный путь может отличаться, но в любом случае все файлы будут располагаться по тому пути, который был указан на шаге установки.
В частности, файл gcc.exe как раз и будет представлять компилятор для языка Си.
Далее для упрощения запуска компилятора мы можем добавить путь к нему в Переменные среды. Для этого перейдем к окну
Система -> Дополнительные параметры системы -> Переменные среды:
И добавим путь к компилятору:
Итак, компилятор установлен, и теперь мы можем написать первую программу. Для этого потребуется любой текстовый редактор для набора исходного кода.
Можно взять распространенный редактор Notepad++ или даже обычный встроенный Блокнот.
Итак, создадим на жестком диске папку для исходных файлов. А в этой папке создадим новый файл, который назовем hello.c.
В моем случае файл hello.c находится в папке C:\c.
Теперь определим в файле hello.c простейший код, который будет выводить строку на консоль:
#include <stdio.h> // подключаем заголовочный файл stdio.h int main(void) // определяем функцию main { // начало функции printf("Hello World! \n"); // выводим строку на консоль return 0; // выходим из функции } // конец функции
Для вывода строки на консоль необходимо подключить нужный функционал. Для этого в начале файла идет строка
#include <stdio.h>
Директива include подключает заголовочный файл stdio.h, который содержит определение функции printf, которая нужна для вывода строки на консоль.
Далее идет определение функции int main(void). Функция main должна присутствовать в любой программе на Си, с нее собственно и начинается
выполнение приложения.
Ключевое слово int в определении функции говорит о том, что функция возвращает целое число.
А слово void в скобках указывает, что функция не принимает параметров.
Тело функции main заключено в фигурные скобки {}. В теле функции происходит вывод строки на консоль с помощью функции printf, в которую передается выводимая строка «Hello world!».
В конце осуществляем выход из функции с помощью оператора return. Так как функция должна возвращать целое число, то после return указывается число 0.
Ноль используется в качестве индикатора успешного завершения программы.
После каждого действия в функции ставятся точка с запятой.
Теперь скомпилируем этот файл. Для этого откроем командную строку Windows и вначале с помощью команды cd перейдем к папке с исходным файлом:
cd C:\c
Чтобы скомпилировать исходный код, необходимо компилятору gcc передать в качестве параметра файл hello.c:
gcc hello.c
После этого будет скомпилирован исполняемый файл, который в Windows по умолчанию называется a.exe. И мы можем обратиться к этому файлу, и в этом случае консоль выведет
строку «Hello World!», собственно как и прописано в коде.
НазадВперед
Brython — реализация Python для браузера
Brython, отмеченный как «реализация Python 3 для веб-программирования на стороне клиента», является популярным компилятором, который преобразует код Python в код JavaScript.
Адаптированный к среде HTML5, Brython поставляется с интерфейсом для объектов и событий DOM. Brython — это сокращение от Browser Python. Он может похвастаться широким функционалом, начиная от создания простых элементов документа и перетаскивания до трехмерной навигации. Компилятор Python работает в Firefox намного лучше, чем в Google Chrome. Brython поддерживает не только все современные настольные браузеры, но и так же мобильные веб-браузеры. Компилятор Python поставляется с консолью JavaScript, которую можно использовать для оценки времени выполнения некоторой программы JS по сравнению с ее эквивалентом Python в редакторе. Согласно официальному блогу Пьера Квентеля, создателя и ведущего разработчика Brython, Brython намного быстрее Pypy.js и Skulpt. В некоторых случаях компилятор Python работает даже быстрее, чем эталонная реализация Python, то есть CPython. Brython поддерживает большую часть синтаксиса Python 3, например генераторы и импорт библиотек. Он также обеспечивает поддержку нескольких модулей, принадлежащих дистрибутиву CPython, и поставляется с библиотеками для взаимодействия с элементами и событиями DOM. Поддержка последних спецификаций HTML5 / CSS3 также доступна в Brython, а компилятор Python может использовать популярные CSS-фреймворки, такие, как BootStrap и LESS.
Компилятор кода с C# компилятором
В платформа .NET Framework предоставляется интерфейс выполнения компиляторов. Класс реализует этот интерфейс и предоставляет доступ к экземплярам генератора C# и компилятора кода. Следующий пример кода создает экземпляр и использует его для получения ссылки на интерфейс.
После ссылки на интерфейс можно использовать его для компиляции исходных кодов. Вы передаете параметры компилятору с помощью класса. Пример:
В вышеуказанном коде объект использует объект, чтобы сообщить компилятору, что необходимо создать исполняемый файл (в отличие от DLL) и вы хотите вы выводить на диск результативную сборку. Вызов в том месте, где сборка компилироваться. Этот метод принимает объект параметров и исходный код, который является строкой. После компиляции кода можно проверить, были ли ошибки в компиляции. Вы используете возвращаемую ценность от объекта. Этот объект содержит коллекцию ошибок, которая содержит все ошибки, которые произошли во время компиляции.
Существуют другие варианты компиляции, например компиляторинг из файла. Вы также можете пакетной компиляции, что означает, что вы можете компиляции нескольких файлов или источников в то же время.
Компиляция программ Linux
Первое что нам понадобиться — это исходники самой программы. В этом примере мы будем собирать самую последнюю версию vim. Это вполне нейтральная программа, достаточно простая и нужная всем, поэтому она отлично подойдет для примера.
Получение исходников
Первое что нам понадобиться, это исходные коды программы, которые можно взять на GitHub. Вы можете найти исходники для большинства программ Linux на GitHub. Кроме того, там же есть инструкции по сборке:
Давайте загрузим сами исходники нашей программы с помощью утилиты git:
Также, можно было скачать архив на сайте, и затем распаковать его в нужную папку, но так будет удобнее. Утилита создаст папку с именем программы, нам нужно сделать ее рабочей:
Настройка configure
Дальше нам нужно запустить скрипт, который проверит нашу программу на совместимость с системой и настроит параметры компиляции. Он называется configure и поставляется разработчиками программы вместе с исходниками. Весь процесс компиляции описан в файле Makefile, его будет создавать эта утилита.
Если configure нет в папке с исходниками, вы можете попытаться выполнить такие скрипты чтобы его создать:
Также для создания этого скрипта можно воспользоваться утилитой automake:
Утилита automake и другие из ее набора генерируют необходимые файлы на основе файла Mackefile.am. Этот файл обязательно есть в большинстве проектов.
После того как вы получили configure мы можем переходить к настройке. Одним из огромных плюсов ручной сборки программ есть то, что вы можете сами выбрать с какими опциями собирать программу, где она будет размещена и какие дополнительные возможности стоит включить. Все это настраивается с помощью configure. Полный набор опций можно посмотреть, выполнив:
Рассмотрим наиболее часто используемые, стандартные для всех программ опции:
- —prefix=PREFIX — папка для установки программы, вместо /, например, может быть /usr/local/, тогда все файлы будут распространены не по основной файловой системе, а в /usr/local;
- —bindir=DIR — папка для размещения исполняемых файлов, должна находится в PREFIX;
- —libdir=DIR — папка для размещения и поиска библиотек по умолчанию, тоже в PREFIX;
- —includedir=DIR — папка для размещения man страниц;
- —disable-возможность — отключить указанную возможность;
- —enable-возможность — включить возможность;
- —with-библиотека — подобно enable активирует указанную библиотеку или заголовочный файл;
- —without-библиотека — подобное disable отключает использование библиотеки.
Вы можете выполнить configure без опций, чтобы использовать значения по умолчанию, но также можете вручную указать нужные пути. В нашем случае ./configure есть, и мы можем его использовать:
Во время настройки утилита будет проверять, есть ли все необходимые библиотеки в системе, и если нет, вам придется их установить или отключить эту функцию, если это возможно. Например, может возникнуть такая ошибка: no terminal library found checking for tgetent()… configure: error: NOT FOUND!
В таком случае нам необходимо установить требуемую библиотеку. Например, программа предлагает ncurses, поэтому ставим:
Приставка lib всегда добавляется перед библиотеками, а -dev — означает, что нам нужна библиотека со всеми заголовочными файлами. После удовлетворения всех зависимостей настройка пройдет успешно.
Сборка программы
Когда настройка будет завершена и Makefile будет готов, вы сможете перейти непосредственно к сборке программы. На этом этапе выполняется непосредственно преобразование исходного кода в машинный. Утилита make на основе Makefile сделает все необходимые действия:
Дальше осталось установить саму программу, если вы использовали опцию prefix, чтобы не устанавливать программу в основную файловую систему, то можно применить стандартную опцию make:
После этого программа будет установлена в указанную вами папку, и вы сможете ее использовать. Но более правильный путь — создавать пакет для установки программы, это делается с помощью утилиты checkinstall, она позволяет создавать как deb, так и rpm пакеты, поэтому может использоваться не только в Ubuntu. Вместо make install выполните:
Затем просто установите получившийся пакет с помощью dpkg:
После этого сборка программы полностью завершена и установлена, так что вы можете переходить к полноценному использованию.
Если вы устанавливали программу с помощью make install, то удалить ее можно выполнив в той же папке обратную команду:
Команда удалит все файлы, которые были скопированы в файловую систему.
Прочее
Параметр | Цель |
---|---|
Отображает список параметров компилятора. | |
Указывает файл ответа. | |
Включает анализ кода | |
Увеличивает число адресуемых секций в OBJ-файле. | |
Задает компиляцию без компоновки. | |
Указывает число потоков cl.exe , используемых для оптимизации и создания кода. | |
Не рекомендуется. отчеты об ошибках контролируются параметрами отчеты об ошибках Windows (WER) . | |
Позволяет управлять диагностикой во внешних заголовках. | |
Отображает полный путь к файлам исходного кода, переданным cl.exe в диагностическое сообщение. | |
Принудительно выполняет запись в PDB-файл для сериализации с помощью MSPDBSRV.EXE. | |
Включает компиляцию инструментирования, например Аддресссанитизер. | |
Не рекомендуется. Ограничивает длину внешних (открытых) имен. | |
Отображает список параметров компилятора. | |
Изменяет тип по умолчанию . | |
Поддерживает отладку в машинном коде C++ Только мой код. | |
Компилятор и компоновщик создадут двоичный файл для выполнения в ядре Windows. | |
Параллельное построение нескольких исходных файлов. | |
Подавление отображения приветствия. | |
Включает дополнительные функции безопасности и предупреждения. | |
Отображает список всех включаемых файлов во время компиляции. | |
Указывает исходный файл на языке C. | |
Указывает все исходные файлы — C. | |
Указывает исходный файл на языке C++. | |
Указывает, что все исходные файлы имеют язык C++. | |
Не рекомендуется. Задает строку версии. | |
Отключает все предупреждения. | |
, , , , | Задает уровень выходного предупреждения. |
, , , | Задает уровень для указанного предупреждения. |
Включает все предупреждения, в том числе предупреждения, отключенные по умолчанию. | |
Отключает указанное предупреждение. | |
Обрабатывает указанное предупреждение как ошибку. | |
Включает однострочные диагностические сообщения об ошибках и предупреждения в ходе компиляции исходного кода C++ из командной строки. | |
Отображает указанное предупреждение только один раз. | |
Отключает предупреждения, появившиеся в более поздних версиях компилятора. | |
Обрабатывает предупреждения как ошибки. | |
Создать файл. | |
Не рекомендуется. Размещает полную отладочную информацию во всех объектных файлах. Вместо этого используйте. | |
Вставляет ссылку PCH при создании отладочной библиотеки. | |
Использует файл предкомпилированного заголовка при построении. | |
Пропускает все прочие параметры компилятора, относящиеся к предварительно скомпилированным заголовкам, в текущем построении. | |
Указывает предел выделения памяти для предкомпилированного заголовка. | |
Включить расширения для подподпрограмм (возобновляемые функции). | |
Задать исходную кодировку. | |
Задать кодировку выполнения. | |
Задайте кодировку UTF-8 для исходного кода и кодировки выполнения. | |
Проверка файлов UTF-8 на наличие только совместимых символов. | |
Управляет форматом диагностических сообщений. | |
Задать режим стандартного соответствия. | |
Селектор совместимости версии C++ Standard. |
Eclipse
Описание: одна из самых популярных мультиязычных сред. Ориентирована преимущественно на разработку Java-приложений, но полезна и для кодов на C#.
Плюсы:
- Множество плагинов. У Eclipse едва ли не самое большое число надстроек — «на все случаи жизни».
- Активное сообщество. Помогает быстрее освоить среду разработки, выпускает новые плагины.
- Отличные компилятор и отладчик. Первый работает на порядок быстрее, чем у конкурентов, второй — показывает потоки, пересечения, позволяет гибко управлять ходом отладки.
- Кастомизация. Благодаря плагинам и настройкам можно полностью персонализировать Eclipse.
- Бесплатность. Это open-source проект, абсолютно бесплатный.
- Высокая функциональность. Благодаря разработчикам-официалам и членам сообщества с помощью Eclipse можно провести любой C#-продукт по полному циклу разработки.
Минусы:
- Сложность. Как и любой функциональный продукт, Eclipse может показаться новичку слишком сложным.
- Нет гарантий надежности. Так как плагины создаются сообществом, за их качество отвечает только разработчик. Кроме того, сами создатели Eclipse с каждой новой версией плодят баги, не успевая порой исправлять старые.
Шаг 5. Компоновка (линковка) объектных файлов и библиотек
После того, как компилятор создал один или несколько объектных файлов, включается другая программа, называемая компоновщиком (линкером). Работа компоновщика состоит из трех частей:
Во-первых, взять все объектные файлы, сгенерированные компилятором, и объединить их в единую исполняемую программу.
Рисунок 3 – Процесс компоновки (линковки)
Во-вторых, помимо возможности связывать объектные файлы, компоновщик (линкер) также может связывать файлы библиотек. Файл библиотеки – это набор предварительно скомпилированного кода, который был «упакован» для повторного использования в других программах.
Ядро языка C++ на самом деле довольно небольшое и лаконичное (и вы узнаете многое о нем в последующих статьях). Однако C++ также поставляется с обширной библиотекой, называемой стандартной библиотекой C++ (обычно сокращенно «стандартная библиотека», или STL), которая предоставляет дополнительные функции, которые вы можете использовать в своих программах. Одна из наиболее часто используемых частей стандартной библиотеки C++ – это библиотека , которая содержит функции для печати текста на мониторе и получения от пользователя ввода с клавиатуры. Почти каждая написанная программа на C++ в той или иной форме использует стандартную библиотеку, поэтому она часто подключается к вашим программам. Большинство компоновщиков автоматически подключают стандартную библиотеку, как только вы используете какую-либо ее часть, так что, как правило, вам не о чем беспокоиться.
Вы также можете при желании выполнить линковку с другими библиотеками. Например, если вы собрались написать программу, которая воспроизводит звук, вы, вероятно, не захотите писать свой собственный код для чтения звуковых файлов с диска, проверки их правильности или выяснения, как маршрутизировать звуковые данные к операционной системе или оборудованию для воспроизведения через динамик – это потребует много работы! Вместо этого вы, вероятно, загрузили бы библиотеку, которая уже знала, как это сделать, и использовали бы ее. О том, как связывать библиотеки (и создавать свои собственные!), мы поговорим в приложении.
В-третьих, компоновщик обеспечивает правильное разрешение всех межфайловых зависимостей. Например, если вы определяете что-то в одном файле .cpp, а затем используете это в другом файле .cpp, компоновщик соединит их вместе. Если компоновщик не может связать ссылку с чем-то с ее определением, вы получите ошибку компоновщика, и процесс линковки будет прерван.
Как только компоновщик завершит линковку всех объектных файлов и библиотек (при условии, что всё идет хорошо), вы получите исполняемый файл, который затем можно будет запустить!
Для продвинутых читателей
Для сложных проектов в некоторых средах разработки используется make-файл (makefile), который представляет собой файл, описывающий, как собрать программу (например, какие файлы компилировать и связывать, или обрабатывать какими-либо другими способами). О том, как писать и поддерживать make-файлы, написаны целые книги, и они могут быть невероятно мощным инструментом. Однако, поскольку make-файлы не являются частью ядра языка C++, и вам не нужно их использовать для продолжения изучения, мы не будем обсуждать их в рамках данной серии статей.
Принцип работы компилятора
Принцип работы компилятора ничем не отличается от работы обычного транслятора. Что мы делаем, когда переводим текст, например, с незнакомого нам языка (например, итальянского) на русский?
Лексический анализ
Прежде всего, мы пытаемся найти в словаре все слова текста и выписать их значение. Если какое-то слово будет написано с ошибкой, то мы не найдем его в словаре. Так и компилятор. На первом этапе (он называется лексический анализ) компилятор проверяет правильность написания всех «слов» (лексем) в тексте программы. Если обнаруживается ошибка, то выдается соответствующее сообщение.
Синтаксический анализ
При переводе текста с итальянского мы, скорее всего, не обратим внимания на правильность расстановки знаков препинания, поскольку для нас основной задачей является понять смысл написанного, хотя в некоторых ситуациях (помните известную фразу «казнить нельзя помиловать») неправильно поставленная запятая может кардинально изменить смысл написанного. Компилятор всегда проверяет правильность расстановки «знаков препинания» (точек, двоеточий, скобок и других символов) в тексте программы, поскольку в языке программирования, в отличие от разговорного языка, у знаков имеется смысловая нагрузка (они, например, определяют порядок действий). Этот этап называется синтаксическим анализом.
Семантический анализ
После того, как мы выписали из словаря все слова, мы пытаемся связать их в предложения так, чтобы каждое предложение имело некоторый смысл. Если это нам не удается, мы возвращаемся к словарю и пытаемся обнаружить другое значение выписанных слов. Это этап семантического анализа. На этом заканчивается первая фаза перевода — аналитическая часть, посвященная изучению и анализу исходного текста.
Синтез, оптимизация и генерация машинного код
Когда нам удалось составить черновой вариант текста, мы пытаемся его оформить, базируясь на правилах русского языка, и выстраиваем фразы так, чтобы они были не только понятны читателю, но и отличались благозвучием. Таким образом, мы начинаем синтезировать новый текст, начинается вторая фаза перевода — синтез. Компилятор разбивает эту фазу на три этапа: синтез промежуточного кода, оптимизация и генерация машинного кода. Этап оптимизации необходим для того, чтобы уменьшить объем машинного кода, что позволит увеличить скорость работы программы. Следует отметить, что этап оптимизации реализован не во всех компиляторах. На выходе компилятор выдаст машинный код исходной программы, который будет понятен компьютеру.