Makefile — файл с инструкции для утилиты make.
Утилита make — инструмент автоматизации сборки, читает Makefile и выполняет команды для компиляции и линковки программ (расскажу дальше), а также для многих других задач автоматизации.
Makefile отвечает на три вопроса:
Что нужно собрать? (цели) - название команды при вызове.
Из чего это состоит? (зависимости) - файлы, от которых зависит цель.
Как это собрать? (команды) - что выполнить для сборки цели.
базовый 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