make

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

Основні відомості

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

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

Походження

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

Утиліту make створив 1977 року Стюарт Фельдман, який працював тоді у 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 Base Specifications Issue 7, 2016 Edition. Архів оригіналу за 28 грудня 2017. Процитовано 24 жовтня 2017.

Посилання