2012-10-28 9 views
7

La struttura di directory del mio C++ progetto è
compilare tutti i file CPP utilizzando makefile in MinGW

/.. 
    makefile  <- the makefile is in root 
    /include  <- subdirectory that has to be included while compiling 
    /obj   <- target place for all *.o and final executable 
    /src   <- sources 

E il mio makefile corrente è:

CC=g++ 
CFLAGS=-c -Wall -std=c++11 

INC=-Iinclude 
SRC=src 
TGT=obj 

all: myapp 

myapp: myapp.o 
    $(CC) $(TGT)/myapp.o -o $(TGT)/myapp 

myapp.o: 
    $(CC) $(CFLAGS) $(INC) $(SRC)/myapp.cpp -o $(TGT)/myapp.o 

clean: 
    rm -rf $(TGT) 
    mkdir $(TGT) 

questo ha lavorato per il mio primo file. Sono un novizio completo di makefile - per favore aiutami a compilare tutti i file sotto la directory /src e collegarli a un eseguibile nella directory /obj.

il makefile deve lavorare sotto Windows, io sto usando MinGW e MSYS

risposta

5

Aggiungere un elenco dei file di origine:

SOURCES = $(wildcard $(SRC)/*.cpp) 

ed una lista di oggetti file corrispondenti:

OBJS = $(addprefix $(TGT)/, $(notdir $(SOURCES:.cpp=.o))) 

e l'eseguibile di destinazione:

$(TGT)/myapp: $(OBJS) 
    $(CXX) $(LDFLAGS) $(OBJS) -o [email protected] 

Il regola per la costruzione degli oggetti:

$(TGT)/%.o: $(SRC)/%.cpp 
    $(CXX) $(CXXFLAGS) -c $< -o [email protected] 

Ora è necessario specificare sono le opzioni per il g ++:

INCLUDES = -Iinclude 
CXXFLAGS = -Wall -std=c++11 $(INCLUDES) 

E tutto insieme:

SRC=src 
TGT=obj 
INCLUDES = -Iinclude 
CXXFLAGS = -Wall -std=c++11 $(INCLUDES) 
SOURCES = $(wildcard $(SRC)/*.cpp) 
OBJS = $(addprefix $(TGT)/, $(notdir $(SOURCES:.cpp=.o))) 

$(TGT)/%.o: $(SRC)/%.cpp 
    $(CXX) $(CXXFLAGS) -c $< -o [email protected] 

$(TGT)/myapp: $(OBJS) 
    $(CXX) $(LDFLAGS) $(OBJS) -o [email protected] 

E 'importante, che di fronte a $(CXX) ... ci deve essere una "scheda "carattere, non spazi.

+0

È possibile parametrizzare la parte '-Idir'? La tua soluzione sembra concisa. Due cose da cambiare: il make-script dovrebbe mettere sia il file '* .o' che l'eseguibile finale nella directory TGT ... – emesx

+0

Cosa intendi con parametrizzato? Puoi metterlo in una variabile separata e aggiungere questa variabile a 'CXXFLAGS', ovviamente. Vedi risposta modificata. –

+1

@elmes Si prega di provare il 'Makefile' modificato, ho regolato per la directory di destinazione separata. –

1

È possibile utilizzare VPATH for separating source and object files:

src/myapp.c 
obj/Makefile 

Prendete il vostro attuale Makefile, spostarlo nella obj/, omettere i riferimenti a $(TGT) e $(SRC) e aggiungere il seguente:

VPATH=../src 

si noti che se si ar e cercando di fare multi-architecture builds, VPATH is not ideal.


BTW, non si sta capitalizzando builtin rules.Dove avete

CC=g++ 
CFLAGS=-c -Wall -std=c++11 
myapp: myapp.o 
    $(CC) $(TGT)/myapp.o -o $(TGT)/myapp 

myapp.o: 
    $(CC) $(CFLAGS) $(INC) $(SRC)/myapp.cpp -o $(TGT)/myapp.o 

si potrebbe invece utilizzare:

CXXFLAGS=-Wall -std=c++11 
CXXFLAGS+=$(INC) 
LDLIBS+=-lstdc++ 

myapp: myapp.o 

Quindi, per riassumere il tutto, il vostro nuovo obj/Makefile dovrebbe presentarsi così:

VPATH=../src 
INC=-I../include 
CXXFLAGS=-Wall -std=c++11 
CXXFLAGS+=$(INC) 
LDLIBS+=-lstdc++ 

myapp: myapp.o 

Puoi crea un altro Makefile da obj/ per recedere in questo nuovo, se necessario:

all: obj/myapp 

obj/myapp: 
    mklink obj/Makefile ../Makefile 
    $(MAKE) --directory=obj/ 
+0

come ho detto, sono nuovo ai makefile. Potresti creare un esempio funzionante che si adatti allo scenario descritto nella domanda? – emesx

+0

ok, l'unica cosa che manca nell'esempio è stata la VPATH. Quindi eccoti. –

+0

ma perché il makefile deve risiedere nella directory 'obj' .. non è un buon posto per tenerlo, dato che voglio cancellare facilmente quella directory – emesx