compile_flags = -O3 -funroll-loops -fomit-frame-pointer
Такой способ поддерживают все варианты утилиты make. Его можно сравнить, например, с заданием макроса в языке Си.
#define compile_flags "-O3 -funroll-loops -fomit-frame-pointer"
Значение переменной, заданной с помощью оператора '=', будет вычислено в момент
ее использования. Например, при обработке make-файла:
var1 = one
var2 = $(var1) two
var1 = three
all:
@echo $(var2)
на экран будет выдана строка ``three two''. Значение переменной var2 будет вычислено непосредственно в момент выполнения команды echo, и будет представлять собой текущее значение переменной var1, к которому добавлена строка ``two''. Как следствие - одна и та же переменная не может одновременно фигурировать в левой и правой части выражения, так как это может привести к бесконечной рекурсии. GNU Make распознает подобные ситуации и прерывает обработку make-файла. Следующий пример вызовет ошибку:
compile_flags = -pipe $(compile_flags)
GNU Make поддерживает также и второй, новый способ задания переменной - с помощью оператора ':=':
compile_flags := -O3 -funroll-loops -fomit-frame-pointer
В этом случае переменная работает подобно ``обычным'' текстовым переменным в каком-нибудь из языков программирования. Вот приблизительный аналог этого выражения на языке C++:
string compile_flags = "-O3 -funroll-loops -fomit-frame-pointer";
Значение переменной вычисляется в момент обработки оператора присваивания.
Если, например, записать
var1 := one
var2 := $(var1) two
var1 := three
all:
@echo $(var2)
то при обработке такого make-файла на экран будет выдана строка ``one two''.
Переменная может ``менять'' свое поведение в зависимости от того, какой из операторов присваивания был к ней применен последним. Одна и та же переменная на протяжении своей жизни вполне может вести себя и как ``макрос'' и как ``текстовая переменная''.
Зависимости цели edit в примерах выше являлись аргументами для команд
компоновки. Можно избежать их повторения, определив переменную, которая будет
содержать имена всех объектных файлов.
OBJS = edit.o kbd.o commands.o display.o
# Makefile for simple editor
Строка, начинающаяся с ``OBJS ='' определяет переменную OBJS, на которую
можно в дальнейшем сослаться через ``$(OBJS)'' или ``$OBJS''. Эти
более поздние ссылки приводят к тому, что обозначение OBJ будет дословно
заменяться, прежде чем правило будет обработано. Иногда неудобно, что и gmake
и shell используют `$' как префикс для ссылок на переменные; gmake
определяет `$$', такое же, как `$', позволяя Вам передавать `$' в shell,
если это необходимо.
insert.o search.o files.o utils.o
edit : $(OBJS)
gcc -g -o edit $(OBJS)
Иногда Вам может понадобиться величина, выглядящая как обычная переменная,
но с некоторыми уточнениями. Например, задавая переменную со списком имен
всех исходных файлов, Вы можете захотеть задать имена всех получающихся
объектных файлов. Можно переопределить OBJS следующим образом.
SRCS = edit.cc kbd.cc commands.cc display.cc
Суффикс уточнения `:.cc=.o' определяет необходимые уточнения. Теперь у нас
есть переменные для имен всех исходных и объектных файлов, при этом не пришлось
повторять в определениях множество имен.
insert.cc search.cc files.cc utils.cc
OBJS = $(SRCS:.cc=.o)
Переменные могут быть упомянуты и в командной строке при вызове gmake.
Например, если make-файл содержит
edit.o: edit.cc
то команда типа
gcc $(DEBUG) -c -Wall edit.cc
gmake DEBUG=-g ...
приведет к использованию ключа -g
(добавить символическую информацию отладчика) при компиляции, а отсутствие
DEBUG=-g
исключит использование этого ключа. Определения
переменных в командной строке имеют преимущество перед определениями
внутри make-файла, что позволяет задать в make-файле значения по умолчанию.
Переменные, не установленные любым из перечисленных методов, могут быть установлены как переменные среды. Поэтому, последовательность команд
setenv DEBUG -g gmake ...
для последнего примера также приведет к использованию ключа -g во время компиляции.