Чому Makefile рятує вас від копіювання команд GCC

1

Давайте будемо чесні. Вручну вводити довгі команди компіляції gcc – це біль. Ситуація швидко погіршується, коли ваша кодова база розростається, підключає декілька бібліотек, і ви щось підкручуєте. У результаті ви отримуєте кошмар із копіюванням та вставкою, який ламається, якщо ви пропустите один прапор.

На сцену виходять makefiles.

Вони існують з однієї причини: щоб змусити вас перестати вручну вводити ту саму послідовність компіляції знову і знову. Замість того, щоб запам’ятовувати точні прапори та порядок об’єктних файлів, ви пишете рецепт. Потім ви просто вводите make.

Як насправді працює Makefile

Ви починаєте із створення файлу з ім’ям буквально makefile. Без розширення. Лише ім’я. Усередині ви визначаєте залежність.

Ось базова структура для невеликого проекту на C:

`

Зверніть увагу на відступи. Тут новачки часто спотикаються. Ця прогалина перед gcc? Це має бути символ табуляції. Не вісім прогалин. Табуляція. Якщо ви використовуєте прогалини, make видасть загадкову помилку, і ви витратите десять хвилин, гадаючи, чому ваш синтаксис виглядає нормально для людського ока, але не для машини. Кожен рядок команди під залежністю має починатися з табуляції. Визначення залежностей самі мають бути притиснуті до лівого краю. Без винятків.

Логіка залежностей

У makefile є два типи рядків. Перший – це рядки залежностей. Вони виглядають як “мета: залежності”.

main.o: main.c util.h

Це перекладається як: Мені потрібен main.o. Щоб отримати його, мені потрібні main.c та util.h ».

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

Система працює за простим принципом: якщо будь-який файл у правій частині двокрапки новіший за файл у лівій частині, запускаються команди нижче. Змінили util.h? make бачить це, знає, що main.o та util.o залежать від нього, і перезбирає їх. Це автоматизує логіку.

Правило мети

Є одне золоте правило для початку вашого makefile. Перша зазначена мета – це та, яку make намагається побудувати за умовчанням.

У наведеному вище прикладі main – це перший рядок. Тому, коли ви запускаєте make без аргументів, він збирає кінцевий файл, що виконується.

main: main.o util.o
gcc -o main main.o util.o

Якщо ви зміните main.o, це запустить перескладання main. Якщо ви зміните main.c, це запустить main.o, який потім запустить main. Це ланцюгова реакція. Вам не потрібно керувати цим. Ви просто редагуєте вихідний код і запускаєте make.

Що робити, якщо я не на Unix?

Якщо ви використовуєте Windows або середовище IDE, як Visual Studio або Xcode, ви можете не побачити makefile у традиційному сенсі. Не панікуйте. Ваш компілятор, мабуть, має еквівалентний функціонал.

Інтегровані середовища розробки часто мають системи збирання «під капотом». Шукайте «Конфігурації збирання» або «Властивості проекту». Вони роблять те саме: відстежують залежності і перезбирають тільки те, що змінилося. Але якщо ви дотримуєтеся командного рядка, make є стандартом.

Більш широка картина

Використання make – це не