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

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

Зноски Редагувати

  1. make. The Open Group[en] Base Specifications Issue 7, 2016 Edition. Архів оригіналу за 28 грудня 2017. Процитовано 24 жовтня 2017. 

Посилання Редагувати