Posso compilare tutti i file .cpp in src / in .o in obj /, quindi collegarmi al binario in ./?


116

La directory del mio progetto ha questo aspetto:

/project
    Makefile
    main
    /src
        main.cpp
        foo.cpp
        foo.h
        bar.cpp
        bar.h
    /obj
        main.o
        foo.o
        bar.o

Quello che vorrei che il mio makefile facesse sarebbe compilare tutti i .cppfile nella /srccartella in .ofile nella /objcartella, quindi collegare tutti i .ofile nel /objbinario di output nella cartella di primo livello /project.

Non ho quasi nessuna esperienza con i Makefile e non sono davvero sicuro di cosa cercare per ottenere questo risultato.

Inoltre, questo è un modo "buono" per farlo o esiste un approccio più standard a ciò che sto cercando di fare?



6
@aaa: Immagino che l'OP voglia una soluzione che non richieda un elenco esplicito di ogni file sorgente.
Cascabel

7
Non voglio specificare ogni file sorgente che ho, e ho già provato a leggere quel manuale, ma lo trovo disorganizzato e difficile da capire. Imparo molto meglio da un esempio reale che fa quello che mi aspetto che fa ed è ben spiegato, piuttosto che da manuali tecnici asciutti.
Austin Hyde

va bene. Ma fare documentazione è eccellente con buoni esempi (non è provare manuale tecnico). stai cercando regole di pattern: gnu.org/software/make/manual/make.html#Pattern-Rules
Anycorn

11
Assomiglia un po 'di più a quello che voglio. Tuttavia, IMHO, il manuale di make è un po 'arido, poiché sembra più mirato agli sviluppatori che si trovano a un livello intermedio con make, e oltre a questo è molto ampio e approfondito. Forse anche troppo.
Austin Hyde

Risposte:


180

Makefile parte della domanda

Questo è abbastanza semplice, a meno che non sia necessario generalizzare, prova qualcosa di simile al codice seguente (ma sostituisci il rientro dello spazio con tabulazioni vicino a g ++)

SRC_DIR := .../src
OBJ_DIR := .../obj
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
LDFLAGS := ...
CPPFLAGS := ...
CXXFLAGS := ...

main.exe: $(OBJ_FILES)
   g++ $(LDFLAGS) -o $@ $^

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
   g++ $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<

Generazione automatica del grafico delle dipendenze

Una caratteristica "indispensabile" per la maggior parte dei sistemi di marca. Con GCC in può essere fatto in un unico passaggio come effetto collaterale della compilazione aggiungendo -MMDbandiera CXXFLAGSe -include $(OBJ_FILES:.o=.d) alla estremità del corpo makefile:

CXXFLAGS += -MMD
-include $(OBJ_FILES:.o=.d)

E come i ragazzi hanno già detto, avere sempre GNU Make Manual in giro, è molto utile.


11
Ah, mi hai battuto di secondi. Ma io suggerisco OBJ_FILES = $(patsubst src/%.cpp,obj/%.o,$(CPP_FILES)).
Beta

1
Ho dovuto cambiarlo perché funzionasse: $<dovrebbe essere $^per la regola di main.exe e penso che ci sia un errore di battitura con obj/%.o: src/%cpp.

1
@bobah Ti manca un "." nella regola degli oggetti per il cpp
regomodo

1
le variabili speciali sono probabilmente degne di essere spiegate, poiché sono specifiche del makefile e difficili da cercare: gnu.org/software/make/manual/html_node/Automatic-Variables.html
Blake

2
So che questa è una vecchia domanda, ma ho modificato un po 'in base al mio progetto, ma non funziona. Ecco il mio makefile: pastebin.com/4CksG9Wc Ottengo in console:make: *** No rule to make target '/main.o', needed by 'bin/main'. Pare.
Mateus Felipe

5

Il carattere jolly funziona anche per me, ma vorrei dare una nota a margine per coloro che utilizzano le variabili di directory. Usa sempre la barra per l'albero delle cartelle (non la barra rovesciata), altrimenti fallirà:

BASEDIR = ../..
SRCDIR = $(BASEDIR)/src
INSTALLDIR = $(BASEDIR)/lib

MODULES = $(wildcard $(SRCDIR)/*.cpp)
OBJS = $(wildcard *.o)

intendevi taglio in avanti? Il tuo esempio mostra ciò che tradizionalmente è considerato la barra in avanti. Nello specifico, quelli "inclinati a destra" sono considerati "in avanti" e quelli a sinistra sono considerati "indietro"
Evan Teran

Sì, hai ragione, intendo solo "taglio". Ho aggiornato il post.
xesf
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.