Определение шаблона в Makefile с использованием динамических переменных c из цикла - PullRequest
0 голосов
/ 13 января 2020

Можете ли вы как-то заменить переменные, определенные с помощью Makefile define внутри циклов?

VERSION ?= v1.0.0
CPUARCHS := amd64 arm arm64
DESCRIPTION := This is epic application doing epic things

# Manifest format for X
export define TEMPLATE_FORMAT1
Version: $(VERSION)
Arch: $$$$arch

$(DESCRIPTION)
endef

# Some other manifest format for Y
export define TEMPLATE_FORMAT2
pkgver=$(VERSION)
cpuarch=$$$$arch
descr=$(DESCRIPTION)
endef


format1:
        @for arch in $(CPUARCHS); do \
          echo "$$TEMPLATE_FORMAT1"; \
        done

format2:
        @for arch in $(CPUARCHS); do \
          echo "$$TEMPLATE_FORMAT2"; \
        done

genformats: format1 format2
        @echo Done.

Это приводит к:

% make format1   
Version: v1.0.0
Arch: $$arch

This is epic application doing epic things
Version: v1.0.0
Arch: $$arch

This is epic application doing epic things
Version: v1.0.0
Arch: $$arch

This is epic application doing epic things

Можете ли вы заменить $$arch на используемую в л oop? Конечно, в реальной ситуации будет намного больше переменных, чем просто $$arch, поэтому есть решение "без проблем" (ie. Нет bazillion sed или другие команды для каждой отдельной цели формата шаблона)

1 Ответ

1 голос
/ 13 января 2020

Итак, во-первых, в bash, когда вы делаете a=$b b=c echo $a, он выдаст $b, а не c - он не расширяет переменную внутри переменной.

В вашем случае вы делают echo "$$TEMPLATE_FORMAT1", который будет преобразован в echo "$TEMPLATE_FORMAT1" командой make, а затем передан в bash, после чего $TEMPLATE_FORMAT1 будет содержать $$arch, который не будет расширен.

Если Ваш make-файл попытался выполнить echo $$arch, однако он расширится до echo $arch, а bash увеличит значение $arch в этой точке. Таким образом, вы можете попытаться использовать $$arch в $(TEMPLATE_FORMAT1) напрямую.

Хитрость в том, что в вашем определении есть новые строки, и если вы попытаетесь развернуть echo $(TEMPLATE_FORMAT1), это приведет к чему-то вроде echo line1 (новая строка) line2 (новая строка) line3, (так эхо относится только к первому). Чтобы обойти это, вы можете заменить символы новой строки на \n, а эхо с -e:

VERSION ?= v1.0.0
CPUARCHS := amd64 arm arm64
DESCRIPTION := This is epic application doing epic things

# Manifest format for X
export define TEMPLATE_FORMAT1
Version: $(VERSION)
Arch: $$arch
$(DESCRIPTION)
endef

define newline


endef


format1:
        @echo $@
        @for arch in $(CPUARCHS); do \
          echo -e "$(subst $(newline),\n,$(TEMPLATE_FORMAT1))"; \
        done

genformats: format1 format2
        @echo Done.

выходными

Version: v1.0.0
Arch: amd64
This is epic application doing epic things
Version: v1.0.0
Arch: arm
This is epic application doing epic things
Version: v1.0.0
Arch: arm64
This is epic application doing epic things
...