2017-02-14 33 views
0

我正在編寫一個生成Makefile的R程序包,我需要編寫一個Makefile,在制定目標之前調用Rscript。以下是MWE的問題。由於.INIT的右側未執行,因此錯誤退出。編寫file.rds的食譜不適合我的需求。稱爲Rscript的便攜式Makefiles

a=1 
.INIT=`Rscript -e 'saveRDS('$(a)', "file.rds")'` 

all: file2.rds 

file2.rds: file.rds 
     cp file.rds file2.rds 

clean: 
     rm file.rds file2.rds 

我能做些什麼來解決這個Makefile並保持便攜?從R擴展手冊中,我不能使用$(shell來實現我想要完成的任務。


編輯

從@ Spacedman的第一個答案,我學會了當且僅當它的地方作爲變量.INIT被「擴大」 /執行。太棒了! @Spacedman,我邀請您將以下Makefile複製到您自己的答案中,以便我可以給您信用。

a=1 
.INIT=`Rscript -e 'saveRDS('$(a)', "file.rds")'` 

all: file2.rds 

file2.rds: 
     echo "file.rds should not have been built." 

file3.rds: 
     echo -n $(.INIT) 
     cp file.rds file3.rds 

clean: 
     rm file.rds file2.rds 

以下演示了我所希望的結果。

$ make file2.rds 
echo "file.rds should not have been built." 
file.rds should not have been built. 
$ ls file.rds 
ls: cannot access file.rds: No such file or directory 
$ make file3.rds 
echo -n `Rscript -e 'saveRDS('1', "file.rds")'` 
cp file.rds file3.rds 
$ ls file.rds 
file.rds 
+1

什麼錯誤?您是否希望Makefile通過.INIT創建'file.rds',然後將其視爲file2.rds的依賴項? – Spacedman

+0

是的,確切地說。可笑,我知道,但實際使用情況不同,足以說明問題。 – landau

+0

如果你不能使用'$(shell)並且你不能使用配方,我懷疑你是塞滿的,我沒有看到運行外部命令的另外一種方式 – Spacedman

回答

1

我認爲你需要使用:=$(shell ...)這樣的:

.INIT := $(shell Rscript -e 'saveRDS('$(a)', "file.rds")') 

這使得simply expanded variable而非recursively expanded variable。我認爲Make甚至不會考慮.INIT的定義,因爲它從未使用過。

反斜槓在Make中不能像這樣工作,您必須使用$(shell ...)。你真的不能在任何地方使用$(shell ...)

https://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_6.html

測試:

$ rm file.rds file2.rds 
$ make 
cp file.rds file2.rds 
$ ls file*rds 
file2.rds file.rds 

這似乎表明make創造了通過R腳本file.rds

如果你可以把反引號字符串放在配方中,你可以使它工作(如你發現的!)。注意我不認爲你需要回顯字符串,你可以得到它擴大,這似乎工作:

a=1 
.INIT=`Rscript -e 'saveRDS('$(a)', "file.rds")'` 

all: file2.rds 

file2.rds: 
    echo "file.rds should not have been built." 

file3.rds: 
    $(.INIT) 
    cp file.rds file3.rds 
+0

是的,我真的不能在任何地方使用'$(shell ...)'。 – landau

+0

查看我更新的帖子。你給了我解決方案的想法。隨意編輯成你自己的答案,我會接受它。 – landau

+1

輕微調整您的解決方案... – Spacedman