2016-04-29 8 views
0

sagen, dass ich eine Liste von Quelldateien wie dieses:Wie definiere ich Ziel-abhängige Voraussetzungen mit GNUMake?

SOURCE=aaa.src bbb.src ccc.src 

ich eine Regel erstellen möchten jedes entsprechende Ziel in einen eigenen Ordner zu erstellen, deren Name ist abhängig von der soruce Datei.

Source ----> Entsprechende Ausgabedatei/Ziel


aaa.src -------------------> aaa/aaa .out

bbb.src -------------------> bbb/bbb.out

ccc.src --------- ----------> ccc/ccc.out

Wie? Ich schreibe dafür eine Regel mit GNUMake? Mein bestes Bemühen war die folgende Makefile:

.PHONY: all clean 

CC=somecompiler 

SOURCE := aaa.src bbb.src ccc.src 
RTARGS := $(SOURCE:%.src=%.out) 
TDIRS := $(addsuffix /,$(basename $(SOURCE))) 
TARGS := $(join $(TDIRS), $(RTARGS)) 

all:$(TARGS) 

%.out: $(SOURCE)  # Better source specification? 
    @[ ! -d "$(dir $*)" ] && mkdir "$(dir $*)" 
    $(CC) "$(patsubst %/,%,$(dir $*)).src" "[email protected]" 

clean: 
    rm -f $(TARGS) 
    rmdir --ignore-fail-on-non-empty $(TDIRS) 

Das Problem hierbei ist, dass jeder eines Ziel (dh .out-Datei) auf Quelle jede abhängt (dh .src-Datei), statt nur die eine, die die gleiche ist Basisname. Ich könnte die kommentierte Zeile in %.out: %.src ändern, aber die Quelldatei müsste sich im selben Verzeichnis wie die Ausgabedatei befinden. Ich könnte es auch so etwas wie dieses kompilieren:

%.out: %.src 
    $(CC) "$>" -o "$*/[email protected]" 

Aber dann würde immer unabhängig von jedem Ziel kompilieren, ob es bereits vorhanden ist oder nicht.

Wie bekomme ich nur die entsprechende Quelldatei verwenden. Wie können Abhängigkeiten für jedes Ziel separat in einer allgemeinen Regel angegeben werden?

Antwort

1

In GNU Make Sie Voraussetzungen getrennt von Rezepten und nach wie vor eine generic/Pattern-Regel für alle .out Dateien angeben:

.PHONY: all clean 

all : 

SOURCES := aaa.src bbb.src ccc.src 
OUTPUTS := $(foreach src,${SOURCES},$(basename ${src})/${src:%.src=%.out}) 

# Build dependencies in the form of x/x.out : x.src | x 
define ESTABLISH_DEPENDENCY = 
$(basename ${1})/${1:%.src=%.out} : ${1} | $(basename ${1}) # Also depend on the output directory. 
$(basename ${1}) : # Rule to create the output directory. 
    mkdir [email protected] 
endef 

$(foreach src,${SOURCES},$(eval $(call ESTABLISH_DEPENDENCY,${src}))) 

all : ${OUTPUTS} 

# Generice rule for all .out files. 
%.out : 
    @echo "build [email protected] from $^" 
    touch [email protected] 

%.src : # For debugging only. 
    touch [email protected] 

.PHONY: all 

Ausgang:

$ make 
touch aaa.src 
mkdir aaa 
build aaa/aaa.out from aaa.src 
touch aaa/aaa.out 
touch bbb.src 
mkdir bbb 
build bbb/bbb.out from bbb.src 
touch bbb/bbb.out 
touch ccc.src 
mkdir ccc 
build ccc/ccc.out from ccc.src 
touch ccc/ccc.out 

Beachten Sie, dass es effizienter ist, und elegant, um nur Order-abhängigkeiten von Verzeichnissen zu haben und sie erstellen zu lassen, als jedes Rezept das Vorhandensein von Verzeichnissen zuerst überprüfen zu lassen.

+0

Okay, im Grunde, was "ESTABLISH_DEPENDENCY" tut, wenn es aufgerufen wird, ist eine leere Regel zu erstellen, die nur die Abhängigkeiten und eine andere Regel angibt, die das Verzeichnis erstellt. Habe ich recht? Auf jeden Fall ist das ziemlich schlau. Vielen Dank! –

+0

@ con-f-use Rechts. Um pedantisch zu sein, erzeugt es nur eine Abhängigkeit und keine Regel für ".out". Und eine Regel für das Verzeichnis. –

+0

Danke nochmal. Bitte ignoriere meinen Schnitt, ich habe übersehen, dass 'all:' schon in der dritten Zeile richtig war –