2012-10-19 2 views
10

Sto volendo utilizzare un makefile per aggiornare i file di figura generati dal codice R. Il codice R si trova in vari file nella directory ../R e tutti terminano con .R. I file delle figure si trovano nella directory ../figs e tutti terminano con .pdf o .png. Se un file R ha una data successiva rispetto a qualsiasi dei file di figura, voglio elaborare il file R con il comandoMakefile con più ingressi e uscite

R --no-save < file.R 

Ho guardato un vari esempi di makefile, ma non ho trovato nulla ho potuto adattarsi.

mio sforzo di corrente (non funzionante) è la seguente:

PLOTDIR= ../figs 
RDIR= ../R 
RFILES= $(RDIR)/*.R 
PLOTS= *.pdf *.png 
FIGURES= $(PLOTDIR)/$(PLOTS) 
$(FIGURES): $(RFILES) 
    R --no-save < $< 
+0

Perché non si usa 'Rscript file.R' invece di' R --no-save rinni

+0

Esiste una connessione tra i nomi dei file R e i nomi dei file di figura? – Beta

+1

@rinni. Nessun motivo speciale Anche quello funzionerebbe. –

risposta

2

È possibile provare quanto segue.

I trucchi sono che è necessario dedurre uscita da ingressi (file .R)

# Makefile 
# Beware of indentation when copying use TABS 

PLOTDIR = ../figs 
RDIR = ../R 

# list R files 
RFILES = $(wildcard $(RDIR)/*.R) 

# compute output file names 
PDF_FIGS = $(RFILES:.R=.pdf) 
PNG_FIGS = $(RFILES:.R=.png) 

# relocate files in output folder 
OUT_FILES = $(subst $(RDIR), $(PLOTDIR), $(PDF_FIGS) $(PNG_FIGS)) 

# first target is the default: simply do 'make' 
all: $(OUT_FILES) 

clean: 
    rm $(OUT_FILES) 

.PHONY: all clean 

# need to split PNG from PDF rules 
$(PLOTDIR)/%.png: $(RDIR)/%.R 
    R --no-save < $< 

$(PLOTDIR)/%.pdf $(PLOTDIR)/%.png: $(RDIR)/%.R 
    R --no-save < $< 

Modifica per riflettere il mio commento: Utilizzo del file di output 1 dipendenza per script R

PLOTDIR= ../figs 
RDIR= ../R 

# list R files 
RFILES := $(wildcard $(RDIR)/*.R) 

# relocate files in output folder 
OUT_FILES=$(subst $(RDIR), $(PLOTDIR), $(RFILES:.R=.out)) 
#$(warning $(OUT_FILES)) 

# first target is the default: simply do 'make' 
all: $(OUT_FILES) 

clean: 
    rm $(OUT_FILES) 

.PHONY: all clean 

$(PLOTDIR)/%.out: $(RDIR)/%.R 
    R --no-save < $< && touch [email protected] 
+0

Non penso che funzionerà. I nomi di "OUT_FILES" non sono corretti, quindi, in generale, eseguirà ogni file R ogni volta. – Beta

+0

@Beat: ho corretto le regole. Solo il problema sussistente è che non sappiamo se è stato emesso un PDF o un PNG (o entrambi). Una soluzione è quella di creare un solo file di output (i.e ../figs/%.out) da uno script R usando 'touch' (più un file di figure veramente generativo, ovviamente). – levif

+0

Grazie. Il tuo secondo file ha fatto esattamente quello di cui avevo bisogno, anche se non era esattamente quello che chiedevo! –

1

Un problema interessante È logicamente semplice, ma va dritti contro la cosa che piace a Make.

Questo sembra funzionare. Fa affidamento su una funzione oscura delle regole del modello: se una regola del modello ha più di un obiettivo, Crea è necessario eseguirlo una sola volta per aggiornare tutti i suoi obiettivi.

PLOTDIR = ../figs 
RDIR = ../R 
RFILES = $(wildcard $(RDIR)/*.R) 
FIGURES = $(wildcard $(PLOTDIR)/*.pdf $(PLOTDIR)/*.png) 

all: $(FIGURES) 

$(PLOTDIR)/%.pdf $(PLOTDIR)/%.png: $(RFILES) 
     @for x in $?; do R --no-save \< $$x; done 
+0

Questo fa quello che voglio (con il \

+1

@Beta: cosa succede se non esiste già una figura? Le figure sono vuote e non viene fatto nulla. – levif

+0

@RobHyndman Per avere un controllo più preciso su cui i file .R generano le cifre, è possibile separare la dichiarazione dei prerequisiti dalla dichiarazione della ricetta. Per fare ciò, usa una ricetta generica (ad es. Rimuovi $ (RFILES) dalla ricetta qui) per eseguire il lavoro, e i prerequisiti per ciascun target (figura) possono essere sulle linee di dichiarazione senza una ricetta. hm; non sono sicuro che funzionerà con $? variabile automatica; potrebbe. –