2017-02-14 36 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