Что значит скомпилировать программу

Процесс компиляции программ на C++

Цель данной статьи:

В данной статье я хочу рассказать о том, как происходит компиляция программ, написанных на языке C++, и описать каждый этап компиляции. Я не преследую цель рассказать обо всем подробно в деталях, а только дать общее видение. Также данная статья — это необходимое введение перед следующей статьей про статические и динамические библиотеки, так как процесс компиляции крайне важен для понимания перед дальнейшим повествованием о библиотеках.

Все действия будут производиться на Ubuntu версии 16.04.
Используя компилятор g++ версии:

Состав компилятора g++

Мы не будем вызывать данные компоненты напрямую, так как для того, чтобы работать с C++ кодом, требуются дополнительные библиотеки, позволив все необходимые подгрузки делать основному компоненту компилятора — g++.

Зачем нужно компилировать исходные файлы?

Исходный C++ файл — это всего лишь код, но его невозможно запустить как программу или использовать как библиотеку. Поэтому каждый исходный файл требуется скомпилировать в исполняемый файл, динамическую или статическую библиотеки (данные библиотеки будут рассмотрены в следующей статье).

Этапы компиляции:

driver.cpp:

1) Препроцессинг

Самая первая стадия компиляции программы.

Препроцессор — это макро процессор, который преобразовывает вашу программу для дальнейшего компилирования. На данной стадии происходит происходит работа с препроцессорными директивами. Например, препроцессор добавляет хэдеры в код (#include), убирает комментирования, заменяет макросы (#define) их значениями, выбирает нужные куски кода в соответствии с условиями #if, #ifdef и #ifndef.

Хэдеры, включенные в программу с помощью директивы #include, рекурсивно проходят стадию препроцессинга и включаются в выпускаемый файл. Однако, каждый хэдер может быть открыт во время препроцессинга несколько раз, поэтому, обычно, используются специальные препроцессорные директивы, предохраняющие от циклической зависимости.

Получим препроцессированный код в выходной файл driver.ii (прошедшие через стадию препроцессинга C++ файлы имеют расширение .ii), используя флаг -E, который сообщает компилятору, что компилировать (об этом далее) файл не нужно, а только провести его препроцессинг:

Взглянув на тело функции main в новом сгенерированном файле, можно заметить, что макрос RETURN был заменен:

В новом сгенерированном файле также можно увидеть огромное количество новых строк, это различные библиотеки и хэдер iostream.

2) Компиляция

На данном шаге g++ выполняет свою главную задачу — компилирует, то есть преобразует полученный на прошлом шаге код без директив в ассемблерный код. Это промежуточный шаг между высокоуровневым языком и машинным (бинарным) кодом.

Ассемблерный код — это доступное для понимания человеком представление машинного кода.

Используя флаг -S, который сообщает компилятору остановиться после стадии компиляции, получим ассемблерный код в выходном файле driver.s:

Мы можем все также посмотреть и прочесть полученный результат. Но для того, чтобы машина поняла наш код, требуется преобразовать его в машинный код, который мы и получим на следующем шаге.

3) Ассемблирование

Так как x86 процессоры исполняют команды на бинарном коде, необходимо перевести ассемблерный код в машинный с помощью ассемблера.

Ассемблер преобразовывает ассемблерный код в машинный код, сохраняя его в объектном файле.

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

Далее возможно сохранение данного объектного кода в статические библиотеки для того, чтобы не компилировать данный код снова.

Получим машинный код с помощью ассемблера (as) в выходной объектный файл driver.o:

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

4) Компоновка

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

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

Получим исполняемый файл driver:

5) Загрузка

Последний этап, который предстоит пройти нашей программе — вызвать загрузчик для загрузки нашей программы в память. На данной стадии также возможна подгрузка динамических библиотек.

Запустим нашу программу:

Заключение

В данной статье были рассмотрены основы процесса компиляции, понимание которых будет довольно полезно каждому начинающему программисту. В скором времени будет опубликована вторая статья про статические и динамические библиотеки.

Источник

Что такое компиляция в программировании?

Компилируется ли язык программирования или интерпретируется, на самом деле это не зависит от природы языка программирования. Любой язык программирования может интерпретироваться так называемым интерпретатором или компилироваться с помощью так называемого компилятора.

Рабочий цикл программы

При использовании любого языка программирования существует определенный рабочий цикл создания кода. Вы пишете его, запускаете, находите ошибки и отлаживаете. Таким образом, вы переписываете и дописываете программу, проверяете ее. То, о чем пойдет речь в этой статье, это « запускаемая » часть программы.

Когда пишете программу, вы хотите, чтобы ее инструкции работали на компьютере. Компьютер обрабатывает информацию с помощью процессора, который поэтапно выполняет инструкции, закодированные в двоичном формате. Как из выражения « a = 3; » получить закодированные инструкции, которые процессор может понять?

Мы делаем это с помощью компиляции. Существует специальные приложения, известные как компиляторы. Они принимают программу, которую вы написали. Затем анализируют и разбирают каждую часть программы и строят машинный код для процессора. Часто его также называют объектным кодом.

На одном из этапов процесса обработки задействуется компоновщик, принимающий части программы, которые отдельно были преобразованы в объектный код, и связывает их в один исполняемый файл. Вот схема, описывающая данный процесс:

Конечным элементом этого процесса является исполняемый файл. Когда вы запускаете или сообщаете компьютеру, что это исполняемый файл, он берет первую же инструкцию из него, не фильтрует, не преобразует, а сразу запускает программу и выполняет ее без какого-либо дополнительного преобразования. Это ключевая характеристика процесса компиляции — его результат должен быть исполняемым файлом, не требующим дополнительного перевода, чтобы процессор мог начать выполнять первую инструкцию и все следующие за ней.

Первые компиляторы были написаны непосредственно через машинный код или с использованием ассемблеров. Но цель компилятора очевидна: перевести программу в исполняемый машинный код для конкретного процессора.

Не все языки программирования учитывают это в своей концепции. Например, Java предназначался для запуска в « интерпретирующей » среде, а Python всегда должен интерпретироваться.

Интерпретация программы

Альтернативой компиляции является интерпретация. Чем отличаются компиляторы и интерпретаторы? Основная разница между компилятором и интерпретатором заключается в том, как они работают. Компилятор берет всю программу и преобразует ее в машинный код, который понимает процессор.

Интерпретатор — это исполняемый файл, который поэтапно читает программу, а затем обрабатывает, сразу выполняя ее инструкции.

Другими словами, программа-интерпретатор выполняет программу поэтапно как часть собственного исполняемого файла. Объектный код не передается процессору, интерпретатор сам является объектным кодом, построенным таким образом, чтобы его можно было вызвать в определенное время.

Это ломает рабочий цикл, который был приведен на диаграмме выше. Теперь у нас есть новая диаграмма:

На ней мы видим, что в отличии от компилятора, интерпретатор всегда должен быть под рукой, чтобы мы могли вызвать его и запустить нашу программу. В некотором смысле интерпретатор становится процессором. Программы, написанные для интерпретации, называются « скриптами », потому что они являются сценариями действий для другой программы, а не прямым машинным кодом.

Природа интерпретатора

Интерпретаторы могут создаваться по-разному. Существуют интерпретаторы, которые читают исходную программу и не выполняют дополнительной обработки. Они просто берут определенное количество строк кода за раз и выполняют его.

Некоторые интерпретаторы выполняют собственную компиляцию, но обычно преобразуют программу байтовый код, который имеет смысл только для интерпретатора. Это своего рода псевдо машинный язык, который понимает только интерпретатор.

Такой код быстрее обрабатывается, и его проще написать для исполнителя ( части интерпретатора, которая исполняет ), который считывает байтовый код, а не код источника.

Есть интерпретаторы, для которых этот вид байтового кода имеет более важное значение. Например, язык программирования Java « запускается » на так называемой виртуальной машине. Она является исполняемым кодом или частью программы, которая считывает конкретный байтовый код и эмулирует работу процессора. Обрабатывая байтовый код так, как если бы процессор компьютера был виртуальным процессором.

За и против

Основным аргументом за использование процесса компиляции является скорость. Возможность компилировать любой программный код в машинный, который может понять процессор ПК, исключает использование промежуточного кода. Можно запускать программы без дополнительных шагов, тем самым увеличивая скорость обработки кода.

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

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

С помощью интерпретатора проще добавить дополнительные функции, реализовать такие элементы, как сборщики мусора, а не расширять язык.

Другим преимуществом интерпретаторов является то, что их проще переписать или перекомпилировать для новых платформ.

Написание компилятора для процессора требует добавления множества функций, или полной переработки. Но как только компилятор написан, можно скомпилировать кучу интерпретаторов и на выходе мы имеем перспективный язык. Не нужно повторно внедрять интерпретатор на базовом уровне для другого процессора.

Самым большим недостатком интерпретаторов является скорость. Для каждой программы выполняется так много переводов, фильтраций, что это приводит к замедлению работы и мешает выполнению программного кода.

Это проблема для конкретных real-time приложений, таких как игры с высоким разрешением и симуляцией. Некоторые интерпретаторы содержат компоненты, которые называются just-in-time компиляторами ( JIT ). Они компилируют программу непосредственно перед ее исполнением. Это специальные программы, вынесенные за рамки интерпретатора. Но поскольку процессоры становятся все более мощными, данная проблема становится менее актуальной.

Заключение

Для меня не имеет значения, скомпилировано что-то или интерпретировано, если оно может выполнить задачу эффективно.

Сообщите мне, что бы вы предпочли: интерпретацию или компиляцию? Спасибо за уделенное время!

Пожалуйста, оставьте ваши комментарии по текущей теме статьи. Мы крайне благодарны вам за ваши комментарии, дизлайки, подписки, отклики, лайки!

Пожалуйста, оставляйте свои отзывы по текущей теме статьи. За комментарии, дизлайки, подписки, отклики, лайки огромное вам спасибо!

Источник

0.7 – Компиляция вашей первой программы

Прежде чем мы сможем написать нашу первую программу, нам нужно научиться создавать новые программы в нашей интегрированной среде разработки (IDE). В этом уроке мы расскажем, как это сделать, а вы скомпилируете и запустите свою первую программу!

Проекты

Каждый проект соответствует одной программе. Когда вы будете готовы создать вторую программу, вам нужно будет либо создать новый проект, либо перезаписать код в существующем проекте (если вы не хотите его оставлять). Файлы проекта обычно специфичны для конкретной IDE, поэтому проект, созданный в одной IDE, необходимо будет заново создать в другой IDE.

Лучшая практика

Создавайте новый проект для каждой новой программы, которую вы пишете.

Консольные проекты

Когда вы создаете новый проект, вас обычно спрашивают, проект какого типа вы хотите создать. Все проекты, которые мы создадим в этом руководстве, будут консольными. Консольный проект означает, что мы собираемся создавать программы, которые можно запускать из консоли Windows, Linux или Mac.

Ниже показан скриншот консоли Windows:

Рисунок 1 – Консоль Windows

По умолчанию консольные приложения не имеют графического пользовательского интерфейса (GUI), они выводят текст на консоль, считывают ввод с клавиатуры и компилируются в автономные исполняемые файлы. Они идеально подходят для изучения C++, поскольку сводят сложность к минимуму и обеспечивают работу в самых разных системах.

Не беспокойтесь, если вы никогда раньше не пользовались консолью или не знаете, как получить к ней доступ. Мы будем компилировать и запускать наши программы через наши IDE (которые при необходимости будут вызывать консоль).

Рабочие пространства / решения

Когда вы создаете новый проект для своей программы, многие IDE автоматически добавляют ваш проект в «рабочее пространство» («workspace» или «solution») (термин зависит от IDE). Рабочее пространство – это контейнер, который может содержать один или несколько связанных проектов. Например, если вы пишете игру и хотите иметь отдельные исполняемые файлы для одиночной и многопользовательской игры, вам нужно будет создать два проекта. Обоим этим проектам не имело бы смысла быть полностью независимыми – в конце концов, они являются частью одной игры. Скорее всего, каждый из них будет настроен как отдельный проект в рамках одного рабочего пространства.

Хотя вы можете добавить несколько проектов в одно рабочее пространство, мы обычно рекомендуем создавать новое рабочее пространство для каждой программы, особенно во время обучения. Это проще, и вероятность того, что что-то пойдет не так, меньше.

Написание вашей первой программы

Традиционно у программистов, пишущих на новом языке, первой программой является печально известная программа hello world, и мы не собираемся лишать вас этого опыта! Вы нас потом поблагодарите. Может быть.

Создание проекта в Visual Studio 2019

Когда вы запустите Visual Studio 2019, вы должны увидеть диалоговое окно, которое выглядит следующим образом:

Рисунок 2 – Диалоговое окно «Начало работы» Visual Studio 2019

Выберите Создание проекта (Create a new project).

После этого вы увидите диалоговое окно, которое выглядит следующим образом:

Рисунок 3 – Visual Studio 2019: диалоговое окно создания нового проекта

Если вы уже открыли предыдущий проект, вы можете открыть это диалоговое окно через меню Файл (File) → Создать (New) → Проект (Project).

Выберите Мастер классических приложений Windows (Windows Desktop Wizard) и нажмите Далее (Next). Если вы этого не видите, то вы, вероятно, при установке Visual Studio забыли выбрать установку Desktop development with C++. В этом случае вернитесь к уроку «0.6 – Установка интегрированной среды разработки (IDE)» и переустановите Visual Studio, как было показано (примечание: вместо полной переустановки вы можете запустить установщик Visual Studio и изменить существующую установку, чтобы добавить поддержку C++).

Далее вы увидите диалоговое окно, которое выглядит следующим образом:

Рисунок 4 – Диалоговое окно настройки нового проекта Visual Studio 2019

Рекомендуется также установить флажок «Поместить решение и проект в одном каталоге» (Place solution and project in the same directory), поскольку это сокращает количество подкаталогов, создаваемых с каждым проектом.

Нажмите Создать (Create), чтобы продолжить.

Наконец, вы увидите последнее диалоговое окно:

Рисунок 5 – Диалоговое окно параметров проекта Visual Studio 2019

Убедитесь, что тип приложения установлен как Консольное приложение (.exe) (Console Application (.exe)), и что параметр Предкомпилированный заголовок (Precompiled Header) не выбран. Затем нажмите ОК.

Вы создали проект! Чтобы продолжить, перейдите в раздел Обозреватель решений Visual Studio ниже.

Создание проекта в Visual Studio 2017 или в более ранней версии

Чтобы создать новый проект в Visual Studio 2017 или более ранней версии, выберите меню Файл (File) → Создать (New) → Проект (Project). Появится диалоговое окно, которое выглядит примерно так:

Рисунок 6 – Диалоговое окно «Новый проект Visual Studio 2017»

Сначала убедитесь, что слева указан Visual C++. Если вы не видите Visual C++, возможно, вы забыли выбрать установку поддержку Desktop development with C++ при установке Visual Studio. В этом случае вернитесь к уроку «0.6 – Установка интегрированной среды разработки (IDE)» и переустановите Visual Studio, как было показано (примечание: вместо полной переустановки вы можете запустить установщик Visual Studio и изменить существующую установку, чтобы добавить поддержку C++).

Если вы используете Visual Studio 2017 v15.3 или новее, под Visual C++ выберите Windows Desktop, а затем выберите Windows Desktop Wizard в главном окне.

Если вы не видите вариант с Windows Desktop, возможно, вы используете старую версию Visual Studio. Отлично. Вместо этого выберите Win32, а затем Win32 Console Application в главном окне.

Внизу в поле Name введите название своей программы (замените существующее имя на HelloWorld ). В поле Location вы можете при желании выбрать другое место для размещения вашего проекта. Пока подойдет и значение по умолчанию.

Нажмите ОК. Если вы используете старую версию Visual Studio, запустится мастер приложений Win32. Нажмите Next.

На этом этапе вы должны увидеть диалоговое окно мастера, которое выглядит примерно так (более старые версии Visual Studio используют другой стиль, но имеют большинство из тех же параметров):

Рисунок 7 – Мастер создания десктопного приложения Visual Studio 2017

Убедитесь, что вы сняли флажок Предкомпилированный заголовок (Precompiled Header).

Затем нажмите ОК или Finish. Теперь ваш проект создан!

Обозреватель решений Visual Studio

Рисунок 8 – Начальные окна Visual Studio 2019

В текстовом редакторе вы увидите, что Visual Studio уже открыла HelloWorld.cpp и создала для вас код. Выделите и удалите весь код и введите/скопируйте следующий код в вашу IDE:

Чтобы скомпилировать программу, либо нажмите F7 (если это не сработает, попробуйте Ctrl + Shift + B ), либо перейдите в меню Сборка (Build) → Собрать решение (Build Solution). Если всё пойдет хорошо, вы должны увидеть следующее в окне вывода:

Или, в зависимости от выбранного языка:

Это означает, что ваша компиляция прошла успешно!

Вопрос: У меня вылетела ошибка C1010 («fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add ‘#include «stdafx.h»‘ to your source?»). Что теперь?

Вы забыли отключить предварительно скомпилированные заголовки при создании проекта. Заново создайте свой проект (в соответствии с инструкциями выше) и обязательно отключите предварительно скомпилированные заголовки.

Чтобы запустить скомпилированную программу, нажмите Ctrl + F5 или перейдите в меню Отладка (Debug) и выберите Запуск без отладки (Start Without Debugging). Вы увидите следующее:

Рисунок 9 – Запуск программы

Это результат выполнения вашей программы! Поздравляем, вы скомпилировали и запустили свою первую программу!

Создание проекта в Code::Blocks

Чтобы создать новый проект, перейдите в меню File (Файл) → New (Новый) → Project (Проект). Появится диалоговое окно, которое выглядит следующим образом:

Рисунок 10 – Code::Blocks. Диалоговое окно создания проекта

Выберите Console application (консольное приложение) и нажмите кнопку Go (перейти/создать).

Если вы видите диалоговое окно мастера консольного приложения, нажмите Next (далее), убедитесь, что выбран C++, и снова нажмите Next.

Рисунок 11 – Code::Blocks. Диалогове окно сохранения проекта

Вы можете увидеть другое диалоговое окно с вопросом, какие конфигурации вы хотите включить. Значения по умолчанию здесь подойдут, поэтому выберите Finish.

Теперь ваш новый проект создан.

В левой части экрана вы должны увидеть окно Management (управление) с выбранной вкладкой Projects (проекты). Внутри этого окна вы увидите папку Workspace с вашим проектом HelloWorld внутри:

Рисунок 12 – Code::Blocks. Workspace

Внутри проекта HelloWorld разверните папку Sources (исходники) и дважды щелкните на « main.cpp ». Вы увидите, что для вас уже написана программа hello world!

Замените ее следующим кодом:

Чтобы собрать проект, нажмите Ctrl + F9 или перейдите в меню Build (Сборка) → Build (Сборка). Если всё пойдет хорошо, вы должны увидеть следующее в окне журнала сборки:

Это означает, что компиляция прошла успешно!

Чтобы запустить скомпилированную программу, нажмите Ctrl + F10 или перейдите в меню Build (Сборка) → Run (Запуск). Вы увидите что-то похожее на следующий скриншот:

Рисунок 13 – Запуск программы

Это результат выполнения вашей программы!

Для пользователей Linux

Пользователям Linux до компиляции в Code::Blocks может потребоваться установить дополнительные пакеты. Дополнительные сведения смотрите в инструкциях по установке Code::Blocks в уроке «0.6 – Интегрированная среда разработки (IDE)».

Если вы используете g++ из командной строки

В этом случае создавать проект не нужно. Просто вставьте следующий код в текстовый файл с именем HelloWorld.cpp и сохраните файл:

В командной строке введите:

И вы увидите результат выполнения своей программы.

Если вы используете другие IDE или веб-компилятор

Вам нужно будет самостоятельно выяснить, как сделать следующее:

Если компиляция завершилась ошибкой

Ничего страшного, сделайте глубокий вдох. Вероятно, мы сможем это исправить. :)

Сначала посмотрите на сообщение об ошибке, которое вам выдал компилятор. Чаще всего оно будет содержать номер строки, указывающий, какая строка содержала ошибку. Изучите и эту строку, и строки вокруг нее и убедитесь, что нет опечаток или орфографических ошибок. Также убедитесь, что вы не скопировали в код номера строк.

Во-вторых, посмотрите вопросы и ответы в уроке «0.8 – Несколько распространенных проблем C++», поскольку ваша проблема может быть там освещена.

В-третьих, прочтите комментарии ниже – кто-то мог столкнуться с той же проблемой.

Наконец, если всё вышеперечисленное не помогло, попробуйте поискать сообщение об ошибке в Google. Скорее всего, кто-то уже сталкивался с этим раньше и придумал, как это исправить.

Если ваша программа запускается, но окно мигает и сразу закрывается

Некоторые IDE автоматически не приостанавливают экран консоли после завершения выполнения программы. Ваша программа запускается, но окно вывода закрывается, прежде чем вы сможете просмотреть результаты.

Если это так с вашей IDE, следующие два шага решат вашу проблему:

Во-вторых, добавьте следующий код в конец функции main() (непосредственно перед оператором return ):

Это приведет к тому, что ваша программа будет ждать, пока пользователь нажмет какую-нибудь клавишу, прежде чем продолжить, что даст вам время изучить вывод вашей программы, прежде чем IDE закроет окно консоли.

Ваш антивирус также может блокировать выполнение программы. В таком случае попробуйте временно отключить его и посмотреть, решится ли проблема.

Для пользователей Visual Studio

Visual Studio не будет в конце делать паузу в работе консольного приложения, если оно запускается с отладкой (меню Отладка (Debug) → Начать отладку (Start Debugging)). Если вы хотите, чтобы она сделала паузу, вы можете либо использовать приведенное выше решение с дополнительным кодом, либо запустить свою программу без отладки (меню Отладка (Debug) → Начать отладку (Start Without Debugging)).

Заключение

Поздравляем, вы прошли самую сложную часть этого руководства (установку IDE и компиляцию вашей первой программы)!

Источник

Понравилась статья? Поделиться с друзьями:

Не пропустите наши новые статьи:

  • что значит система не обнаружила vcruntime140 dll для windows 10
  • что значит система не обнаружила msvcp140 dll для windows 10
  • что значит система windows не активирована
  • что значит синхронизация отложена windows 10
  • что значит сжать диск для экономии места windows 10

  • Операционные системы и программное обеспечение
    0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest
    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии