Многофайловая сборка
Есть ли смысл говорить про персонализированную настройку окружения?
Сборка из нескольких файлов
- Зачем много файлов?
- Быстрее компилировать не все
- Проще ориентироваться
- Си: пространства имён!
пример будем обращаться к нему по ходу лекции
- Скомпилировать сразу все файлы?
- (пере)компиляция только изменённых
Компиляция до .o файлов из примера
Компоновка бинарника (ещё одна offline-тема из курса «ОС»)
(повтор: сложность команды компоновки вручную с помощью ld)
Make
Проблемы многофайловой сборки: вручную муторно, сценарий делает много лишнего
- Перекомпиляция только обновлённых исходников
- Построение графа зависимостей и подграфа пересборки
- Пример:
- Проект:
- Исходники — файлы на Си
- Из них компилируются объектники
- Из некоторых объектников собираются библиотеки
- Из некоторых объектников и библиотек собираются бинарники
Мы изменили один файл на си
- Что нуждается в пересборке?
- Проект:
- Удаление мусора и генератов
В том числе того, что разработчик считает генератом
- В примере выше:
- Бинарники, библиотеки и объектники — это генраты
- Однако иногда бинарники и библиотеки удалять не надо!
- Скриптование / code reuse / общая настройка приёмов сборки
- в т. ч. уникальных для проекта
- Например, все бинарники надо собирать с такими-то библиотеками, при компиляции испольозвать такие-то ключи и т. п.
ТАБУЛЯЦИИ!
Gnu make
(есть много, но этот популярнее всех остальных, вместе взятых)
- Цели и рецепты
«Как создать некий файл из других файлов» (например, prog.o из prog.c)
«некий файл» — цель (target, $@)
«другие файлы» — исходники (prerequisites, $^)
- «как создать» — рецепт (recipe, список команд, выделенных табуляцией)
Вариант с шаблоном: «как создать файл определённого типа из других файлов другого определённого типа» (например .o из .c)
- Командный интерпретатор ОС в качестве языка сценариев (как правило, shell)
Сборка цели считается неуспешной, если команда завершилась с ненулевым статусом (так делают компиляторы при ошибках)
- ⇒ недостаток: нужен shell под системы, в которых его нет (Windows)
- Переменные
- Специальные переменные
Подстановка / подстановка с заменой $(foo:.o=.c) / ... (ещё куча всякого $( … ))
Отложенная (=) и немедленная (::= или :=, это одно и то же) подстановка (например, в присваивании) (тут)
Много правил по умолчанию, make -p
- условные операторы / функции
- … чёрт в ступе …
- … и не только …
Литература по GNU Make
Очень старый учебник по старому Make (зато подробный и с объяснениями)
Managing Projects with GNU Make, 3rd Edition (гуглится☺)
Книга Владимира Игнатова Эффективное использование GNU Make
Пример
См. FrBrGeorge/MakefileExample
Другие низкоуровневые системы сборки
Ориентированные на ЯП и особенности сред программирования Apache_Ant/Apache_Maven (Java), Cabal (Haskell), ASDF (Lisp/CLisp), Boost.Build…
∃ Более высокий уровень — инструменты генерации сборочных сценариев (+окружение, +варианты сборки, +параметризация, +…), об этом после
Д/З
- Прочитать и прощёлкать
по возможности учебник по Make (про интеграцию с античной системой контроля версий SCCS лучше не читать☺). Есть ли отличия в поведении от GNU Make?
В репозитории с Д/З сделать (вложенный) подкаталог 03_Multifile и поместить туда код из Пример применения make
- Убедиться, что он работает. Исправить ошибки, если они есть)
Доделать Makefile так, чтобы
Собирались две библиотеки: liboutput_static.a и liboutput.so из файлов fun.o и const.o
Собиралось три бинарника: prog (из .o-фйалов), prog-a (из prog.o и liboutput_static.a) и prog-so (из prog.o и liboutput.so)
Имелась цель test:, для достижения которой
- каждый из трёх бинарников запускается
без параметров (обратите внимание на перенаправление stderr),
- с одним каким-нибудь параметром
- и с тремя параметрами (для каждого бинарника параметры одинаковые).
Затем выводы соответствующих запусков сравниваются (например, с помощью cmp file1 file2, который вернёт ненулевой статус ошибки, если файлы не одинаковы)
- каждый из трёх бинарников запускается
И чтобы все генераты (включая файлы с выводами из тестов) удалялись по make clean!