Вычисленные имена переменных
Вычисленные имена переменных — это продвинутая концепция, очень полезная в более сложных программах makefile. В простых ситуациях их можно не учитывать, но они могут быть чрезвычайно полезными.
Переменные могут быть упомянуты внутри имени переменной. Это называется вычисляемым именем переменной или вложенной ссылкой на переменную. Например,
x = y y = z a := $($(x))
определяет a как ‘z’: ‘$(x)’ внутри ‘$($(x))’ расширяется до ‘y’, поэтому ‘$($(x))’ расширяется до ‘$(y)’, которое, в свою очередь, расширяется до ‘z’. Здесь имя переменной для ссылки не указано явно; оно вычисляется путем расширения ‘$(x)’. Ссылка ‘$(x)’ здесь вложена во внешнюю ссылку на переменную.
Предыдущий пример показывает две уровня вложенности, но возможно любое количество уровней. Например, вот три уровня:
x = y y = z z = u a := $($($(x)))
Здесь внутреннее ‘$(x)’ расширяется до ‘y’, поэтому ‘$($(x))’ расширяется до ‘$(y)’, которое, в свою очередь, расширяется до ‘z’; теперь у нас есть ‘$(z)’, которое становится ‘u’.
Ссылки на рекурсивно расширенные переменные внутри имени переменной повторно расширяются обычным способом. Например:
x = $(y) y = z z = Hello a := $($(x))
определяет a как ‘Hello’: ‘$($(x))’ становится ‘$($(y))’, которая становится ‘$(z)’, которая становится ‘Hello’.
Вложенные ссылки на переменные также могут содержать изменённые ссылки и вызовы функций (см. Функции для преобразования текста), как и любая другая ссылка. Например, используя функцию subst (см. Функции для подстановки и анализа строк):
x = variable1 variable2 := Hello y = $(subst 1,2,$(x)) z = y a := $($($(z)))
в конечном итоге определяет a как ‘Hello’. Сомневаюсь, что кто-то когда-либо захочет написать такую сложную вложенную ссылку, но она работает: ‘$($($(z)))’ расширяется до ‘$($(y))’, которая становится ‘$($(subst 1,2,$(x)))’. Это получает значение ‘variable1’ из x и изменяет его заменой на ‘variable2’, так что вся строка становится ‘$(variable2)’, простой ссылкой на переменную, значение которой ‘Hello’.
Вычисляемое имя переменной необязательно должно состоять только из одной ссылки на переменную. Оно может содержать несколько ссылок на переменные, а также некоторую неизменяемую текстовую часть. Например,
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.
Вычисляемые имена переменных также могут использоваться в ссылках на подстановку:
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.
Единственное ограничение на использование вложенных ссылок на переменные заключается в том, что они не могут указывать часть имени вызываемой функции. Это связано с тем, что проверка распознавания имени функции выполняется до расширения вложенных ссылок. Например,
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’.
Обратите внимание, что вложенные ссылки на переменные сильно отличаются от рекурсивно расширенных переменных (см. Два типа переменных), хотя оба используются вместе сложными способами при программировании makefile.
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/Computed-Names.html