我正在编写一个生成Makefile
的R包,我需要在制作目标之前编写一个Makefile
来调用Rscript
。该问题的MWE如下。因为.INIT
的右侧不执行而导致退出错误。为file.rds
编写食谱不符合我的需要。
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
答案 0 :(得分:1)
我认为您需要使用:=
和$(shell ...)
:
.INIT := $(shell Rscript -e 'saveRDS('$(a)', "file.rds")')
这会产生simply expanded variable
而不是recursively expanded variable
。我认为,即使查看.INIT
的定义,Make也不会烦恼,因为它从未使用过。
反引号在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