2014-04-10 3 views
3

У меня есть правило Makefile, которое требует хранения результатов из команд оболочки в переменные для последующего использования. По какой-то причине кажется, что вызов $(shell) выполняется, как только мое правило соответствует, в отличие от того, когда оно встречается во время выполнения.Назначение переменной Makefile выполняется раньше

Файл выглядит следующим образом:

TMPDEV=/tmp/disk.img 

$(TMPDEV): 
     fallocate -l 806354944 $(TMPDEV) 
     sudo parted --script $(TMPDEV) unit s mklabel msdos \ 
      mkpart primary fat16 2048 526335 \ 
      mkpart primary fat32 526336 1050623 \ 
      mkpart primary NTFS 1050624 1574911 \ 
      quit 
     $(eval TMPDISK := $(shell sudo partx --verbose -a $(TMPDEV) | tail -1 | cut -d':' -f1)) 
     echo $(TMPDISK) 
     sudo mkfs.fat -F 16 -n FAT16 $(TMPDISK)p1 

Это невозможно знать, что значение TMPDISK не будет до тех пор, по крайней мере, после fallocate вызова; поэтому оператор $(eval) задерживается до тех пор, пока изображение диска не будет разделено.

выход я получаю это:

$ make 
partx: stat failed /tmp/disk.img: No such file or directory 
fallocate -l 806354944 /tmp/disk.img || dd if=/dev/zero of=/tmp/disk.img bs=1b count=1574912 
sudo parted --script /tmp/disk.img unit s mklabel msdos \ 
    mkpart primary fat16 2048 526335 \ 
    mkpart primary fat32 526336 1050623 \ 
    mkpart primary NTFS 1050624 1574911 \ 
    quit 
echo 

Тот факт, что partx ошибки вне (и, таким образом, TMPDISK устанавливается опустошить) перед любой другой команды выполнять заставляет меня думать, что $(shell) называют раньше, чем предполагалось. В любом случае, чтобы отложить вызов оболочки и присвоение TMPDISK до соответствующей строки?

ответ

2

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

Как правило, не типично использовать $(shell ...) в рецепте, так как рецепт уже запущен в оболочке. И внесение переменных в рецепт через $(eval ...) также очень необычно.

Я бы порекомендовал вам переписать этот рецепт для использования переменных оболочки, а не для переменных; это будет более понятным:

TMPDEV=/tmp/disk.img 

$(TMPDEV): 
     fallocate -l 806354944 $(TMPDEV) 
     sudo parted --script $(TMPDEV) unit s mklabel msdos \ 
      mkpart primary fat16 2048 526335 \ 
      mkpart primary fat32 526336 1050623 \ 
      mkpart primary NTFS 1050624 1574911 \ 
      quit 
     TMPDISK=$$(sudo partx --verbose -a $(TMPDEV) | tail -1 | cut -d':' -f1); \ 
      echo $$TMPDISK; \ 
      sudo mkfs.fat -F 16 -n FAT16 $${TMPDISK}p1 
+1

Вам нужно удвоить все '' ', которые вы хотите передать оболочке, чтобы оценить оболочку вместо make. Поэтому вам нужно использовать backticks или '$$ (..)' –

+0

. Вы не правы: пропустили один. – MadScientist

2

У меня была та же проблема. Команда eval расширяется еще до запуска целевой команды. На мой вопрос ответил Саймон Гиббонс.

makefile variable assignment under a target

Решение состоит в том, чтобы добавить другую цель для команды «fallocate» и добавить, что как зависимость до $ (TMPDEV) цели.

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