The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

Каталог документации / Раздел "Программирование, языки" / Оглавление документа
Вперед Назад Содержание

6. Как использовать переменные

Переменная представляет собой имя, определенное в make-файле для представления текстовой строки, называемой значением переменной. Такое значение подставляется, при явном указании на это, в цели, зависимости, команды и другие части make-файла. (В некоторых других версиях программы make переменные называются макросами.)

Переменные и функции во всех частях make-файла вычисляются при их чтении, за исключением команд командной оболочки в правилах, правой части определения переменной с использованием символа '=' и тел определений переменных с использованием директивы define.

Переменные могут представлять списки имен файлов, опции, передаваемые компилятору, запускаемые программы, каталоги для поиска исходных файлов, каталоги для записи выхода, или все остальное, что вы можете представить.

Именем переменной может быть любая последовательность символов, не содержащая символов ':', '#', '=' , а также начальных или конечных пробелов. Однако, следует избегать имен переменных, содержащих символы, отличные от букв, цифр и символов подчеркивания, поскольку таким символам в будущем может быть назначено специальное значение, а в некоторых командных оболочках их нельзя будет передать через командную среду порожденному процессу make (смотрите раздел 5.6.2 [Связь порожденным процессом make через переменные]).

Имена переменных чувствительны к регистру. Каждое из имен 'foo', 'FOO' и 'Foo' ссылается на отдельную переменную.

Традиционным является использование в именах переменных больших букв, но мы рекомендуем использовать маленькие буквы для имен переменных, служащих в make-файла для внутренних нужд, и резервировать верхний регистр для параметров, управляющих неявными правилами, и для параметров, которые предназначены для переопределения пользователем при помощи опции командной строки (смотрите раздел 9.5 [Перекрывающиеся переменные]).

Несколько переменных имеют имена, представляющие собой одиночный символ пунктуации или несколько таких символов. Это автоматические переменные, и они имеют отдельно оговоренное использование. Смотрите раздел 10.5.3 [Автоматические переменные].

6.1 Основы обращения к переменным

Для подстановки значения переменной напишите знак доллара с последующим именем переменной в круглых или фигурных скобках: как '$(foo)', так и '${foo}' являются правильными ссылками на переменную foo. Это специальное значение символа '$' является причиной того, что вы должны писать '$$' для обеспечения эффекта появления одного знака доллара в имени файла или команде.

Ссылки на переменные могут быть использованы в любом контексте: в целях, в зависимостях, в командах, в большинстве директив и в значениях новых переменных. Вот типичный пример, в котором переменная содержит имена всех объектных файлов программы:

      objects = program.o foo.o utils.o   
      program : $(objects)   
              cc -o program $(objects)   
    
      $(objects) : defs.h   
Ссылки на переменные обрабатываются при помощи строгой текстуальной подстановки. Таким образом, правило

      foo = c   
      prog.o : prog.$(foo)   
              $(foo)$(foo) -$(foo) prog.$(foo)   
могло бы быть использовано для компиляции C-программы 'prog.c'. Так как при присвоении переменной значения пробелы, предшествующие ему, игнорируются, значением переменной foo является именно 'c'. (На самом деле вам не рекомендуется писать make-файлы таким образом !)

Если за знаком доллара следует символ, отличный от знака доллара или открывающейся круглой или квадратной скобки, то этот символ обрабатывается как имя переменной. Таким образом, вы могли бы обратиться к переменной x при помощи '$x'. Однако, такая практика крайне нежелательна, за исключением случая автоматических переменных (смотрите раздел 10.5.3 [Автоматические переменные]).

6.2 Две разновидности переменных

Есть два способа, с помощью которых переменная в GNU-версии программы make может получить значение - мы будем называть их двумя разновидностями переменных. Две разновидности различаются тем, как они определяются и что с ними просиходит при их вычислении.

Первая разновидность переменной - это рекурсивно вычисляемая переменная. Переменные такого рода определяются в пределах одной строки make-файла с использованием символа '=' (смотрите раздел 6.5 [Установка переменных]), или при помощи директивы define (смотрите раздел 6.8 [Определение многостроковых переменных]). Определяемое вами значение устанавливается неявным образом - если переменная содержит ссылки на другие переменные, они заменяются на значения всегда, когда происходит подстановка переменной (во время вычисления какой-либо другой строки). Когда такое происходит, это называется рекурсивным вычислением.

Например, фрагмент make-файла

      foo = $(bar)   
      bar = $(ugh)   
      ugh = Huh?   
    
      all:;echo $(foo)   
отобразит на экране 'Huh?': ссылка на переменную '$(foo)' заменяется на ссылку на переменную '$(bar)', которая заменяется на ссылку на переменную '$(ugh)', которая, наконец, заменяется на 'Huh?'.

Только эта разновидность переменных поддерживается другими версиями программы make. Она имеет свои достоинства и недостатки. Преимущество (по мнению большинства) заключается в том, что следующий фрагмент:

      CFLAGS = $(include_dirs) -O   
      include_dirs = -Ifoo -Ibar   
сделает то, что предполагается: когда в команде происходит 'CFLAGS' вычисление, результатом вычисления будет '-Ifoo -Ibar -O'. Основным недостатком является то, что вы не можете ничего добавить в конец переменной, как показано ниже:

      CFLAGS = $(CFLAGS) -O   
поскольку это вызовет бесконечный цикл при вычислении переменной. (На самом деле, программа make обнаруживает бесконечный цикл и сообщает об ошибке.)

Еще один недостаток состоит в том, что любая функция (смотрите главу 8 [Функции преобразования текста]), упомянутая в определении, будет выполняться каждый раз при вычислении переменной. Это замедляет выполнение программы make; хуже того, это приводит к тому, что функции wildcard и shell дают непредсказуемые результаты, так как вы не можете легко проконтролировать, когда, и даже сколько раз, они вызываются.

Для того, чтобы избавиться от всех проблем и неудобств рекурсивно вычисляемых переменных, есть другая разновидность: упрощенно вычисляемые переменные.

Упрощенно вычисляемые переменные определяются в пределах одной строки make-файла с использованием ':=' (смотрите раздел 6.5 [Установка переменных]). Значение упрощенно вычисляемой переменной просматривается один раз за все время работы с ней, при этом в ее определении происходит замена всех ссылок на другие переменные и функции на их значения. В действительности, значением упрощенно вычисляемой переменной является результат вычисления написанного вами текста. Оно не содержит никаких ссылок на другие переменные - она содержит их значения на тот момент, когда она определялась. Следовательно, данный фрагмент:

      x := foo   
      y := $(x) bar   
      x := later   
эквивалентнен следующему:

      y := foo bar   
      x := later   
При ссылке на упрощенно вычисляемую переменную, происходит просто подстановка ее значения.

Вот несколько более сложный пример, иллюстрирующий использование ':=' вместе с функцией shell. (смотрите раздел 8.6 [Функция shell]). Этот пример также показывает использование переменной MAKELEVEL, которая изменяется при ее передаче с одного уровня на другой. (Смотрите раздел 5.6.2 [Связь порожденным процессом make через переменные] для информации о переменной MAKELEVEL.)

      ifeq (0,${MAKELEVEL})   
      cur-dir   := $(shell pwd)   
      whoami    := $(shell whoami)   
      host-type := $(shell arch)   
      MAKE := ${MAKE} host-type=${host-type} whoami=${whoami}   
      endif   
Преимущество такого использования ':=' состоит в том, что типичная команда 'спуска в каталог' выглядит в данном случае так:

      ${subdirs}:   
            ${MAKE} cur-dir=${cur-dir}/$@       -C $@      all   
Упрощенно вычисляемые переменные, вообще говоря, делают программирование сложных make-файлов более предсказуемым, поскольку они работают, как переменные в большинстве языков программирования. Они позволяют вам переопределять переменную, используя ее собственное значение (или ее значение, обработанное некоторым образом одной из преобразующей функций) и намного более эффективно использовать преобразующие функции (смотрите главу 8 [Функции преобразования текста]).

Вы также можете использовать их для внесения в значения переменных управляемого ведущего пробела. Ведущие пробельные символы удаляются из вашего указанного вами значения перед подстановкой значений вместо ссылок на переменные и вызовов функций; это означает, что вы можете включить ведущие пробелы в значение переменной посредством защиты их с помощью ссылок на переменные, как показано ниже:

      nullstring :=   
      space := $(nullstring) # конец строки   
Здесь значением переменной space является ровно один пробел. Комментарий '# конец строки' вставлен сюда только для ясности. Так как ведомые пробельные символы не удаляются из значений переменых, просто пробел в конце строки имел бы такой же эффект (но это было бы довольно сложно читать). Если вы добавляете пробел в конце значениея переменной, неплохо бы добавить в конце строки подобный комментарий, чтобы сделать ваш замысел ясным. Напротив, если вы не хотите никаких пробельных символов в конце значения вашей переменной, вы должны запомнить, что не следует добавлять случайный комментарий в конце строки после нескольких пробелов, как показано ниже:

      dir := /foo/bar    # directory to put the frobs in   
Здесь значением переменной dir является '/foo/bar ' (с четырьмя ведомыми пробелами), что, вероятно, не является замыслом. (Представьте что-либо типа '$(dir)/file' с таким определением !)

6.3 Дополнительные возможности для ссылки на переменные

Этот раздел описывает некоторые дополнительные возможности, которые вы можете использовать для обращения с переменными более гибкими способами.

Cсылки с заменой

На место ссылки на замену подставляется значение переменной с определяемыми вами изменения. Она имеет форму '$(var:a=b)' (или '${var:a=b}') и означает, что в значении переменной var, вхождение 'a' в конце каждого слова в этом значении заменяется на 'b', а получившаяся строка будет подставлена на место ссылки.

Когда мы говорим "в конце каждого слова", мы имеем ввиду, что либо за вхождением 'a' должен следовать пробел, либо оно должно находиться в конце значения для того, чтобы быть замененным; другие вхождения 'a' в значение остаются неизмененными. Например, фрагмент make-файла

      foo := a.o b.o c.o   
      bar := $(foo:.o=.c)   
устанавливает переменную 'bar' в 'a.c b.c c.c'. Смотрите раздел 6.5 [Установка переменных].

На самом деле, ссылка с заменой является сокращением использования преобразующей функции patsubst (смотрите раздел 8.2 [Функции подстановки и анализа строк]). Для совместимости с лругими реализациями программы make, данная версия поддерживает ссылку с заменой, также как и patsubst.

Еще один вид ссылки с заменой позволяет вам использовать всю мощь функции patsubst. Он имеет такую же форму '$(var:a=b)', описанную выше, за исключением того, что теперь 'a' должна содержать один, и только один, символ '%'. Этот случай эквивалентен вызову '$(patsubst A,B,$(VAR))'. Смотрите раздел 8.2 [Функции подстановки и анализа строк] для описания функции patsubst.

Например, фрагмент make-файла

      foo := a.o b.o c.o   
      bar := $(foo:%.o=%.c)   
устанавливает переменную 'bar' в 'a.c b.c c.c'.

Вычисляемые имена переменных

Вычисляемые имена переменных - это сложное понятие, необходимое только для утонченного программирования make-файла. В большинстве случаев вам нет необходимости изучать их, надо только знать, что создание переменной со знаком доллара в ее имени может привести к странным результатам. Однако, если вы человек того типа, который хочет все понять или вы на самом деле интересуетесь тем, что представляют собой такие переменные, читайте дальше.

На переменные можно ссылаться в имени переменной. Это называется вычисляемым именем переменной или вложенной ссылкой на переменную. Например, фрагмент make-файла

      x = y   
      y = z   
      a := $($(x))   
определяет 'z' в качестве значения переменной a: ссылка '$(x)' внутри '$($(x))' заменяется на 'y', поэтому '$($(x))' заменяется на ссылку '$(y)', которая, в свою очередь, заменяется на 'z'. Здесь имя ссылающейся переменной не указано явным образом - оно вычисляется путем замены '$(x)'. В данном случае ссылка '$(x)' вложена в более внешнюю ссылку на переменную.

Предыдущий пример показывает два уровня вложенности, но возможно любое количество уровней. Например, здесь три уровня вложенности:

      x = y   
      y = z   
      z = u   
      a := $($($(x)))   
В этом примере самая внутрення ссылка '$(x)' заменяется expands to 'y', поэтому '$($(x))' заменяется на ссылку '$(y)', которая, в свою очередь, заменяется на 'z'; теперь мы имеет ссылку '$(z)', которая превращается в 'u'.

Ссылки на рекурсивно вычисляемые переменные внутри имени переменной перевычисляются обычным образом. Например, данный фрагмент make-файла:

      x = $(y)   
      y = z   
      z = Hello   
      a := $($(x))   
определяет 'Hello' в качестве значения переменной a: ссылка '$($(x))' превращается в ссылку '$($(y))', которая превращается в ссылку '$(z)', которая превращается в 'Hello'.

Вложенные ссылки на переменные могут также содержать модифицированные ссылки и вызовы функций (смотрите главу 8 [Функции преобразования текста]), так же, как и любые другие ссылки. Например, использование функции subst (смотрите раздел 8.2 [Функции подстановки и анализа строк]), как в данном примере:

      x = variable1   
      variable2 := Hello   
      y = $(subst 1,2,$(x))   
      z = y   
      a := $($($(z)))   
определяет 'Hello' в качестве значения переменной a. Сомнительно, что кто-нибудь когда-либо захочет написать вложенную ссылку, запутанную так же, как и эта, но она работает: ссылка '$($($(z)))' заменяется на ссылку '$($(y))', которая превращается в '$($(subst1,2,$(x)))'. Здесь из переменной x берется значение 'variable1', которое заменяется путем подстановки на 'variable2', таким образом строка целиком принимает вид '$(variable2)', что является простой ссылкой на переменную , значением которой является 'Hello'.

Вычисляемому имени переменной не обязательно состоять целиком из одной ссылки на переменную. Оно может содержать несколько ссылок на переменные, а также какой-нибудь неизменяемый текст. Например, в данном фрагменте make-файла:

      a_dirs := dira dirb   
      1_dirs := dir1 dir2   
    
      a_files := filea fileb   
      1_files := file1 file2   
    
      ifeq "$(use_a)" "yes"   
      a1 := a   
      else   
      a1 := 1   
      endif   
    
      ifeq "$(use_dirs)" "yes"   
      df := dirs   
      else   
      df := files   
      endif   
    
      dirs := $($(a1)_$(df))   
переменной dirs будет дано, такое же значение, как переменной 'a_dirs', '1_dirs', 'a_files' или '1_files', в зависимости от установленных значений переменных 'use_a' и 'use_dirs'.

Вычисляемые имена переменных также могут быть использованы в ссылках с заменой. Например, в данном фрагменте make-файла

      a_objects := a.o b.o c.o   
      1_objects := 1.o 2.o 3.o   
    
      sources := $($(a1)_objects:.o=.c)   
в качестве значения переменной sources определяется либо 'a.c b.c c.c', либо '1.c 2.c 3.c', в зависимости от значения переменной a1.

Единственное ограничение на такого рода использование вложенных ссылок на переменные состоит в том, что они не могут определять часть имени вызываемой функции. Это из-за того, что проверка на корректность имени функции производится до вычисления вложенных ссылок. Например, в данном фрагменте make-файла:

      ifdef do_sort   
      func := sort   
      else   
      func := strip   
      endif   
    
      bar := a d b g q c   
   
      foo := $($(func) $(bar))   
принимается попытка присвоить переменной 'foo' либо значение 'sort a d b g q c', либо значение 'strip a d b g q c', а не передавать 'a d b g q c' в качестве аргумента либо функции sort, либо функции strip. Это ограничение в будущем может быть снято, если такое изменение покажется хорошей идеей.

Вы также можете использовать вычисляемые имена переменных в левой части присваивания значения переменной или в директиве define, как показано ниже:

      dir = foo   
      $(dir)_sources := $(wildcard $(dir)/*.c)   
      define $(dir)_print   
      lpr $($(dir)_sources)   
      endef   
В этом примере определяются переменные 'dir', 'foo_sources' и 'foo_print'.

Обратите внимание, что вложенные ссылки на переменные полностью отличаются от рекурсивно вычисляемых переменных (смотрите раздел 6.2 [Две разновидности переменных]), хотя и те, и другие сложными способами используются вместе при программировании make-файла.

6.4 Как переменные получают свои значения

Переменные могут получать значения несколькими различными способами:

6.5 Установка переменных

Чтобы установить переменную из make-файла, напишите строку, начинающуюся с имени переменной, за которым следует '=' или ':='. Все, что в данной строке следует за '=' или ':=', становится значением. Например, в данной строке:

      objects = main.o foo.o bar.o utils.o   
определяется переменная с именем objects. Пробелы вокруг имени переменной и непосредственно после символа '=' игнорируются.

Переменные, определенные при помощи символа '=', являются рекурсивно вычисляемыми переменными. Переменные, определенные с помощью ':=', являются упрощенно вычисляемыми переменными - эти определения могут содержать ссылки на переменные, которые будут вычислены, прежде чем будет сделано определение. Смотрите раздел 6.2 [Две разновидности переменных].

Имя переменной может содержать ссылки на функции и переменные, которые вычисляются для определения того, какое имя на самом деле надо использовать, в тот момент, когда считывается строка make-файла.

На длину значения переменной нет ограничений, за исключением количества пространства для подкачки на компьютере. Когда определение переменной длинное, неплохо бы разбить ее на несколько строк, вставляя в определении символ '\' с последующим переводом строки там, где это удобно. Это не повлияет на работу программы make, но сделает make-файл более легким для чтения.

Для большинства имен переменных считается, что соответствующая переменная имеет в качестве значения пустую строку, если вы нигде ее не устанавливали. Несколько переменных имеют встроенные первоначальные значения, которые не являются пустыми, но вы можете установить их обычными способами (смотрите раздел 10.3 [Переменные, используемые неявными правилами]). Некоторые специальные переменные в каждом правиле автоматически устанавливаются в новое значение - они называются автоматическими переменными (смотрите раздел 10.5.3 [Автоматические переменные]).

6.6 Добавление дополнительного фрагмента к пеpеменным

Часто полезно добавлять дополнительный фрагмент к значению уже определенной переменной. Это делается при помощи строки, содержащей '+=', как показано ниже:

      objects += another.o   
В этом примере берется значение переменной objects, и к нему добавляется фрагмент 'another.o' (с предшествующим пробелом). Таким образом, данный фрагмент make-файла

      objects = main.o foo.o bar.o utils.o   
      objects += another.o   
устанавливает 'main.o foo.o bar.o utils.o another.o' в качестве значения переменной objects.

Использование '+=' аналогично следующему:

      objects = main.o foo.o bar.o utils.o   
      objects := $(objects) another.o   
но отличается теми деталями, которые становятся важными при использовании более сложных значений.

Когда расматриваемая переменная ранее не была определена, '+=' действует так же, как обычный символ '=': определяется рекурсивно вычисляемую переменную. Однако, если есть предыдущее определение, тогда то, что именно делает '+=' зависит от того, какая разновидность переменной определена первоначально. Смотрите раздел 6.2 [Две разновидности переменных] для объяснения двух разновидностей переменных.

Когда вы что-либо добавляете к значению переменной при помощи '+=', программа make, по существу, действует так, как будто вы включили дополнительный текст в первоначальное определение переменной. Если вы изначально определили переменную при помощи ':=', сделав ее упрощенно вычисляемой переменной, '+=' производит добавление к этому упрощенно-вычисленному определению, и вычисляет новый фрагмент перед добавлением его к старому значению, так же, как это делается при использовании ':=' (смотрите раздел 6.5 [Установка переменных] для полного объяснения ':='). Фактически, следуюзий фрагмент make-файла:

      variable := value   
      variable += more   
в точности эквивалентен такому фрагменту:

      variable := value   
      variable := $(variable) more   
С другой стороны, когда вы используете '+=' с переменной, которую вы при помощи одиночного символа '=' изначально определили как рекурсивно-вычисляемую, программа make некоторые вещи делает немного иначе. Вспомните, что когда вы определяете рекурсивно-вычисляемую переменную, программа make не вычисляет сразу значение установленных вами ссылок на переменные и функции. Вместо этого, она она запоминает фиксированные фрагменты и хранит эти ссылки на переменные и функции с тем, чтобы вычислить их позже, когда вы обратитесь к новой пременной (смотрите раздел 6.2 [Две разновидности переменных]). Когда вы используете '+=' с рекурсивно-вычисляемой переменной, имеется невычисленный фрагмент, к которому make добавляет определенный вами новый фрагмент.

      variable = value   
      variable += more   
Приведенные выше строки make-файла, грубо говоря, эквивалентны следующим строкам:

      temp = value   
      variable = $(temp) more   
за исключением того, что, конечно, никогда не определяется переменная с именем temp. Важность использования '+=' проявляется в той ситуации, когда старое значение переменной содержит ссылки на переменные. Рассморим такой типичный пример:

      CFLAGS = $(includes) -O   
      ...   
      CFLAGS += -pg # enable profiling   
Первая строка определяет переменную CFLAGS со ссылкой на другую переменную, includes. (CFLAGS используется правилами для C-компиляции, смотрите раздел 10.2 [Перечень неявных правил].) Использование для определения '=' делает CFLAGS рекурсивно-вычисляемой переменной, а это означает, что '$(includes) -O' не вычисляется в тот момент, когда программа make обрабатывает значение определение переменной CFLAGS. Таким образом, чтобы получить эффект от использования переменной includes, не обязательно наличие у нее определенного значения на момент определения CFLAGS. Достаточно того, чтобы переменная includes была определена перед любой ссылкой на CFLAGS. Если бы мы попробовали добавить значение к CFLAGS без использования '+=', мы могли бы сделать это примерно так:

      CFLAGS := $(CFLAGS) -pg # enable profiling   
Это близко к истине, но не совсем то, чего мы хотим. При использовании ':=' CFLAGS переопределяется как упрощенно-вычисляемая переменная - это означает, что программа make вычисляет фрагмент '$(CFLAGS) -pg' перед установкой значения переменной. Если переменная includes еще неопределена, мы получим ' -O -pg', и более позднее определение переменной includes не окажет никакого воздействия. Напротив, при использовании '+=' мы устанавливаем переменную CFLAFGS в невычесленное значение '$(includes) -O -pg'. Таким образом, мы сохраняем ссылку на переменную includes, поэтому если эта переменная оказывается определенной где-нибудь дальше, ссылка вида '$(CFLAGS)' все-таки будет использовать ее значение.

6.7 Директива override

Если переменная была установлена при помощи аргумента командной строки (смотрите раздел 9.5 [Перекрывающиеся переменные]), то обычные присваивания в make-файле игнорируются. Если вы хотите вы хотите установить переменную в make-файле, даже если она установлена при помощи аргумента командной строки, вы можете использовать директиву override, которая представляет собой строку make-файла, выглядящую следующим образом:

      override VARIABLE = VALUE   
или так:

      override VARIABLE := VALUE   
Для добавления дополнительного фрагмента к переменной, определенной в командной строке, используйте такую строку make-файла:

      override VARIABLE += MORE TEXT   
Смотрите раздел 6.6 [Добавление дополнительного фрагмента к пеpеменным].

Директива override была введена не для усиления войны между make-файлами и аргументами командной строки. Она была введена для того, чтобы вы могли изменять и дополнять значения, которые пользователь определяет при помощи аргументов командной строки.

Например, предположим, что вы всегда хотите, чтобы при запуске C-компилятора использовалась опция '-g', но вы хотели бы позволить позволить пользователю определять другие опции, как обычно, в аргументе командной строки.

      override CFLAGS += -g   

Вы можете также использовать директивы override с директивами define. Это делается так же, как вы и могли ожидать:

      override define foo   
      bar   
      endef   
Смотрите следующий раздел для информации о директиве define.

6.8 Определение многостроковых переменных

Еще один способ устанвки значения переменной - использовать директиву define. Эта директива имеет необычный синтаксис, который позволяет включать в значение символы перевода строки, что удобно для определения именованных последовательностей команд (смотрите раздел 5.7 [Определение именованных командных последовательностей]).

За директивой define на той же строке следует имя переменной и ничего больше. Значение, в которое устанавливается переменная, появляется на последующих строках. Конец значения обозначается строкой, содержащей только одно слово endef. За исключением этого отличия в синтаксисе, директива define работает точно так же, как и '=': она создает рекурсивно вычисляемую переменную (смотрите раздел 6.2 [Две разновидности переменных]). Имя переменной может содержать ссылки на функции и переменные, которые вычисляются в момент чтения директивы для определения того, какое реальное имя переменной следует использовать.

      define two-lines   
      echo foo   
      echo $(bar)   
      endef   
При обычном присваивании значение не может содержать символов перевода строки, в то же время символы перевода строки, которые разделяют строки в значении, определяемом директивой define, становятся частью значения переменной (за исключением последнего перевода строки, который предшествует директиве endef и не рассматривается как часть значения).

Предыдущий пример функционально эквивалентен приведенному ниже:

      two-lines = echo foo; echo $(bar)   
так как две команды, разделенные точкой с запятой, ведут себя во многом так же, как две отдельные команды командной оболочки. Однако, обратите внимание, что использование двух отдельных строк означает, что программа make будет вызывать командную оболочку дважды, запуская независимые подоболочки для каждой строки. Смотрите раздел 5.2 [Выполнение команд].

Если вы хотите, чтобы определения переменных, сделанные при помощи define, имели преимущество перед определениями переменных из командной строки, вы можете вместе с директивой define использовать директиву override, как показано ниже:

      override define two-lines   
      foo   
      $(bar)   
      endef   
Смотрите раздел 6.7 [Директива override].

6.9 Переменные из командной среды

Переменные могут приходить в программу make из командной среды, в которой make запускается. Каждая переменная командной среды, которая доступна программе make при старте, преобразуется в переменную программы make с таким же именем и значением. Но явное присваивание в make-файле или при помощи арргумента командной строки перекрывает значение из командной среды. (Если определена опция '-e', значение из командной среды перекрывает присваивания в make-файле. Смотрите раздел 9.7 [Обзор опций]. Но такая практика не рекомендуется.)

Таким образом, установив переменную CFLAGS в вашей командной среде, вы можете сделать так, чтобы во всех сеансах компиляции C-программ в большинстве make-файлов использовались выбранные вами опции компилятора. Это безопасно для переменных со стандартными или обговоренными предназначениями, поскольку вы знаете, что ни один make-файл не будет использовать их ни для чего другого. (Но это не является абсолютно надежным - некоторые make-файлы явным образом устанавливают переменную CFLAGS и, следовательно, на них не действует значение из командной среды).

Когда программа make вызывается рекурсивно, переменные, определенные в более внешних порожденных процессах make, могут быть переданы более внутренним порожденных процессах make через командную среду ( смотрите раздел 5.6 [Рекурсивное использование make]). По умолчанию, при рекурсивных вызовах передаются только переменные, которые пришли из командной среды или определены в командной строке. Для того, чтобы передать другие переменные, вы можете использовать директиву export. Смотрите раздел 5.6.2 [Связь порожденным процессом make через переменные], для выяснения всех деталей.

Другое использование переменной из командной строки не рекомендуется. make-файлы, функционирование которых зависит от установок неконтролируемых ими переменных командной среды, не являются дальновидно написанными, поскольку это может привести к тому, что разные пользователи получат разные результаты от одного и того же make-файла. Это противоречит самому предназначению большинства make-файлов.

Такие проблемы были бы особенно вероятны в связи с переменной SHELL, которая обычно присутствует в командной среде для определения выбранной пользователем диалоговой командной оболочки. Было бы очень нежелательно, чтобы этот выбор воздействовал на программу make. Поэтому программа make игнорирует значение переменной SHELL из командной среды.


Вперед Назад Содержание


Спонсоры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2022 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру