make (укр. зробити) — утиліта для автоматичної побудови програм. Дії, які має виконати make, описують у спеціальних файлах, які називаються Makefile.
Основні відомості
Makefile задає послідовність дій, які мають бути виконані для побудови програми. В основному ця послідовність складається з викликів команд компілятора, компонувальника та файлової системи.
Основною особливістю утиліти make є те, що вона виконує дії лише з тими файлами, які змінилися з часу попереднього виклику програми. Отже, час на перебудову програми значно скорочується.
Походження
До створення make, системи побудови програм у Unix складалися з різних скриптів, що супроводжували початковий код програм.
Утиліту make створив 1977 року Стюарт Фельдман[en], який працював тоді у Bell Labs.
Для обробки залежностей розроблено багато утиліт, але make — одна з найпоширеніших, у першу чергу тому, що вона включена в Unix, починаючи з версії PWB/UNIX (for Programmer's Workbench), яка містила інструменти для розробки програмного забезпечення.
Сучасні версії
Існує декілька версій make, які базуються на оригіналі або ж написані заново, що застосовують однакові формати файлів і базові принципи й алгоритми, а також містять деякі поліпшення й розширення. Наприклад:
- BSD make, заснована на роботі Адама де Бура (Adam de Boor) над версією make, із можливістю паралельної побудови; у тій чи іншій формі вона перейшла в FreeBSD, NetBSD і OpenBSD.
- GNU make — входить до більшості дистрибутивів GNU/Linux і часто застосовується у поєднанні з GNU build system.
POSIX містить стандарт основних можливостей утиліти make[1][відсутнє в джерелі], з тим чи іншим ступенем сумісності реалізований у різних версіях make. Як правило, прості make-файли можуть бути успішно виконані різними версіями make.
Застосування
make [-f make-файл] [мета] ...
Якщо опцію -f не задано, застосовується назва файлу за умовчанням — Makefile (однак, у різних реалізаціях make крім того можуть перевірятися й інші файли, наприклад GNUmakefile).
make відкриває файл, зчитує правила й виконує команди, необхідні для досягнення зазначеної мети (англ. target).
Якщо при запуску make явно не задано мету, то буде оброблятися перша мета в make-файлі, назва якої не починається з символу «.».
Make-файл
make виконує команди відповідно до правил, заданих у файлі. Цей файл називається make-файл (makefile, мейкфайл). Здебільшого, make-файл описує, яким чином слід компілювати й компонувати програму.
make-файл складається з правил і змінних. Правила описують залежності й мають такий синтаксис:
мета1 [мета2] ...: компонент1 [компонент2] ... Tab ↹команда1 Tab ↹команда2 ...
Рядки, в яких записано команди, мають починатися з символу табуляції.
Правило повідомляє make про залежність мети (вона може бути не одна) (мета1, мета2) від компонентів (компонент1, компонент2). І мета і компонента зазвичай є файлами, тоді послідовність команд (команда1, команда2) будує файл-мету із файлів-компонент. Утім, мета може бути не файлом, а результатом виконання команд. Наприклад, мета clean у make-файлах для компіляції програм зазвичай видаляє всі файли, створені в процесі компіляції.
make ніяк не перевіряє вміст файлів компоненти чи мети. Зазначення списку файлів-компонент потрібно тільки для того, щоб make переконалася в наявності цих файлів перед початком виконання команд, та для відстеження залежностей між файлами. Для цього утиліта перевіряє час їх останньої зміни.
Приклад
Нехай програма на C складається з двох файлів коду — main.c
та lib.c
—, й одного файлу заголовків — defines.h
, який включається в обидва файли коду.
Тоді для створення program необхідно з пар (main.c
defines.h
) та (lib.c
defines.h
) створити об'єктні файли (main.o
і lib.o
), а потім злінкувати їх у program
. При збірці вручну потрібно дати такі команди:
cc -c main.c defines.h cc -c lib.c defines.h cc -o program main.o lib.o
Якщо в процесі розробки програми у файл defines.h
внесено зміни, то потрібно перекомпілювати обидва файли й виконати лінкування, а якщо змінюється лише lib.c
, то повторну компіляцію main.о
можна не виконувати.
Таким чином, для кожного файлу, який утворюється в процесі компіляції, можна вказати, на основі яких файлів, а також за допомогою якої команди він створюється. Програма make на основі цих даних:
- Збирає з цієї інформації правильну послідовність команд для отримання необхідних кінцевих файлів;
- Ініціює створення визначеного в правилах файлу, якщо такого файлу не існує або ж він старіший за файли, від яких залежить.
Для програми program
достатньо написати такий make-файл:
program: main.o lib.o cc -o program main.o lib.o main.o lib.o: defines.h
Варто відзначити низку особливостей. У назві другої мети вказано два файли і для цієї мети не задано команду компіляції. Крім того, ніде явно не задано залежність об'єктних файлів від «*.c»-файлів. Справа в тому, що make має вбудовані правила для отримання файлів із певними розширеннями. Так, якщо метою є об'єктний файл (розширення «.о») при виявленні відповідного файлу з розширенням «.с» буде викликано компілятор «сс -с
» із зазначенням у параметрах цього «.с»-файлу і всіх файлів, від яких він залежить[джерело?].
Змінні
Синтаксис для визначення змінних:
змінна = значення
Значенням може бути довільна послідовність символів, включаючи пробіли і звернення до значень інших змінних.
Із застосуванням змінних можна модифікувати вищенаведений make-файл таким чином:
OBJ = main.o lib.o program: $(OBJ) cc -o program $(OBJ) $(OBJ): defines.h
Слід зазначити, що для змінних застосовується так зване ліниве обчислення — значення обчислюється тільки в момент звернення до змінної (а не в момент її визначення). Наприклад, якщо задати мету all для такого make-файлу:
foo = $(bar) bar = $(ugh) ugh = Що? all: echo $(foo)
то на екран буде виведено рядок «Що?».
Припустимо, що до вищезгаданого проекту додано другий файл заголовків lib.h
, який включається тільки в lib.c
. Тоді make-файл збільшиться на один рядок:
lib.o: lib.h
Таким чином, один цільовий файл можна вказати як мету у кількох правилах. Повний список залежностей для файлу буде складено зі списків залежностей для кожної мети, у яких його вказано, однак створення такого файлу буде здійснюватися тільки один раз.
Зноски
- ↑ make. The Open Group[en] Base Specifications Issue 7, 2016 Edition. Архів оригіналу за 28 грудня 2017. Процитовано 24 жовтня 2017.
Посилання
- BSD Make man page
- GNU Make [Архівовано 5 липня 2006 у Wayback Machine.]
- The GNU make manual [Архівовано 25 листопада 2008 у Wayback Machine.]
- FreeBSD make manual page [Архівовано 22 грудня 2013 у Wayback Machine.]
- OPUS Makefile Tutorial [Архівовано 11 грудня 2008 у Wayback Machine.]
- GTK Hello World tutorial including HOWTO create Makefiles
- Recursive Make Considered Harmful
- What is wrong with make?
- What’s Wrong With GNU make? [Архівовано 13 серпня 2016 у Wayback Machine.]
- Advanced Auto-Dependency Generation [Архівовано 25 грудня 2008 у Wayback Machine.].