gnu makefile: порядок выполнения функции оболочки в рецепте - PullRequest
1 голос
/ 16 октября 2019

Я использую функцию $ (shell ...) gnu make в рецепте Makefile, и она запускается первой перед предыдущими строками. Почему?

Очень простой пример:

.PHONY: all
all:
    @echo 1
    @echo $(eval a=$(shell echo 2a 1>&2))2b
    @echo 3 $(a)

Вывод:

2a
1
2b
3

Сначала запускается строка $ (shell ...) (2a),тогда другие строки. Как мне запустить функцию $ (shell ...), когда ее строка выполняется в рецепте, в следующем порядке?

1
2a
2b
3

Редактировать:

Без $ (shell .. .) он работает, как я ожидал:

.PHONY: all
all:
    @echo 1
    $(eval a=a)
    @echo 2 $(a)
    $(eval a=b)
    @echo 3 $(a)

Вывод:

1
2 a
3 b

Редактировать 2:

Вот часть оригинального Makefile. Фрагменты в >>> показывают суть моей проблемы: я хочу поместить вывод udisksctl в переменную make вместо файла $ @. Loop (и сделать то же самое с $ @. Mount).

$(HDIMG): $(BOOTBLOCK_MBR_BIN) $(BOOTBLOCK_EXT2_BIN) $(LOADER_BIN) | $(DESTDIR)
        dd if=/dev/zero of=$@.ext2 bs=1 seek=$(PSIZEB) count=0 2>/dev/null
        $(MKFSEXT2) -F $@.ext2 >/dev/null
        dd if=$(word 2,$^) of=$@.ext2 conv=notrunc 2>/dev/null
        cp $< $@
        dd if=/dev/zero of=$@ bs=1 seek=$(HDSIZEB) count=0 2>/dev/null
        echo $(PFDISK) | $(TR) | $(FDISK) $@ >/dev/null
        dd if=$@.ext2 of=$@ bs=512 seek=$(PSTART) conv=sparse,notrunc iflag=fullblock 2>/dev/null
>>>     udisksctl loop-setup --file $@ --offset $(PSTARTB) --size $(PSIZEB) >$@.loop
        sed -i -e 's/.* //;s/\.//' $@.loop
        cat $@.loop
>>>     udisksctl mount --block-device $$(cat $@.loop) >$@.mount
        sed -i -e 's/.* //;s/\.//' $@.mount
        cat $@.mount
        #
        mkdir -p $$(cat $@.mount)/boot/
        cp $(word 2,$^) $$(cat $@.mount)/boot/
        #/sbin/filefrag -b512 -e /
        #
        udisksctl unmount --block-device $$(cat $@.loop)
        udisksctl loop-delete --block-device $$(cat $@.loop)
        rm $@.loop

1 Ответ

0 голосов
/ 16 октября 2019

Когда make запускает рецепт, он сначала раскрывает все переменные / функции в нем, а затем запускает команды оболочки построчно.

Выможно обойти это, выполнив каждую команду оболочки с $(shell ...), или, в вашем случае, используя $(info ...) вместо echo:

.PHONY: all
all:
    $(info 1)
    $(info $(eval a=$(shell echo 2a 1>&2))2b)
    $(info 3 $(a))

Вывод:

1
2a
2b
3
make: Nothing to be done for 'all'.

Часть Nothing to be done for 'all'. вызвана тем, что после расширения функций рецепт фактически пуст (имеет 0 команд оболочки). Добавление к нему команды no-op (например, @true) удаляет сообщение.

...