Відповіді:
VARIABLE = value
Нормальне встановлення змінної, але будь-які інші змінні, згадані з value
полем, рекурсивно розширюються їх значенням у точці, в якій використовується змінна, а не тій, яку вона мала, коли вона була оголошена
VARIABLE := value
Встановлення змінної з простим розширенням значень всередині - значення всередині неї розширюються під час оголошення.
VARIABLE ?= value
Встановлення змінної, лише якщо вона не має значення. value
завжди оцінюється при VARIABLE
зверненні. Це еквівалентно
ifeq ($(origin FOO), undefined)
FOO = bar
endif
Детальнішу інформацію див. У документації .
VARIABLE += value
Додавання доданого значення до існуючого значення (або встановлення цього значення, якщо змінна не існувала)
Використання =
призводить до присвоєння змінній значення. Якщо змінна вже мала значення, її замінюють. Це значення буде розширено при використанні. Наприклад:
HELLO = world
HELLO_WORLD = $(HELLO) world!
# This echoes "world world!"
echo $(HELLO_WORLD)
HELLO = hello
# This echoes "hello world!"
echo $(HELLO_WORLD)
Використання :=
подібне до використання =
. Однак замість значення, яке розширюється при його використанні, воно розширюється під час призначення. Наприклад:
HELLO = world
HELLO_WORLD := $(HELLO) world!
# This echoes "world world!"
echo $(HELLO_WORLD)
HELLO = hello
# Still echoes "world world!"
echo $(HELLO_WORLD)
HELLO_WORLD := $(HELLO) world!
# This echoes "hello world!"
echo $(HELLO_WORLD)
Використання ?=
призначає змінної значення, якщо змінна раніше не була призначена. Якщо для змінної раніше було присвоєно порожнє значення ( VAR=
), я вважаю , що це встановлено як я вважаю . Інакше функції точно так само =
.
Використовувати +=
подібне до використання =
, але замість заміни значення значення додається до поточного з проміжком між ними. Якщо змінна була встановлена раніше :=
, я думаю , вона буде розширена . Отримане значення розширюється, коли воно використовується, я думаю . Наприклад:
HELLO_WORLD = hello
HELLO_WORLD += world!
# This echoes "hello world!"
echo $(HELLO_WORLD)
Якщо б щось подібне HELLO_WORLD = $(HELLO_WORLD) world!
було використано, виникла б рекурсія, яка, швидше за все, закінчила б виконання вашого Makefile. Якби вони A := $(A) $(B)
були використані, результат не був би таким самим, як використання, +=
оскільки B
він розширений, :=
тоді як +=
не призведе B
до розширення.
VARIABLE = literal
і VARIABLE := literal
завжди рівнозначний. Я правильно зрозумів?
Я пропоную вам зробити кілька експериментів, використовуючи "make". Ось проста демонстрація, яка показує різницю між =
і :=
.
/* Filename: Makefile*/
x := foo
y := $(x) bar
x := later
a = foo
b = $(a) bar
a = later
test:
@echo x - $(x)
@echo y - $(y)
@echo a - $(a)
@echo b - $(b)
make test
відбитки:
x - later
y - foo bar
a - later
b - later bar
@
попереду кожен рецепт, щоб уникнути цього заплутаного повторення результатів.
/* ... */
коментар блоку
Якщо ви використовуєте VARIABLE = value
, якщо value
насправді є посилання на іншу змінну, то значення визначається лише тоді, коли VARIABLE
використовується. Це найкраще проілюструвати на прикладі:
VAL = foo
VARIABLE = $(VAL)
VAL = bar
# VARIABLE and VAL will both evaluate to "bar"
Під час використання VARIABLE := value
ви отримуєте значення такого, value
як є зараз . Наприклад:
VAL = foo
VARIABLE := $(VAL)
VAL = bar
# VAL will evaluate to "bar", but VARIABLE will evaluate to "foo"
Використання VARIABLE ?= val
означає, що ви встановлюєте лише значення, VARIABLE
якщо VARIABLE
воно вже не встановлено. Якщо його вже не встановлено, значення значення відкладається до тих пір, поки не VARIABLE
буде використано (як у прикладі 1).
VARIABLE += value
просто приєднує value
до VARIABLE
. Дійсне значення value
визначається таким, яким воно було, коли воно було встановлено спочатку, використовуючи =
або :=
.
У наведених вище відповідях важливо зрозуміти, що означає "значення розширюються під час декларації / використання". Надання такого значення, як *.c
і раніше, не тягне за собою будь-якого розширення. Лише тоді, коли ця рядок буде використана командою, вона, можливо, спровокує деяке глобулювання. Аналогічно, значення, яке подобається $(wildcard *.c)
або $(shell ls *.c)
не спричиняє будь-якого розширення, і повністю оцінюється під час визначення, навіть якщо ми використовуємо :=
у визначенні змінної.
Спробуйте наступний Makefile у каталозі, де у вас є декілька файлів C:
VAR1 = *.c
VAR2 := *.c
VAR3 = $(wildcard *.c)
VAR4 := $(wildcard *.c)
VAR5 = $(shell ls *.c)
VAR6 := $(shell ls *.c)
all :
touch foo.c
@echo "now VAR1 = \"$(VAR1)\"" ; ls $(VAR1)
@echo "now VAR2 = \"$(VAR2)\"" ; ls $(VAR2)
@echo "now VAR3 = \"$(VAR3)\"" ; ls $(VAR3)
@echo "now VAR4 = \"$(VAR4)\"" ; ls $(VAR4)
@echo "now VAR5 = \"$(VAR5)\"" ; ls $(VAR5)
@echo "now VAR6 = \"$(VAR6)\"" ; ls $(VAR6)
rm -v foo.c
Запуск make
викликає правило, яке створює додатковий (порожній) файл C, який називається, foo.c
але жодна з 6 змінних не має foo.c
свого значення.