2012-10-19 18 views
10

Chcę użyć pliku makefile do aktualizacji plików figur generowanych przez kod R. Kod R znajduje się w różnych plikach w katalogu ../R, a wszystkie kończą się w .R. Pliki figur są w katalogu ../figs i wszystkie kończą się .pdf lub. Jeśli plik R ma datę późniejszą niż którykolwiek z plików rysunku, chcę przetworzyć pliku R z poleceniemMakefile z wieloma wejściami i wyjściami

R --no-save < file.R 

szukałem różnego przykładowe pliki Makefile, ale nie mógł znaleźć coś mogłem przystosować.

Mój obecny wysiłek (nie działa) jest następujący:

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

Dlaczego nie używacie 'Rscript file.R' zamiast' R --no-save rinni

+0

Czy istnieje związek między nazwami plików R a nazwami plików figur? – Beta

+1

@rinni. Bez specjalnego powodu. To też by działało. –

Odpowiedz

2

Można spróbować wykonać następujące czynności.

Sztuczki to, że trzeba wyprowadzić wyjście z wejściami (plik 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 < $< 

Edit odzwierciedla mój komentarz: Stosować 1 zależnościach plik wyjściowy za skryptu 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

Nie sądzę, że to zadziała. Nazwy 'OUT_FILES' są niepoprawne, więc za każdym razem uruchamiają każdy plik R. – Beta

+0

@Beat: Naprawiłem zasady. Jedynym problemem jest to, że nie wiemy, czy plik PDF lub PNG został wydany (lub oba). Jednym z rozwiązań jest utworzenie tylko jednego pliku wyjściowego (tzn. ../figs/%.out) z jednego skryptu R za pomocą "dotyku" (plus naprawdę generowanie pliku liczbowego, oczywiście). – levif

+0

Dzięki. Twój drugi plik zrobił dokładnie to, czego potrzebowałem, mimo że nie było to dokładnie to, o co prosiłem! –

1

Ciekawy problem. Jest to logicznie proste, ale idzie wbrew ziarnom tego, co Make robi.

To wydaje się działać. Opiera się na niejasnej funkcji reguł wzorca: jeśli reguła wzoru ma więcej niż jeden cel, upewnij się, że trzeba uruchomić tylko raz, aby zaktualizować wszystkie swoje obiekty docelowe.

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

To robi to, co chcę (z \

+1

@Beta: co jeśli żadna postać już nie istnieje? FIGURES jest puste i nic się nie dzieje. – levif

+0

@RobHyndman Aby uzyskać dokładniejszą kontrolę nad tym, które pliki .R generują liczby, można oddzielić deklarację wymagań od deklaracji receptury. Aby to zrobić, użyj ogólnej recepty (tj. Usuń $ (RFILES) z przepisu tutaj), aby wykonać pracę, a wymagania wstępne dla każdego celu (rysunku) mogą znajdować się na liniach deklaracji bez receptury. Hm; nie jestem pewien, czy to zadziała z $? zmienna automatyczna; może. –

Powiązane problemy