Відповіді:
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свого значення.