make
make (укр. зробити) — утиліта для автоматичної побудови програм. Дії, що повинна виконати make, описують в спеціальних файлах, які називаються Makefile.
Зміст
1 Основні відомості
2 Походження
3 Сучасні версії
4 Використання
5 Make-файл
5.1 Приклад
5.2 Змінні
6 Зноски
7 Посилання
Основні відомості |
Make вказує послідовність дій, які повинні бути виконані заради побудови програми. В основному ця послідовність складається з викликів команд компілятора, компонувальника та файлової системи.
Основною особливістю утиліти make є те, що вона не просто виконує послідовність кроків, що може привести до великого часу побудови програми. Make виконує дії лише над тими файлами, які змінилися з часу попереднього виклику програми. Отже час на перебудову програми стає значно менший.
Походження |
До створення make системи складання (компіляції) у Unix звичайно складалися зі скриптів складання, що супроводжували сирцевий код програм.
make була створена Стюартом Фельдманом[en] в 1977 році в Bell Labs.
В даний час існує безліч утиліт для відстеження залежностей, але make — одна з найпоширеніших, в першу чергу завдяки тому, що вона включена в Unix, починаючи з версії PWB/UNIX (for Programmer's Workbench), яка містила інструменти для розробки програмного забезпечення.
Сучасні версії |
Існує декілька версій make, що базуються на першому 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 не вказана, використовується ім'я за умовчанням для make-файлу — Makefile (однак, в різних реалізаціях make крім цього можуть перевірятися і інші файли, наприклад GNUmakefile).
make відкриває make-файл, зчитує правила і виконує команди, необхідні для створення зазначеної цілі.
Make-файл |
Програма make виконує команди відповідно до правил в спеціальному файлі. Цей файл називається make-файл (makefile, мейкфайл). Як правило, make-файл описує, яким чином слід компілювати і компонувати програму.
make-файл складається з правил і змінних. Правила мають такий синтаксис:
ціль1 ціль2 ...: реквізит1 реквізит2 ...
Команда1
Команда2
...
Правило являє собою набір команд, виконання яких призведе до складання файлів-цілей з файлів-реквізиту.
Правило повідомляє 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. При збірці вручну потрібно дати такі команди:
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 на основі цих даних виконує таке:
- Збирає з цієї інформації правильну послідовність команд для отримання необхідних кінцевих файлів;
- Ініціює створення запланованого файлу тільки у випадку, якщо такого файлу не існує, або він старший за файли, від яких він залежить.
Якщо при запуску make явно не вказати ціль, то буде оброблятися перша ціль в 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. Процитовано 2017-10-24.
Посилання |
- BSD Make man page
- GNU Make
- The GNU make manual
- FreeBSD make manual page
- OPUS Makefile Tutorial
- GTK Hello World tutorial including HOWTO create Makefiles
- Recursive Make Considered Harmful
- What is wrong with make?
- What’s Wrong With GNU make?
Advanced Auto-Dependency Generation.