Что полезно знать начинающему в Си/Си++, сборка программы из нескольких файлов.

Всем, доброго утречка, с вами Мирра Андрюхан. И насчет прошлой статьи в данном цикле статей, могу заметить, что пример можно собрать и на компиляторе Си++, поменяв «gcc» на «g++». Но, чтобы нормально программировать на Си++, рекомендую ознакомиться и попрактиковаться с данной статьей. Т.к. в свое время я тоже кое-что делал и садился в лужу, когда не мог понять, где ошибка в программе и почему программа не может собраться из нескольких файлов. А, все нормальные люди пишут интересные программы разбивая их на несколько файлов.

Для начала, давайте посмотрим на то, как можно собрать пример из прошлой статьи (см. ниже), причем оба способа делают в конечном итоге исполняемый файл, который пишет нам «Привет, Мир!» после своего запуска. Причем прошлый способ — это взаимодействие посредством командной строки с компилятором напрямую одной командой, так легко собирать примеры и задачки из учебника по Си++ для школьников и студентов. Однако, способ ниже, применяет программу «make«, для автоматизированного изготовления исполняемого файла программы (чаще говорят «собрать файл», но мы это опустим для данного цикла статей). При этом, «make» задействована по минимуму и может многое для создания полноценной программы. Однако, для этого нужно, чтобы в директории с файлом исходного кода лежал файл  «makefile«, в котором прописываются все нужные задачи, условия выполнения задача и команды для выполнения их в командной строке. Т.е. правила составления задач (целей) в данном файле просты. Слева прописываем имя задачи, справа прописываем необходимые условия для выполнения данной задачи, а также другие задачи, которые должны быть выполнены раньше данной, а строкой ниже прописываем команды для командной строки в одну строку. Однако, прежде чем мы будем рассматривать задачи, предлагаю посмотреть другой вариант файла «makefile«, в котором вы наверняка заметите, что в нем все написано еще проще и он делает тоже самое в конечном итоге.

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

Теперь, давайте пройдемся по задачам из двух примеров файла «makefile». Задача «programma» имеет условие «programma.o«, которое необходимо выполнить перед выполнением данной задачи, т.е. команда строкой ниже, будет выполнена после выполнения задачи «programma.o«. Разумеется у задачи «programma.o» есть тоже условие, но оно указывает на наличие файла (ведь такой задачи нет, поэтому ищет файл) «programma.c», который обязан быть в рабочей директории рядом с файлом «makefile». При этом, задача «programma.o» создает файл «programma.o» в той же директории из исходника «programma.c», а после данный объектный файл применяется для изготовления исполняемого файла в задаче «programma«. Для второго примера файла «makefile», выполнение закончится выполнением задачи «final«, которая помимо вышеописанного еще и вызовет задачу без условий для выполнения «clean«, которая удалит ненужные объектные файлы, применявшиеся в изготовлении исполняемого файла программы. Однако, если второму варианту задать задачу «programma«, то задача «final» будет проигнорирована, т.к. ниже она нигде не упоминается, т.е. есть это вариант вызова «make» с конкретной задачей.

Запускать выполнение «make», по вышеописанному примеру можно следующим способом.

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

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

Если обратите внимание, на задачу «programma.o«, то увидите, что она дополнилась файлом «vtoroifile.c», который содержит функцию «privetmir», выполняющую, что и пример из прошлой статьи (см. ссылку в начале статьи), а также условием выполнения на наличие этого файла в рабочей директории. Т.е. в данном случае, были собраны все необходимые файлы для компиляции из исходного кода в один объектный файл, а потом из него в исполняемый файл программы. Как видите, ничего сложного в этом нет.

При этом, вы можете данную программу собрать на компиляторе Си++, для этого достаточно в файле «makefile» поменять везде «gcc» на «g++».

А теперь, возьмемся за пример сбора нескольких файлов для Си++, на примере создания объекта из класса PrivetMir, который будет прописан в двух файлах «privetmir.cpp» и «privetmir.h». Итог выполнения программы будет такой же.

 

В общем смысл программы тот же, а суть такова. Т.е., в простом классе «PrivetMir«, в его конструкторе выводится все та же строка «Привет, Мир!». А, сам класс прописан, в привычной форме для Си++, в виде двух файлов. Это наглядный пример, того как изготавливается исполняемый файл программы через «make«. А теперь, рассмотрим его подробнее.

Файл «privetmir.h» является заголовочным файлом в языке Си/Си++, в нем объявляются все классы и переменные, а также прописываются дополнительные заголовочные файлы, нужные для работы класса «PrivetMir«. В данном примере применяется язык Си++, т.к. мы применяем классы, а в Си нет ООП, т.е. объектно ориентированного программирования. И, остальное пока оставим без объяснений, т.к. этот пример не про классы и ООП в языке Си++, а про сборку программы из нескольких файлов исходного кода.

В файле «makefile» вы наверняка заметили, что появилась задача «privetmir.o«, а также она стала дополнительным условием для задачи «programma» и командная строка для выполнения также дополнилась ее объектным файлом. При этом, заметьте, что у задачи «privetmir.o«, тоже есть дополнительное условие для выполнения, которое указывает на файл исходного кода «privetmir.h«.

При этом, обращая внимание на команды для командной строки, представленные в задачах, могу сказать следующие. В задачах «privetmir.o» и «programma.o» идет компиляция исходного кода и перевод его в данные объектных файлов, а уже потом в задаче «programma» происходит связывание файлов между собой в исполняемый файл. У иностранцев это называется процессом «линковки» (т.е. на их слове «link» по нашему «связь»). На данном этапе формируется исполняемый файл, который потом может выполнятся ОС Линукс после его запуска.

Для простоты понимания самого процесса сборки посмотрите на диаграмму ниже.

Диаграмма сборки исполняемого файла programma.

Из диаграммы выше видно, что программой «make» сначала компилируется исходники класса «PrivetMir«, потом компилируется исходник самой программы. После компиляции исходных файлов программы, производится линковка, где применяется файл стандартной библиотеки «stdio» (он применяется в классе «PrivetMir»). И все собирается в конечный, исполняемый файл.

Как видите ничего сложного, если до сих пор это для вас не так, советую не напрягаться, отдохнуть и прочитать с абзаца выше еще позднее. Т.к. проще уже не объяснить или повторяться по новому кругу в самом уже тексте данной статьи. Однако, думаю что ничего тут сложного нет, только подскажу, что директива «#include» указывает на точку включения текста в исходный файл из указанного, который включает нужное в процесс компиляции и в итоге получаем объектный файл, и так далее. Если не понятно и это, то посмотрите последний пример сборки одного файла, где применяется данная директива (это тот пример, что с файлом «vtoroifile.c«). И просто дайте себе время, т.к. это все дано в сокращенном варианте и вам пока еще не все известно, чтобы собрать в себе свое собственное представление об описанном. Все, придет постепенно со временем, по мере чтения данного цикла статей.

А пока, поздравляю вас с тем, что вы теперь знаете и в малой мере понимаете, как собирать программу из нескольких файлов программой «make» в ОС ГНУ/Линукс. А также, теперь вы сможете собирать программы различной сложности, что потом нам с вами пригодится для создания программы работающей с командной строкой.

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

Loading

Один комментарий к “Что полезно знать начинающему в Си/Си++, сборка программы из нескольких файлов.”

  1. Исправил вывод исходного кода с новым плагином Uranov Syntax Highlighter, продолжающий дело автора плагина Crayon Syntax Highlighter.

Обсуждение закрыто.