2014-04-10 84 views
3

我有一個Makefile規則,要求將shell命令的結果存儲到變量中以供以後使用。出於某種原因,看起來$(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之前,始終首先擴展整個配方中的所有變量。沒有辦法「推遲」,直到晚些時候。

通常,在配方中使用$(shell ...)並不常見,因爲配方已經在shell中運行。通過$(eval ...)在配方內設置變量也非常不尋常。

我會建議你改寫這個配方,使用shell變量,而不是變量;它會更容易理解:

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

您需要將所有想要傳遞到shell的'$'加倍以使shell評估,而不是make。所以你需要使用反引號或$$(..)' –

+0

哎呀,你是對的:錯過了一個。 – MadScientist

2

我有同樣的問題。即使在目標命令運行之前,eval命令也會擴展。下面我回答Simon Gibbons提出的問題。

makefile variable assignment under a target

的解決方案是增加另一個目標,爲「fallocate」命令,並添加作爲依賴於$(TMPDEV)目標。