r语言 - 调用 Rscript 的可移植生成文件



我正在编写一个生成Makefile的 R 包,我需要编写一个在创建目标之前调用RscriptMakefile。问题的 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

我认为您需要使用:=并因此$(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

最新更新