Відповіді:
За замовчуванням цілі Makefile є "файловими цілями" - вони використовуються для створення файлів з інших файлів. Make передбачає, що його мета - це файл, а це робить програму Makefiles відносно простою:
foo: bar
create_one_from_the_other foo bar
Однак іноді потрібно, щоб ваш Makefile запускав команди, які не представляють фізичні файли у файловій системі. Хорошими прикладами для цього є загальні цілі "чисто" та "все". Швидше за все, це не так, але, можливо,clean
у вашому головному каталозі може бути названий файл . У такому випадку Make буде заплутаний, оскільки за замовчуванням clean
ціль буде пов’язана з цим файлом, і Make запустить її лише тоді, коли файл не буде оновлений в залежності від його залежностей.
Ці спеціальні цілі називаються фальшивими, і ви можете чітко сказати Зробити, що вони не пов'язані з файлами, наприклад:
.PHONY: clean
clean:
rm -rf *.o
Тепер make clean
він запуститься, як очікувалося, навіть якщо у вас є ім’я з файлом clean
.
З точки зору Make, підроблена ціль - це просто ціль, яка завжди застаріла, тому щоразу, коли ви запитаєте make <phony_target>
, вона буде працювати, незалежно від стану файлової системи. Деякі загальні make
цілі, які часто фальшиво є: all
, install
, clean
, distclean
, TAGS
, info
, check
.
Припустимо, у вас є install
ціль, що дуже часто зустрічається в makefiles. Якщо ви не використовуєте .PHONY
, а названий файл install
існує в тому ж каталозі, що і Makefile, тоді make install
нічого не буде робити . Це пояснюється тим, що Make інтерпретує правило таким чином, щоб означати "виконувати такий-і-такий рецепт для створення файлу з назвою install
". Оскільки файл вже є, а його залежності не змінилися, нічого не буде зроблено.
Однак якщо ви зробите install
цільовий PHONY, він скаже інструменту make, що ціль вигадана, і цей make не повинен очікувати, що він створить фактичний файл. Отже, він не перевірить, чи install
існує файл, тобто: а) його поведінку не буде змінено, якщо файл існує, і б) додаткові stat()
не будуть викликатися.
Як правило, всі цілі у вашому Makefile, які не створюють вихідний файл з тим самим іменем, як ім'я цілі, повинні бути PHONY. Це , як правило , включає в себе all
, install
, clean
, distclean
, і так далі.
.sh
або .bash
розширення для "програм", які працюють так, як вони мають основну функцію, і резервуйте додавання розширення для бібліотек, які ви включаєте ( source mylib.sh
). Насправді я потрапив до цього питання ТАК, тому що у мене був сценарій у тому самому каталозі, що і мій Makefile називавсяinstall
.PHONY
весь час використовую ...
.PHONY
версія.
ПРИМІТКА : Інструмент make читає makefile і перевіряє часові позначки модифікації файлів з обох боків символу ':' у правилі.
У каталозі 'test' є такі файли:
prerit@vvdn105:~/test$ ls
hello hello.c makefile
У makefile правило визначається так:
hello:hello.c
cc hello.c -o hello
Тепер припустимо, що файл 'привіт' - це текстовий файл, що містить деякі дані, створений після файлу 'hello.c'. Отже модифікація (або створення) часової позначки "привіт" буде новішою, ніж "hello.c". Отже, коли ми будемо викликати "make hello" з командного рядка, він надрукує як:
make: `hello' is up to date.
Тепер перейдіть до файлу 'hello.c' та покладіть у нього білі пробіли, що не впливає на синтаксис чи логіку коду, тоді збережіть та закрийте. Тепер модифікація часу hello.c є новішою, ніж "hello". Тепер, якщо ви викликаєте "привіт", він виконує команди як:
cc hello.c -o hello
І файл 'привіт' (текстовий файл) буде перезаписаний новим бінарним файлом 'привіт' (результат вищевказаної команди компіляції).
Якщо ми використовуємо .PHONY у makefile так:
.PHONY:hello
hello:hello.c
cc hello.c -o hello
а потім викликати "привіт", він ігнорує будь-який файл, присутній у "тесті" pwd, і виконуватиме команду щоразу.
Тепер припустимо, що цільовий привіт не має оголошених залежностей:
hello:
cc hello.c -o hello
і файл 'привіт' вже присутній у тесті pwd ', тоді' make hello 'завжди відображатиметься як:
make: `hello' is up to date.
make
має сенс у цілому, це все про файли! Дякую за цю відповідь.
.PHONY: install
Найкращим поясненням є сам посібник GNU: розділ 4.6 «Цільові цілі» .
.PHONY
є одним із спеціальних вбудованих цільових імен марки . Є й інші цілі, які можуть вас зацікавити, тому варто переглядати ці посилання.
Коли настане час розглянути ціль .PHONY, make запустить її рецепт беззастережно, незалежно від того, існує файл з цим ім'ям або який його час останньої модифікації.
Можливо, вам також будуть цікаві стандартні цілі марки, такі як all
і clean
.
Існує також одна важлива хитра трактування ". FONY" - коли фізична ціль залежить від підробленої цілі, яка залежить від іншої фізичної цілі:
TARGET1 -> PHONY_FORWARDER1 -> PHONY_FORWARDER2 -> TARGET2
Ви просто очікуєте, що якщо ви оновили TARGET2, тоді TARGET1 слід вважати старим проти TARGET1, тому TARGET1 слід відновити. І це дійсно працює таким чином .
Найскладніша частина полягає в тому, що TARGET2 не є неспроможним проти TARGET1 - у такому випадку ви повинні очікувати, що TARGET1 не повинен бути відновлений.
Це дивно не працює, тому що: фальшива ціль все одно була запущена (як зазвичай це підроблені цілі) , що означає, що фальшива ціль вважається оновленою . І через це TARGET1 вважається несвіжим щодо хибної цілі .
Поміркуйте:
all: fileall
fileall: file2 filefwd
echo file2 file1 >fileall
file2: file2.src
echo file2.src >file2
file1: file1.src
echo file1.src >file1
echo file1.src >>file1
.PHONY: filefwd
.PHONY: filefwd2
filefwd: filefwd2
filefwd2: file1
@echo "Produced target file1"
prepare:
echo "Some text 1" >> file1.src
echo "Some text 2" >> file2.src
Ви можете пограти з цим:
Ви можете бачити, що файл файлів залежить від файлу1 опосередковано через хибну ціль - але він завжди перебудовується через цю залежність. Якщо змінити залежність в fileall
від filefwd
до file
, тепер fileall
не отримує перебудований кожен раз, але тільки тоді , коли який - або з залежних цілей несвіжий проти нього у вигляді файлу.
Спеціальна ціль .PHONY:
дозволяє оголошувати підроблені цілі, так щоmake
не перевіряти їх як фактичні імена файлів: вона буде працювати весь час, навіть якщо такі файли все ще існують.
Ви можете помістити кілька .PHONY:
у свої Makefile
:
.PHONY: all
all : prog1 prog2
...
.PHONY: clean distclean
clean :
...
distclean :
...
Є ще один спосіб оголосити підроблені цілі: просто поставте "::"
all :: prog1 prog2
...
clean ::
...
distclean ::
...
«::» має особливе значення: цілі є фальшивими плюс вони можуть з'являтися кілька разів:
clean ::
rm file1
...
clean ::
rm file2
Командні блоки будуть називатися один за одним.
Я часто використовую їх, щоб сказати, що ціль за замовчуванням не стріляти.
superclean: clean andsomethingelse
blah: superclean
clean:
@echo clean
%:
@echo catcher $@
.PHONY: superclean
Без фальшиво, make superclean
стрілятиме clean
, andsomethingelse
і catcher superclean
; але з PHONY make superclean
не запустить catcher superclean
.
Нам не потрібно турбуватися про те, щоб сказати зробити це clean
ціль - ТЕЛЕФОН, тому що це не зовсім фальшиво. Хоча він ніколи не видає чистий файл, він має команди для запуску, тому make вважатиме, що це кінцева мета.
Однак superclean
ціль справді є хибною, тому make make спробує скласти її з будь-яким іншим, що забезпечує деп-ціли для superclean
цілі - сюди входять інші superclean
цілі та %
ціль.
Зверніть увагу , що ми взагалі нічого не говорить про те, andsomethingelse
чи blah
, так що вони явно йдуть на видовище.
Вихід виглядає приблизно так:
$ make clean
clean
$ make superclean
clean
catcher andsomethingelse
$ make blah
clean
catcher andsomethingelse
catcher blah