make

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

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

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

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

Походження

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

make була створена Стюартом Фельдманом в 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

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

Зноски

  1. make. The Open Group Base Specifications Issue 7, 2016 Edition. Процитовано 24 жовтня 2017.

Посилання

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.