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''
.
Переменная может ``менять'' свое поведение в зависимости от того, какой из операторов присваивания был применен к ней последним. Одна и та же переменная на протяжении ее жизни может вести себя и как ``макрос'', и как ``текстовая переменная''.
Зависимости цели
OBJS = edit.o kbd.o commands.o display.o
edit
в приведенных выше примерах являлись аргументами для команд
компоновки. Можно избежать их повторения, определив переменную, которая будет
содержать имена всех объектных файлов:
Makefile for simple editor
Строка, начинающаяся с
insert.o search.o files.o utils.o
edit : $(OBJS)
gcc -g -o edit $(OBJS)
``OBJS =''
определяет переменную OBJS
, на которую
можно в дальнейшем сослаться через ``$(OBJS)'' или ``OBJS''.
Эти более поздние ссылки приводят к тому, что обозначение OBJ
будет дословно
заменяться, прежде чем правило будет обработано. Иногда неудобно, что и gmake
и shell
используют `$'
как префикс для ссылок на переменные; gmake
определяет `$$'
, такое же, как `$'
, позволяя вам передавать `$'
в shell
,
если это необходимо.
Иногда вам может понадобиться величина в виде обычной переменной,
но с некоторыми уточнениями. Например, задавая переменную со списком имен
всех исходных файлов, вы можете попытаться задать имена всем получающимся
объектным файлам. Можно переопределить OBJS
следующим образом:
SRCS = edit.cc kbd.cc commands.cc display.cc
Суффикс
insert.cc search.cc files.cc utils.cc
OBJS = $(SRCS:.cc=.o)
`:.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 во время компиляции.