make - утиліта, яка автоматизує процес перетворення файлів з однієї форми в іншу. Найчастіше це компіляція вихідного коду в об'єктні файли і подальша компонування у виконувані файли або бібліотеки.
Утиліта використовує спеціальні make-файли, в яких вказані залежності файлів один від одного і правила для їх задоволення. На основі інформації про час останнього зміни кожного файлу make визначає і запускає необхідні програми.
До створення make системи збирання (компіляції) ПО Unix зазвичай складалися з shell-скриптів збірки, які супроводжували вихідний код програм.
make була створена Стюартом Фельдманом (Stuart Feldman) в 1977 році в Bell Labs.
В даний час існує безліч утиліт для відстеження залежностей, але make - одна з найбільш широко поширених, в першу чергу завдяки тому, що вона включена в Unix, починаючи з версії PWB / UNIX (англ. Programmer's Workbench), яка містила інструменти для розробки програмного забезпечення.
Існує кілька версій make. заснованих на оригінальній make або написаних з нуля, що використовують ті ж самі формати файлів і базові принципи і алгоритми, а також містять деякі поліпшення і розширення. наприклад:
- BSD make. заснована на роботі Адама де Бура (Adam de Boor) над версією make. з можливістю паралельної збірки; в тій чи іншій формі перейшла в FreeBSD, NetBSD і OpenBSD.
- GNU make - входить в більшість дистрибутивів Linux і часто використовується в поєднанні з GNU build system.
POSIX включає в себе стандарт основних можливостей утиліти make. з тим або іншим ступенем сумісності реалізований в різних версіях make. Як правило, прості make-файли можуть бути успішно використані різними версіями make.
Якщо опція -f не вказана, використовується ім'я за замовчуванням для make-файлу - Makefile (проте, в різних реалізаціях make крім цього можуть перевірятися і інші файли, наприклад GNUmakefile).
make відкриває make-файл, зчитує правила і виконує команди, необхідні для створення зазначеної мети.
Стандартні цілі для збірки дистрибутивів GNU:
У процесі складання додатків BSD часто застосовують:
- depend - виконати компіляцію / вибудовування залежностей
Програма make виконує команди згідно з правилами, зазначеним у спеціальному файлі. Цей файл називається make-файл (makefile, мейкфайл). Як правило, make-файл описує, яким чином потрібно компілювати і компонувати програму.
make-файл складається з правил і змінних. Правила мають наступний синтаксис:
Правило являє собою набір команд, виконання яких приведе до збірки файлів-цілей з файлів-реквізиту.
Правило повідомляє make. що файли, одержувані в результаті роботи команд (цілі) є залежними від відповідних файлів-реквізиту. make не відчуває і не використовує вміст файлів-реквізиту, однак, вказівка списку файлів-реквізиту потрібно тільки для того, щоб make переконалася в наявності цих файлів перед початком виконання команд і для відстеження залежностей між файлами.
Зазвичай мета являє собою ім'я файлу, який генерується в результаті роботи зазначених команд. Метою також може служити назва деякого дії, яке буде виконано в результаті виконання команд (наприклад, мета clean в make-файлах для компіляції програм зазвичай видаляє всі файли, створені в процесі компіляції).
Рядки, в яких записані команди. повинні починатися з символу табуляції.
Розглянемо нескладну програму на Сі. Нехай програма program складається з пари файлів коду - main.c і lib.c, а також з одного заголовки - defines.h, який підключений в обидва файли коду. Тому, для створення program необхідно з пар (main.c defines.h) і (lib.c defines.h) створити об'єктні файли main.o і lib.o, а потім скомпонувати їх в program. При складанні вручну потрібно дати наступні команди:
Якщо в процесі розробки програми в файл defines.h будуть внесені зміни, потрібно перекомпіляція обох файлів і лінковка, а якщо змінимо lib.c, то повторну компіляцію main.о можна не виконувати.
Таким чином, для кожного файлу, який ми повинні отримати в процесі компіляції потрібно вказати, на основі яких файлів і з допомогою якої команди він створюється. Програма make на основі цих даних виконує наступне:
- збирає з цієї інформації правильну послідовність команд для отримання необхідних результуючих файлів;
- і ініціює створення необхідного файлу тільки в разі, якщо такого файлу не існує, або він старше, ніж файли від яких він залежить.
Якщо при запуску make явно не вказати мету, то буде оброблятися перша мета в make-файлі, ім'я якої не починається з символу «.».
Для програми program досить написати наступний make-файл:
Варто відзначити ряд особливостей. В імені другої мети вказані два файли і для цієї ж мети не вказана команда компіляції. Крім того, ніде явно не вказана залежність об'єктних файлів від «* .c»-файлів. Справа в тому, що програма make має зумовлені правила для отримання файлів з певними розширеннями. Так, для мети-об'єктного файлу (розширення «.o») при виявленні відповідного файлу з розширенням «.c» буде викликаний компілятор «сс -з» із зазначенням в параметрах цього «.c»-файлу і всіх файлів-залежностей.
Синтаксис для визначення змінних:
Значним може бути довільна послідовність символів, включаючи пробіли та звернення до значень інших змінних. З урахуванням сказаного, можна модифікувати наш make-файл наступним чином:
Потрібно відзначити, що обчислення значення змінних відбувається лише за потреби (використовується так зване ліниве обчислення). Наприклад, при складанні мети all з наступного make-файлу на екран буде виведений рядок «Huh?».
Припустимо, що до проекту додався другий заголовки lib.h, який включається тільки в lib.c. Тоді make-файл збільшиться ще на одну сходинку:
Таким чином, один цільової файл може вказуватися в декількох цілях. При цьому повний список залежностей для файлу буде складено зі списків залежностей всіх цілей, в яких він бере участь, створення файлу буде проводитися тільки один раз.