Makefile — файл с инструкции для утилиты make.

Утилита make — инструмент автоматизации сборки, читает Makefile и выполняет команды для компиляции и линковки программ (расскажу дальше), а также для многих других задач автоматизации.

Makefile отвечает на три вопроса:

  1. Что нужно собрать? (цели) - название команды при вызове.

  2. Из чего это состоит? (зависимости) - файлы, от которых зависит цель.

  3. Как это собрать? (команды) - что выполнить для сборки цели.

базовый Makefile

цель: зависимости команда

Важно соблюдать лестничную структуру команд и создает ее именно Tab (НЕ пробелы)

eat: (зависимости пока нет)

gcc ./eat.c (необходимо исполнить) -o (флаг говорящий, задаю имя исполняемого файла) eat.out (имя исполняемого файла, может быть людым)

Вызов команды

make eat

Все пути в Makefile строятся относительно расположения файла

Дальше будем предполагать что у нас такая структура проекта

src

materials

.clang-format

build

eat.c

sleep.c

code.c

static_day.c

dinamic_day.c

repeat.c

Makefile

Перепишем команду кушать относительно этой структуры. Будем складывать все исполняемые файлы в папку build

eat:

gcc ./eat.c -o ./build/Eat

Добавим побольше проверок чтобы все наверняка работало

eat:

gcc -Wall -Werror -Wextra -std=c11 -pedantic -pedantic-errors ./eat.c -o ./build/Eat

Создадим вторую команду и сразу с проверками

eat:

gcc -Wall -Werror -Wextra -std=c11 -pedantic -pedantic-errors ./eat.c -o ./build/Eat

sleep:

gcc -Wall -Werror -Wextra -std=c11 -pedantic -pedantic-errors ./sleep.c -o ./build/Sleep

Одинковые фрагменты можно складывать в переменные и использовать в дальнейшем. Как например эти флаги разнообразных проверок

FLAGS := -Wall -Werror -Wextra -std=c11 -pedantic -pedantic-errors

Заменим повторения на переменную

FLAGS := -Wall -Werror -Wextra -std=c11 -pedantic -pedantic-errors

eat:

gcc $(FLAGS) ./eat.c -o ./build/Eat

sleep:

gcc $(FLAGS) ./sleep.c -o ./build/Sleep

А что если написать make без команды?

Выполнится первая с веруху команды

А как сделать чтобы по умолчанию при команде make выполнылись все уже существующие команды и вообще не перечислять их.

Можно прописать это в Makefile обозначив команду именем all и в зависимостях указать какие именно команды надо испольнять

FLAGS := -Wall -Werror -Wextra -std=c11 -pedantic -pedantic-errors

all: eat sleep

eat:

gcc $(FLAGS) ./eat.c -o ./build/Eat

sleep:

gcc $(FLAGS) ./sleep.c -o ./build/Sleep

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

pre_build:
cp ../materials/.clang-format .
clang-format -i .c .h
clang-format -n .c .h
cppcheck --enable=all --suppress=missingIncludeSystem .

FLAGS := -Wall -Werror -Wextra -std=c11 -pedantic -pedantic-errors

all: pre_build eat sleep

eat:

gcc $(FLAGS) ./eat.c -o ./build/Eat

sleep:

gcc $(FLAGS) ./sleep.c -o ./build/Sleep

pre_build:
cp ../materials/.clang-format .
clang-format -i .c .h
clang-format -n .c .h
cppcheck --enable=all --suppress=missingIncludeSystem .

Кажется файлы только создаются и не чистятся (почистим целиком папку build и удалим файл .clang-format)

clean:

rm -f ./build/* .clang-format

Думаю вы уже сами можете создать команду rebuild

Сборка статических пакетов

В процессе сборки есть два этапа компеляции и линьковки

Флаг -c позволяет остановится на этапе компеляции без линьковки (без уточнения зависимостей. Написано, что пирожок где-то есть и мы не уточняем где .Просто верим, что он есть)

Зачем это нужно?

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

Сделаем несколько исполняемых файлов без линковки

repeat:

gcc $(FLAGS) -c ./eat.c -o ./build/Eat

gcc $(FLAGS) -c ./sleep.c -o ./build/Sleep

Но пока что это не библиотек По сути в си библиотека это архив и чтобы пакеты стали библиотекой надо заархивировать испольняемые файлы Что мы можем сделать командой

ar -rcs (Название архива. Назовем одноименно с названием команды: repeat.a) ./build/Eat ./build/Sleep

Получается вот такая команда для создание статического пакета

repeat.a:

gcc $(FLAGS) -c ./eat.c -o ./build/Eat

gcc $(FLAGS) -c ./sleep.c -o ./build/Sleep

ar -rcs repeat.a ./build/Eat ./build/Sleep

Пакет можно подключать в зависимостях команды

static_day: repeat.a

gcc $(FLAGS) ./static_day.c -o ./build/Static_lib repeat.a

Хочу разбить на несколько строк для красоты при это в конце строки кроме последней надо подставалять \

static_day: repeat.a

gcc $(FLAGS) ./static_day.c \

-o ./build/Static_lib \

repeat.a

Сборка динамического пакета

Команда для сборки динамического пакета

dinamic_day.so: data_stat.a

gcc $(FLAGS) -fPIC -shared -o dinamic_day.so ./dinamic_day.c data_stat.a