Как компилировать cpp файлы

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

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

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

$ g++ --version g++ (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609

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

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

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

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

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

Перед тем, как приступать, давайте создадим исходный .cpp файл, с которым и будем работать в дальнейшем.

#include using namespace std; #define RETURN return 0 int main()

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

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

Читайте также:  Html css and php book

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

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

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

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

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

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

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

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

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

 .file "driver.cpp" .local _ZStL8__ioinit .comm _ZStL8__ioinit,1,1 .section .rodata .LC0: .string "Hello, world!" .text .globl main .type main, @function main: .LFB1021: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $.LC0, %esi movl $_ZSt4cout, %edi call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi movq %rax, %rdi call _ZNSolsEPFRSoS_E movl $0, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1021: .size main, .-main .type _Z41__static_initialization_and_destruction_0ii, @function _Z41__static_initialization_and_destruction_0ii: .LFB1030: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $16, %rsp movl %edi, -4(%rbp) movl %esi, -8(%rbp) cmpl $1, -4(%rbp) jne .L5 cmpl $65535, -8(%rbp) jne .L5 movl $_ZStL8__ioinit, %edi call _ZNSt8ios_base4InitC1Ev movl $__dso_handle, %edx movl $_ZStL8__ioinit, %esi movl $_ZNSt8ios_base4InitD1Ev, %edi call __cxa_atexit .L5: nop leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1030: .size _Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii .type _GLOBAL__sub_I_main, @function _GLOBAL__sub_I_main: .LFB1031: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $65535, %esi movl $1, %edi call _Z41__static_initialization_and_destruction_0ii popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1031: .size _GLOBAL__sub_I_main, .-_GLOBAL__sub_I_main .section .init_array,"aw" .align 8 .quad _GLOBAL__sub_I_main .hidden __dso_handle .ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609" .section .note.GNU-stack,"",@progbits

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

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

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

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

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

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

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

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

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

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

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

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

$ g++ driver.o -o driver // также тут можно добавить и другие объектные файлы и библиотеки

5) Загрузка

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

Заключение

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

Источник

Пошаговое руководство: Создание стандартной программы C++ (C++)

Вы можете использовать Visual Studio для создания программ C++ уровня «Стандартный». Выполнив действия, описанные в этом пошаговом руководстве, вы можете создать проект, добавить новый файл в проект, изменить файл, чтобы добавить код C++, а затем скомпилировать и запустить программу с помощью Visual Studio.

Вы можете ввести собственную программу C++ или использовать один из примеров программ. Пример программы в этом пошаговом руководстве является консольным приложением. Это приложение использует set контейнер в стандартной библиотеке C++.

Если требуется соответствие определенной версии стандарта языка C++ (например, C++14, C++17 или C++20), используйте параметр компилятора /std:c++14 , /std:c++17 или /std:c++20 . (Visual Studio 2017 и более поздние версии.)

Предварительные требования

Для выполнения этого пошагового руководства читатель должен владеть основами языка C++.

Создание проекта и добавление исходного файла

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

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

  1. В главном меню выберите Файл >Создать >Проект, чтобы открыть диалоговое окно Создание проекта.
  2. В верхней части диалогового окна задайте для параметра Язык значение C++, для параметра Платформа значение Windows, а для Типа проектаКонсоль.
  3. В отфильтрованном списке типов проектов щелкните Консольное приложение, а затем нажмите кнопку Далее. На следующей странице введите имя проекта и при необходимости укажите расположение проекта.
  4. Нажмите кнопку Создать, чтобы создать проект.

Создание проекта C++ в Visual Studio 2017

  1. Создайте проект, наведите указатель на пункт Создать в меню Файл и выберите Пункт Проект.
  2. В области Типы проектов Visual C++ щелкните Рабочий стол Windows, а затем — Консольное приложение Windows.
  3. Введите имя проекта. По умолчанию решение, содержащее проект, имеет то же имя, что и проект, но вы можете ввести другое имя. Вы также можете ввести другое расположение для проекта.
  4. Чтобы создать проект, нажмите кнопку ОК .

Создание проекта C++ в Visual Studio 2015

  1. Создайте проект, наведите указатель на пункт Создать в меню Файл и выберите Пункт Проект.
  2. В области Типы проектов Visual C++ щелкните Рабочий стол Windows, а затем — Консольное приложение Windows.
  3. В диалоговом окне Новый проект разверните узел Установленные>шаблоны>Visual C++, а затем выберите Win32. В центральной области выберите Консольное приложение Win32.
  4. Введите имя проекта. По умолчанию решение, содержащее проект, имеет то же имя, что и проект, но вы можете ввести другое имя. Вы также можете ввести другое расположение для проекта.
  5. Чтобы создать проект, нажмите кнопку ОК .
  6. Завершите работу мастера приложений Win32.
  7. Нажмите кнопку Далее, а затем убедитесь, что консольное приложение выбрано, и снимите флажок Предкомпилированные заголовки .
  8. Нажмите кнопку Готово.

Добавление нового исходного файла

  1. Если Обозреватель решений не отображается, в меню Вид выберите Обозреватель решений.
  2. Добавьте в проект новый исходный файл, как показано ниже.
    1. В Обозреватель решений щелкните правой кнопкой мыши папку Исходные файлы, наведите указатель на пункт Добавить и выберите пункт Создать элемент.
    2. В узле Код щелкните Файл C++ (CPP), введите имя файла и нажмите кнопку Добавить.

    CPP-файл отображается в папке Исходные файлыв Обозреватель решений, а файл открывается в редакторе Visual Studio.

    Источник

    Как скомпилировать CPP в EXE

    wikiHow работает по принципу вики, а это значит, что многие наши статьи написаны несколькими авторами. При создании этой статьи над ее редактированием и улучшением работали, в том числе анонимно, 18 человек(а).

    Количество просмотров этой статьи: 68 931.

    Это пошаговое руководство по компиляции исходного кода на C++ в EXE файлы (в Windows). Описанные методы также работают при компиляции форматов .c ++, .cc и .cxx (возможно, что и .c). Это руководство предполагает, что исходный код на C++ является консольным приложением и не требует никаких внешних библиотек.

    Изображение с названием Compile CPP File to EXE Step 1

    Скачайте C++ компилятор. Одним из лучших компиляторов для компьютеров под управлением Windows является бесплатный Microsoft Visual C++ 2012 Express.

    Изображение с названием Compile CPP File to EXE Step 2

    Начните новый проект в Visual C++. Это довольно просто. Нажмите «New Project» в левом верхнем углу, а затем следуйте инструкциям на экране. Введите название проекта и в открывшемся окне нажмите «Finish».

    Изображение с названием Compile CPP File to EXE Step 3

    Скопируйте и вставьте все .cpp файлы в каталог «Source Files», а затем скопируйте и вставьте все .h файлы (если таковые имеются) в каталог «Header Files». Переименуйте основной CPP файл (тот, который содержит «int main()») на выбранное вами название проекта.

    Изображение с названием Compile CPP File to EXE Step 4

    Изображение с названием Compile CPP File to EXE Step 5

    Найдите EXE файл. Перейдите в каталог «Projects», в который Visual C++ помещает все программы (в Windows 7 этот каталог расположен в папке «Мои документы). В каталоге «Debug» найдите EXE файл под именем, которые вы дали ему ранее.

    Изображение с названием Compile CPP File to EXE Step 6

    Проверьте файл. Дважды щелкните по EXE файлу, чтобы запустить его; если все прошло хорошо, то программа работает нормально. Если что-то пошло не так, попробуйте выполнить описанные действия еще раз.

    Источник

Оцените статью