简体   繁体   中英

Portable Makefiles that call Rscript

I'm writing an R package that generates Makefile s, I need to write a Makefile that calls Rscript before making the targets. A MWE of the problem is below. Make quits in error because the right-hand side of .INIT does not execute. Writing a recipe for file.rds does not suit my needs.

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

What can I do to fix this Makefile and keep it portable? From the R extensions manual, I can't use $(shell for what I'm trying to accomplish.


EDIT

From @Spacedman's first answer, I learned that .INIT is "expanded"/executed if and only if it is used as a variable somewhere. This is perfect! @Spacedman, I invite you to copy the following Makefile into an answer of your own so I can give you credit.

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

The following demonstrates the results I had hoped for.

$ 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

I think you need to use := and $(shell ...) thus:

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

This makes a simply expanded variable rather than a recursively expanded variable . I think Make doesn't bother even looking at your definition for .INIT because its never used.

Backticks don't work like this in Make, you have to use $(shell ...) . Can you really not use $(shell ...) anywhere ?

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

Test:

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

Which seems to show make has created file.rds via the R script.

If you can put the backquoted string in a recipe, you can make it work (as you discovered!). Note I don't think you need to echo the string, you can just get it expanded and this seems to work:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM