Немного о компиляции и сборке

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

Любое приложение консольного типа может запускаться с набором ключей (параметров). Для того, чтобы знать, какие ключи может принимать это приложение, необходимо запустить его с ключом --help или -h, в зависимости уже от реализации самого приложения. Например, об использовании компилятора GNU C++ можно узнать, выполнив следующую команду:

compiler 01
gcc --help

Чтобы скомпилировать файл main.cpp в файл file[.exe] достаточно написать следующую строку:

compiler 02
gcc main.cpp -o file -l stdc++

На самом деле можно попробовать запустить компиляцию файла только с указанием имени файла, но в этом случае компиляция будет успешна только в случае если программа использует только стандартную бублиотеку С, а полученный исполняемый файл будет называться a[.exe]. Поэтому ключ -o указывает, как будет называться выходной файл, то есть file. Ключ -l указывает, что к сборке результата необходимо добавить стандартную библиотеку С++. По правилам подключения библиотек программирования в ОС Linux, если файл библиотеки называется libfilename.a, то для подключения достаточно прописать -l filename. Либо указать полное имя библиотеки.

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

compiler 03
gcc main.cpp -ofile -lstdc++

Если проект приложения состоит из нескольких файлов, то для сборки приложения можно указать все компилируемые файлы:

compiler 04
gcc first.cpp second.cpp main.cpp -o file -lstdc++

Помните, что заголовочные файлы не комилируются!

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

compiler 05
gcc first.cpp -o fisrt.o -O2 -c -std=c++14
gcc second.cpp -o second.o -O2 -c -std=c++14
gcc main.cpp -o main.o -O2 -c -std=c++14
gcc first.o second.o main.o -o file -lstdc++ -love

Выполнять компиляцию каждого файла и исборку приложения - это становится утомительной процедурой. Поэтому для автоматизации данного процесса используют программу make и скрипты Makefile (файл сборки). Ниже прведен листинг Makefile.01, эквивалентный по функциональности командам compiler 05

Makefile.01
all: file

file: first.o second.o main.o
    gcc first.o second.o main.o -o file -lstdc++ -love
    
first.o: first.cpp
    gcc -c first.cpp -O2 -std=c++14

second.o: second.cpp
    gcc -c second.cpp -O2 -std=c++14

main.o: main.cpp
    gcc -c main.cpp -O2 -std=c++14

Правила написания makefile следующие:

  • каждый элемент документа есть структура

<цель> : [<зависимость> [...]]
    [<команда>]
  • каждая зависимость это определенная в документе Makefile цель или имя файла.

  • Целью может быть имя получаемого файла.

  • Цель может иметь несколько зависимостей, или не иметь вовсе. Если цель имеет зависимости, то сначала выполняются они, в том порядке, как они перечислены, а потом команда цели.

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

Makefile.02
CC = gcc
CXXFLAGS = -O2 -std=c++14
LDFLAGS = -lstdc++ -love
OUT = file

all: file

file: first.o second.o main.o
    $(CC) first.o second.o main.o -o $(OUT) $(LDFLAGS)
    
first.o: first.cpp
    $(CC) -c first.cpp $(CXXFLAGS)

second.o: second.cpp
    $(CC) -c second.cpp $(CXXFLAGS)

main.o: main.cpp
    $(CC) -c main.cpp $(CXXFLAGS)

Last updated