make

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до: навігація, пошук

make (укр. зробити) — утиліта для автоматичної побудови програм. Дії, що повинна виконати make, описують в спеціальних файлах, які називаються Makefile.

Основні відомості[ред.ред. код]

Make вказує послідовність дій, які повинні бути виконані заради побудови програми. В основному ця послідовність складається з викликів команд компілятора, компонувальника та файлової системи.

Основною особливістю утиліти make є те, що вона не просто виконує послідовність кроків, що може привести до великого часу побудови програми. Make виконує дії лише над тими файлами, які змінилися з часу попереднього виклику програми. Отже час на перебудову програми стає значно менший.

Походження[ред.ред. код]

До створення make системи збірки (компіляції) у Unix звичайно складалися зі скриптів збірки, що супроводжували вихідний код програм.

make була створена Стюартом Фельдманом (Stuart Feldman) в 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, з тім чи іншим ступенем сумісності реалізований в різних версіях 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

Таким чином, один цільовий файл може вказуватися у кількох цілях. При цьому повний список залежностей для файлу буде складено зі списків залежностей всіх цілей, в яких він бере участь, створення файлу буде здійснюватися тільки один раз.

Посилання[ред.ред. код]