make вычислить значение в правиле

Не получается вычислить значение в правиле и записать его в переменную.

Есть вот такое правило:

elastic-load-balancer:
    $(info "running elastic load balancer of yandex cloud")
    COMMAND_VAR=...
    cd elb && terraform plan
    cd elb && terraform apply -auto-approve -var="yandex_compute_instance_group_id=${COMMAND_VAR}"

Вместо многоточия мне требуется подставить cd instance_group && echo $(terraform output terraform_group_instance_id) и записать в переменную результат выполнения команды terraform output terraform_group_instance_id.

Затем эту переменную нужно подставить ниже, в коде. Как это сделать?


UPD

$(info "running elastic load balancer of yandex cloud" ${cd instance_group/ && terraform output terraform_group_instance_id})

Ответ не подставляет. Если выполнить команду, то получу строку


Ответы (3 шт):

Автор решения: Ainar-G

В большинстве имплементаций make, включая GNU Make, каждая команда выполняется в отдельном процессе, так что очевидно, что переменные так работать не будут. Про вынос в скрипт я уже написал вам в комментарии. Вот вариант с макросами для POSIX Make:

COMMAND_VAR = $$(echo foo)

elastic-load-balancer:
    @ echo "running elastic load balancer of yandex cloud"
    cd elb && terraform plan
    cd elb && terraform apply -auto-approve\
        -var="yandex_compute_instance_group_id=$(COMMAND_VAR)"
→ Ссылка
Автор решения: Arenoros

Дополню предыдущий ответ, для ограничения области видимости можно так же писать

elastic-load-balancer: COMMAND_VAR = $$(echo foo)
    echo ${COMMAND_VAR}
    ...

Так же объявление можно вынести

elastic-load-balancer: COMMAND_VAR = $$(echo foo)
elastic-load-balancer:
    echo ${COMMAND_VAR}
    ...

и так тоже будет корректно

elastic-load-balancer:
    echo ${COMMAND_VAR}
    ...
...
elastic-load-balancer: COMMAND_VAR = $$(echo foo)

→ Ссылка
Автор решения: aleksandr barakin

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

цели : пререквизиты
    рецепт
    ...

итак. можно пойти разными путями:

  1. например, объединить присвоение переменной и те команды, в которых она нужна, в «непрерывную» строку (если строка заканчивается символом \, то следующая за ней считается её непосредственным продолжением). т.е., заменить в рецепте:

        COMMAND_VAR=...
        cd elb && terraform plan
        cd elb && terraform apply -auto-approve -var="yandex_compute_instance_group_id=${COMMAND_VAR}"
    

    на что-нибудь вроде:

        COMMAND_VAR=... && \
        cd elb && terraform plan && \
        terraform apply -auto-approve -var="yandex_compute_instance_group_id=${COMMAND_VAR}"
    

    обратите внимание: я убрал один вызов cd. он получается лишним.

  2. добавить в файл специальную цель .ONESHELL. в результате оболочка будет вызываться однократно на один рецепт, а не на каждую строку в каждом рецепте. учтите, что, например, количество тех же cd надо будет сократить.
  3. но лучше, вероятно, будет изменить весь подход. так, чтобы он соответствовал основной парадигме программы make: отслеживанию зависимостей между файлами и выполнению рецепта (т.е., «обновлению» цели, она же — файл) только в том случае, если у цели обновился хотя бы один пререквизит (и пререквизиты — тоже файлы).

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

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

    и т.д. и т.п.


всё-таки дополню: да, конечно, часто используются цели, файлам не соотвтетствующие (т.н. «phony targets»). главная их «проблема» в том, что они «рвут» основную парадигму программы make: обычная цель может не требовать обновления (если пререквизиты старше цели), а вот «phony»-цель требует обновления (выполнения рецепта) всегда. и того же она требует ещё и от тех целей, у которых записана в пререквизиты.

→ Ссылка