Автоматические переменные
Предположим, вы пишете правило шаблона для компиляции файла ‘.c’ в файл ‘.o’: как записать команду ‘cc’, чтобы она работала с правильным именем исходного файла? Вы не можете записать имя в рецепте, потому что имя различно каждый раз, когда применяется неявное правило.
Что вы делаете, так это используете специальную возможность make, автоматические переменные. Эти переменные получают значения, вычисляемые заново для каждого выполняемого правила, на основе целевого файла и предварительных условий правила. В этом примере вы бы использовали ‘$@’ для имени файла объекта и ‘$<’ для имени исходного файла.
Очень важно понимать ограниченную область действия значений автоматических переменных: они имеют значения только внутри рецепта. В частности, вы не можете использовать их где-либо в списке целей правила; там они не имеют значения и будут расширяться до пустой строки. Также к ним нельзя получить прямой доступ в списке предварительных условий правила. Распространённой ошибкой является попытка использовать $@ в списке предварительных условий; это не сработает. Однако существует специальная функция GNU make, вторичное расширение (см. Вторичное расширение), которая позволит использовать значения автоматических переменных в списках предварительных условий.
Вот таблица автоматических переменных:
$@-
Имя файла цели правила. Если цель является членом архива, то ‘$@’ — это имя файла архива. В правиле шаблона, имеющем несколько целей (см. Введение в правила шаблонов), ‘$@’ — это имя той цели, которая заставила выполнить рецепт правила.
$%-
Имя члена цели, когда цель является членом архива. См. Архивы. Например, если цель — foo.a(bar.o), то ‘$%’ — bar.o, а ‘$@’ — foo.a. ‘$%’ пусто, когда цель не является членом архива.
$<-
Имя первого предварительного условия. Если цель получила свой рецепт из неявного правила, это будет первое предварительное условие, добавленное неявным правилом (см. Неявные правила).
$?-
Имена всех предварительных условий, которые новее цели, с пробелами между ними. Если цель не существует, будут включены все предварительные условия. Для предварительных условий, являющихся членами архива, используется только указанное имя члена (см. Архивы).
‘$?’ полезно даже в явных правилах, когда вы хотите обработать только те предварительные условия, которые изменились. Например, предположим, что архив под названием lib должен содержать копии нескольких файлов объектов. Это правило копирует только изменённые файлы объектов в архив:
lib: foo.o bar.o lose.o win.o ar r lib $? $^-
Имена всех предварительных условий, с пробелами между ними. Для предварительных условий, являющихся членами архива, используется только указанное имя члена (см. Архивы). Цель имеет только одно предварительное условие для каждого другого файла, от которого она зависит, независимо от того, сколько раз каждый файл указан как предварительное условие. Так что, если вы указываете предварительное условие более одного раза для цели, значение
$^содержит только одну копию имени. Этот список не содержит никаких предварительных условий только для порядка; для них см. переменную ‘$|’ ниже. $+-
Это похоже на ‘$^’, но предварительные условия, указанные более одного раза, дублируются в порядке их перечисления в файле make.
$|-
Имена всех предварительных условий только для порядка, с пробелами между ними.
$*-
Основа, с которой совпадает неявное правило (см. Как совпадают шаблоны). Если цель — dir/a.foo.b, а шаблон цели — a.%.b, то основой является dir/foo. Основа полезна для построения имён связанных файлов.
В статическом правиле шаблона основа является частью имени файла, которое соответствовало ‘%’ в шаблоне цели.
В явном правиле основы нет; поэтому ‘$*’ нельзя определить таким образом. Вместо этого, если имя цели заканчивается на распознаваемый суффикс (см. Правила старой школы для суффиксов), ‘$*’ устанавливается в имя цели минус суффикс. Например, если имя цели — ‘foo.c’, то ‘$*’ устанавливается в ‘foo’, так как ‘.c’ — это суффикс. GNU
makeделает эту странную вещь только для совместимости с другими реализациямиmake. Как правило, следует избегать использования ‘$*’, за исключением неявных правил или статических правил шаблонов.Если имя цели в явном правиле не заканчивается на распознаваемый суффикс, ‘$*’ устанавливается в пустую строку для этого правила.
Из перечисленных выше переменных четыре имеют значения, представляющие собой имена отдельных файлов, и три имеют значения, представляющие собой списки имён файлов. Эти семь имеют варианты, которые получают только имя каталога файла или только имя файла в каталоге. Имена переменных-вариантов образуются путём добавления ‘D’ или ‘F’ соответственно. Функции dir и notdir могут быть использованы для достижения подобного эффекта (см. Функции для имён файлов). Обратите внимание, однако, что все варианты ‘D’ опускают заключительный слэш, который всегда появляется в выводе функции dir. Вот таблица вариантов:
- ‘$(@D)’
-
Часть имени файла цели, представляющая каталог, с удалением заключительного слэша. Если значение ‘$@’ — dir/foo.o, то ‘$(@D)’ — dir. Это значение — ., если ‘$@’ не содержит слэша.
- ‘$(@F)’
-
Часть имени файла цели, представляющая файл в каталоге. Если значение ‘$@’ — dir/foo.o, то ‘$(@F)’ — foo.o. ‘$(@F)’ эквивалентно ‘$(notdir $@)’.
- ‘$(*D)’
- ‘$(*F)’
-
Часть каталога и часть имени файла в каталоге основы; dir и foo в этом примере.
- ‘$(%D)’
- ‘$(%F)’
-
Часть каталога и часть имени файла в каталоге имени члена целевого архива. Это имеет смысл только для целевых членов архива в формате archive(member) и полезно только когда member может содержать имя каталога. (См. Члены архива в качестве целей.)
- ‘$(<D)’
- ‘$(<F)’
-
Часть каталога и часть имени файла в каталоге первого предварительного условия.
- ‘$(^D)’
- ‘$(^F)’
-
Списки частей каталога и частей имён файлов в каталоге всех предварительных условий.
- ‘$(+D)’
- ‘$(+F)’
-
Списки частей каталога и частей имён файлов в каталоге всех предварительных условий, включая несколько экземпляров дублированных предварительных условий.
- ‘$(?D)’
- ‘$(?F)’
Списки частей каталога и частей имён файлов в каталоге всех предварительных условий, которые новее цели.
Обратите внимание, что мы используем специальную стилистическую конвенцию, когда говорим об этих автоматических переменных; мы пишем «значение ‘$<’», а не «переменная <», как мы писали бы для обычных переменных, таких как objects и CFLAGS. Мы считаем, что эта конвенция выглядит более естественной в этом особом случае. Пожалуйста, не предполагайте, что она имеет глубокий смысл; ‘$<’ относится к переменной под названием < так же, как ‘$(CFLAGS)’ относится к переменной под названием CFLAGS . Вы можете так же использовать ‘$(<)’ вместо ‘$<’.
Copyright © 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Free Software Foundation, Inc.
Licensed under the GNU Free Documentation License.
https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html