2017-02-17 4 views
1

Я озадачен разницей между функцией «shell» MAKE и «$$». В документации я считаю:

Функция оболочки принимает один аргумент, который расширяется (как и все аргументы) и передается субоболочке для исполнения. Стандартный вывод команды затем считывается и возвращается как значение функции.

Я полагал, что это был именно , что "$$" делает так, однако в этом небольшом примере:

a = $(shell find . -maxdepth 1 -type f -name "Makefile") 
b = $$(find . -maxdepth 1 -type f -name "Makefile") 

.PHONY: all A B 

all: A B 

A: $(a) 
    @echo "Target: $(@)" 
    @echo "Prereq: $(<)" 
    @echo "Var a: $(a)" 
    @echo "Var b: $(b)" 

B: $(b) 
    @echo "Target: $(@)" 
    @echo "Prereq: $(<)" 
    @echo "Var a: $(a)" 
    @echo "Var b: $(b)" 

Выходом является следующее:

Target: A 
Prereq: Makefile 
Var a: ./Makefile 
Var b: ./Makefile 
make: *** No rule to make target '$(find)', needed by 'B'. Stop. 

Примечание здесь говорится: «Нет правила делать цель '$ (найти)'", как будто аргумент еще не был расширен. (Я также попытался сделать переменную просто расширенной, «b:=$$(...)», но это ничего не изменило).

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

ответ

2

$(shell ...) a текстовая функция. Make будет расширять это, поэтому в вашем примере a будет разворачиваться при замене на результат команды find. (Если вы сделали его просто расширенной переменной, команда оболочки будет оцениваться только один раз, конечно).

$$ просто расширена до $, так что в вашем примере, b заменит в качестве значения $(find . -maxdepth 1 -type f -name "Makefile"). Это будет одинаково, если b определяется с помощью = или :=.

При использовании $(b) в команде , такие как echo $(b), бег оболочки, что команда будет видеть это как подстановки команд. Другими словами, вы используете команду echo $(find ...) как команду оболочки.

Использование $(b) in a Сделать цель или зависимость, как вы видели, выполнить дальнейшую оценку.

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

a = $$(echo true) 
b = $(shell echo true) 

print: 
    echo '$$a: $a' = "$a" 
    echo '$$b: $b' = "$b" 

.PHONY: print 

Это дает мне

echo '$a: $(echo true)' = "$(echo true)" 
$a: $(echo true) = true 
echo '$b: true' = "true" 
$b: true = true 

показывает, что в первом случае оболочка дается $(echo true) в его команде, в то время как в второй случай, делает оценку echo true и просто подставляет результат true в команду.

+0

Благодарим вас за подробный ответ, пример отличный.Должен признаться, что для того, чтобы заставить переменные переменные всегда были для меня несколько волшебными. –

Смежные вопросы