Многофайловая сборка
Сборка из нескольких файлов
- Зачем много файлов? - Быстрее компилировать не все
- Проще ориентироваться
- Си: пространства имён!
 пример пример будем обращаться к нему по ходу лекции будем обращаться к нему по ходу лекции
 
- Скомпилировать сразу все файлы?
- (пере)компиляция только изменённых - Компиляция до .o файлов из примера + компоновка 
- Компоновка бинарника (ещё одна offline-тема из курса «ОС») 
 
- Сложность компоновки вручную с помощью ld: - cc -v hello.c - …
 
- /usr/lib64/gcc/x86_64-alt-linux/*/collect2 --help - …!
 
- strace -fvv -eexecve cc hello.c |& grep '"/usr/bin/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? 
 
- В репозитории с Д/З сделать (вложенный) подкаталог 02_Multifile и поместить туда код из Пример применения make - Убедиться, что он работает. Исправить ошибки, если они есть)
- Доделать Makefile так, чтобы в цели по умолчанию 
 
  Edit conflict - other version:
 Edit conflict - other version: 
- Собиралось две библиотеки: liboutput_static.a и liboutput.so из файлов fun.o и const.o (одна статическая, другая — динамическая) 
  Edit conflict - your version:
 Edit conflict - your version: 
- Собиралось две библиотеки: liboutput_static.a и liboutput.so из файлов fun.o и const.o (одна статическая, другая — динамическая) 
  End of edit conflict
 End of edit conflict 
- Собиралось три бинарника: prog (из .o-файлов), prog-a (из prog.o и liboutput_static.a) и prog-so (из prog.o и liboutput.so) 
- Имелась цель test:, для достижения которой - каждый из трёх бинарников запускается  - без параметров (при запуске без параметров на stderr выводится help — обратите внимание на перенаправление и на то, что argv[0] у программ не совпадают), - (перенаправление обоих выходных потоков (stderr и stdout) можно делать так: ./prog > outfile 2>&1) 
- (чтобы выводы совпали, в исходном тексте разрешается вместо argv[0] использовать одинаковую константу, например, "prog") 
 
- с одним каким-нибудь параметром
- и с тремя параметрами (для каждого бинарника параметры одинаковые).
 
- Затем выводы соответствующих запусков сравниваются (например, с помощью cmp file1 file2, который вернёт ненулевой статус ошибки, если файлы не одинаковы) 
 
- каждый из трёх бинарников запускается  
- И чтобы все генераты (включая файлы с выводами из тестов) удалялись по make clean! 
