Come creare un Makefile C ++ SEMPLICE


303

Ci viene richiesto di usare un Makefile per mettere insieme tutto per il nostro progetto, ma il nostro professore non ci ha mai mostrato come.

Ho solo un file a3driver.cpp. Il conducente importa una classe da una posizione, "/user/cse232/Examples/example32.sequence.cpp".

Questo è tutto. Tutto il resto è contenuto con .cpp.

Come farei per creare un semplice Makefile che crei un eseguibile chiamato a3a.exe?


9
.EXE quindi è sicuramente Windows. A pensarci bene ... il percorso è in stile Unix. Probabilmente usando Mingw-32.
Nathan Osman,

2
Sospiro. Suppongo che tu debba imparare le basi di ogni operazione, anche se non le userai mai. Devo solo capire come funzionano le cose. È probabile, tuttavia, che svilupperai sempre in un IDE, come Eclipse. Otterrai una risposta qui per il tuo semplice caso a una riga e ci sono molti tutorial Web, ma se vuoi una conoscenza approfondita, non puoi battere il libro di O'reilly (lo stesso per la maggior parte degli argomenti in bianco e nero). amazon.com/Managing-Projects-Make-Nutshell-Handbooks/dp/… Scegli una copia di seconda mano da amazon, half.com, betterworldbooks eBay
Mawg dice di ripristinare Monica

2
Il link pubblicato da @Dennis ora è morto, ma lo stesso materiale può essere trovato in questa pagina di archive.org .
Guilherme Salomé,

Preferisco le idee di questa persona. ( hiltmon.com/blog/2013/07/03/… ) La struttura del progetto può essere facilmente modificata per adattarla. E sono anche d'accordo sul fatto che il tempo degli sviluppatori dovrebbe essere speso per altre cose oltre a automake / autoconf. Questi strumenti hanno il loro posto, ma forse non per i progetti interni. Sto costruendo una sceneggiatura che produrrà tale struttura di progetto.
Daisuke Aramaki,

@ GuilhermeSalomé Grazie, credo che questo sia il miglior tutorial semplice e completo.
Hareen Laks,

Risposte:


561

Poiché questo è per Unix, gli eseguibili non hanno estensioni.

Una cosa da notare è che root-configè un'utilità che fornisce i corretti flag di compilazione e collegamento; e le librerie giuste per la creazione di applicazioni contro root. Questo è solo un dettaglio relativo al pubblico originale per questo documento.

Make Me Baby

o non dimentichi mai la prima volta che sei stato realizzato

Una discussione introduttiva su make e su come scrivere un semplice makefile

Cos'è Make? E perché dovrei preoccuparmi?

Lo strumento chiamato Make è un gestore delle dipendenze di compilazione. Cioè, si occupa di sapere quali comandi devono essere eseguiti nell'ordine in cui prendere il progetto software da una raccolta di file sorgente, file oggetto, librerie, intestazioni, ecc. Ecc., Alcuni dei quali potrebbero essere cambiati di recente --- e trasformandoli in una corretta versione aggiornata del programma.

In realtà, puoi usare Make anche per altre cose, ma non ne parlerò.

Un Makefile Trivial

Supponiamo di avere una directory contenente:, tool tool.cc tool.o support.cc support.hhe support.oche dipendono da roote dovrebbero essere compilati in un programma chiamato tool, e supponiamo che tu abbia hackerato i file di origine (il che significa che l'attuale non toolè aggiornato) e vuoi compilare il programma.

Per farlo da soli potresti farlo

  1. Controlla se uno support.cco support.hhè più recente di support.o, e in tal caso esegui un comando simile

    g++ -g -c -pthread -I/sw/include/root support.cc
  2. Controlla se uno support.hho tool.ccsono più recenti di tool.o, e in tal caso esegui un comando simile

    g++ -g  -c -pthread -I/sw/include/root tool.cc
  3. Controlla se tool.oè più recente di tool, e in tal caso esegui un comando simile

    g++ -g tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
    -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
    -Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl

Accidenti! Che seccatura! C'è molto da ricordare e diverse possibilità di commettere errori. (A proposito, i dettagli delle righe di comando qui esposte dipendono dal nostro ambiente software. Questi funzionano sul mio computer.)

Naturalmente, potresti semplicemente eseguire tutti e tre i comandi ogni volta. Funzionerebbe, ma non si adatta bene a un sostanziale software (come DOGS che impiega più di 15 minuti per essere compilato da zero sul mio MacBook).

Invece potresti scrivere un file chiamato makefilecosì:

tool: tool.o support.o
    g++ -g -o tool tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
        -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
        -Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl

tool.o: tool.cc support.hh
    g++ -g  -c -pthread -I/sw/include/root tool.cc

support.o: support.hh support.cc
    g++ -g -c -pthread -I/sw/include/root support.cc

e basta digitare makedalla riga di comando. Che eseguirà automaticamente i tre passaggi sopra indicati.

Le linee senza rientro qui hanno il formato "target: dipendenze" e indicano a Make che i comandi associati (linee rientrate) devono essere eseguiti se una qualsiasi delle dipendenze è più recente del target. Cioè, le linee di dipendenza descrivono la logica di ciò che deve essere ricostruito per adattarsi alle modifiche in vari file. Se support.cccambia ciò significa che support.odeve essere ricostruito, ma tool.opuò essere lasciato solo. Quando le support.omodifiche tooldevono essere ricostruite.

I comandi associati a ciascuna linea di dipendenza sono impostati con una scheda (vedi sotto) dovrebbe modificare la destinazione (o almeno toccarla per aggiornare il tempo di modifica).

Variabili, regole incorporate e altri gadget

A questo punto, il nostro makefile sta semplicemente ricordando il lavoro che deve essere fatto, ma dovevamo ancora capire e digitare ogni comando necessario nella sua interezza. Non deve essere così: Make è un linguaggio potente con variabili, funzioni di manipolazione del testo e un'intera serie di regole integrate che possono semplificarci molto.

Crea variabili

La sintassi per accedere a una variabile make è $(VAR).

La sintassi per l'assegnazione a una variabile Make è: VAR = A text value of some kind (o VAR := A different text value but ignore this for the moment).

Puoi usare le variabili in regole come questa versione migliorata del nostro makefile:

CPPFLAGS=-g -pthread -I/sw/include/root
LDFLAGS=-g
LDLIBS=-L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
       -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz \
       -Wl,-framework,CoreServices -Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root \
       -lm -ldl

tool: tool.o support.o
    g++ $(LDFLAGS) -o tool tool.o support.o $(LDLIBS)

tool.o: tool.cc support.hh
    g++ $(CPPFLAGS) -c tool.cc

support.o: support.hh support.cc
    g++ $(CPPFLAGS) -c support.cc

che è un po 'più leggibile, ma richiede ancora molta digitazione

Crea funzioni

GNU make supporta una varietà di funzioni per l'accesso alle informazioni dal filesystem o altri comandi sul sistema. In questo caso siamo interessati a ciò $(shell ...)che si espande nell'output degli argomenti e $(subst opat,npat,text)che sostituisce tutte le istanze di opatcon npatnel testo.

Sfruttare questo ci dà:

CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)

SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))

tool: $(OBJS)
    g++ $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)

tool.o: tool.cc support.hh
    g++ $(CPPFLAGS) -c tool.cc

support.o: support.hh support.cc
    g++ $(CPPFLAGS) -c support.cc

che è più facile da scrivere e molto più leggibile.

Notare che

  1. Stiamo ancora dichiarando esplicitamente le dipendenze per ciascun file oggetto e l'eseguibile finale
  2. Abbiamo dovuto digitare esplicitamente la regola di compilazione per entrambi i file di origine

Regole implicite e modello

Generalmente ci aspettiamo che tutti i file sorgente C ++ vengano trattati allo stesso modo e Make fornisce tre modi per affermarlo:

  1. regole del suffisso (considerate obsolete in GNU make, ma conservate per compatibilità con le versioni precedenti)
  2. regole implicite
  3. regole del modello

Sono incorporate regole implicite e alcune saranno discusse di seguito. Le regole del modello sono specificate in una forma simile

%.o: %.c
    $(CC) $(CFLAGS) $(CPPFLAGS) -c $<

ciò significa che i file oggetto vengono generati dai file sorgente C eseguendo il comando mostrato, in cui la variabile "automatica" si $<espande al nome della prima dipendenza.

Regole integrate

Make ha un'intera serie di regole integrate che significano che molto spesso, un progetto può essere compilato da un makefile molto semplice, anzi.

La regola GNU integrata per i file sorgente C è quella mostrata sopra. Allo stesso modo creiamo file oggetto da file sorgente C ++ con una regola simile $(CXX) -c $(CPPFLAGS) $(CFLAGS).

I file a oggetto singolo vengono collegati utilizzando $(LD) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS), ma questo non funzionerà nel nostro caso, perché vogliamo collegare più file oggetto.

Variabili utilizzate dalle regole incorporate

Le regole integrate utilizzano un set di variabili standard che consentono di specificare le informazioni sull'ambiente locale (come dove trovare i file di inclusione ROOT) senza riscrivere tutte le regole. Quelli che molto probabilmente saranno interessanti per noi sono:

  • CC - il compilatore C da usare
  • CXX - il compilatore C ++ da usare
  • LD - il linker da usare
  • CFLAGS - flag di compilazione per i file sorgente C.
  • CXXFLAGS - flag di compilazione per file sorgente C ++
  • CPPFLAGS - flag per il preprocessore c (in genere includono percorsi di file e simboli definiti nella riga di comando), utilizzati da C e C ++
  • LDFLAGS - flag linker
  • LDLIBS - librerie da collegare

Un Makefile di base

Sfruttando le regole integrate possiamo semplificare il nostro makefile per:

CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)

SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))

all: tool

tool: $(OBJS)
    $(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)

tool.o: tool.cc support.hh

support.o: support.hh support.cc

clean:
    $(RM) $(OBJS)

distclean: clean
    $(RM) tool

Abbiamo anche aggiunto diversi target standard che eseguono azioni speciali (come ripulire la directory di origine).

Nota che quando make è invocato senza un argomento, usa la prima destinazione trovata nel file (in questo caso tutto), ma puoi anche nominare la destinazione per ottenere qual è ciò che rende make cleanrimuovere i file oggetto in questo caso.

Abbiamo ancora tutte le dipendenze codificate.

Alcuni misteriosi miglioramenti

CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)

SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))

all: tool

tool: $(OBJS)
    $(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)

depend: .depend

.depend: $(SRCS)
    $(RM) ./.depend
    $(CXX) $(CPPFLAGS) -MM $^>>./.depend;

clean:
    $(RM) $(OBJS)

distclean: clean
    $(RM) *~ .depend

include .depend

Notare che

  1. Non ci sono più linee di dipendenza per i file sorgente!?!
  2. C'è qualche strana magia legata a .dipendente e dipendente
  3. Se lo fai make, allora ls -Asi vede un file di nome .dependche contiene cose che assomigliano a linee di dipendenza make

Altra lettura

Conoscere bug e note storiche

La lingua di input per Make è sensibile agli spazi bianchi. In particolare, le linee d'azione che seguono le dipendenze devono iniziare con una scheda . Ma una serie di spazi può sembrare la stessa (e in effetti ci sono editor che convertiranno silenziosamente le schede in spazi o viceversa), il che si traduce in un file Make che sembra giusto e continua a non funzionare. Questo è stato identificato come un bug all'inizio, ma ( la storia continua ) non è stato corretto, perché c'erano già 10 utenti.

(Questo è stato copiato da un post wiki che ho scritto per studenti laureati in fisica.)


9
Questo metodo per generare dipendenze è obsoleto e effettivamente dannoso. Vedere Generazione avanzata di dipendenza automatica .
Maxim Egorushkin,

5
-pthreadflag causa la gccdefinizione delle macro necessarie, -D_REENTRANTnon è necessario.
Maxim Egorushkin,

8
@jcoe Esegue un passaggio preprocessore aggiuntivo non necessario per generare dipendenze. Facendo un lavoro inutile dissipa semplicemente il calore che scioglie i bastoncini di ghiaccio e, su una scala più grande, si avvicina alla morte per calore del nostro universo.
Maxim Egorushkin,

2
Probabilmente "dannoso" è un po 'troppo, ma dato che le fasi o gli obiettivi espliciti di generazione della dipendenza sono obsoleti dal momento che almeno GCC 3, penso davvero che tutti dovremmo superarli. bruno.defraine.net/techtips/makefile-auto-dependencies-with-gcc/…
hmijail piange le dimissioni il

2
In realtà, la risposta accettata non dovrebbe dipendere da un software molto specifico ( root-config). Un'alternativa più generale con la stessa capacità dovrebbe essere proposta se ce ne fosse una o se ne fosse semplicemente esclusa. Non ho votato in basso a causa della lista e della spiegazione delle macro di make più utilizzate.
diodo verde,

56

Ho sempre pensato che fosse più facile da imparare con un esempio dettagliato, quindi ecco come penso ai makefile. Per ogni sezione hai una riga che non è rientrata e mostra il nome della sezione seguito da dipendenze. Le dipendenze possono essere altre sezioni (che verranno eseguite prima della sezione corrente) o file (che se aggiornate causeranno la successiva esecuzione della sezione corrente alla successiva esecuzione make).

Ecco un breve esempio (tieni presente che sto usando 4 spazi in cui dovrei usare una scheda, Stack Overflow non mi permette di usare le schede):

a3driver: a3driver.o
    g++ -o a3driver a3driver.o

a3driver.o: a3driver.cpp
    g++ -c a3driver.cpp

Durante la digitazione make, sceglierà la prima sezione (a3driver). a3driver dipende da a3driver.o, quindi andrà a quella sezione. a3driver.o dipende da a3driver.cpp, quindi verrà eseguito solo se a3driver.cpp è cambiato dall'ultima esecuzione. Supponendo che sia (o non sia mai stato eseguito), compilerà a3driver.cpp in un file .o, quindi tornerà a a3driver e compilerà l'eseguibile finale.

Poiché esiste un solo file, potrebbe persino essere ridotto a:

a3driver: a3driver.cpp
    g++ -o a3driver a3driver.cpp

Il motivo per cui ho mostrato il primo esempio è che mostra il potere dei makefile. Se devi compilare un altro file, puoi semplicemente aggiungere un'altra sezione. Ecco un esempio con secondFile.cpp (che viene caricato in un'intestazione denominata secondFile.h):

a3driver: a3driver.o secondFile.o
    g++ -o a3driver a3driver.o secondFile.o

a3driver.o: a3driver.cpp
    g++ -c a3driver.cpp

secondFile.o: secondFile.cpp secondFile.h
    g++ -c secondFile.cpp

In questo modo se cambi qualcosa in secondFile.cpp o secondFile.h e ricompili, ricompilerà solo secondFile.cpp (non a3driver.cpp). In alternativa, se cambi qualcosa in a3driver.cpp, non ricompilerà secondFile.cpp.

Fammi sapere se hai qualche domanda a riguardo.

È anche tradizionale includere una sezione denominata "all" e una sezione denominata "clean". "all" di solito costruirà tutti gli eseguibili e "clean" rimuoverà "build artefacts" come i file .o e gli eseguibili:

all: a3driver ;

clean:
    # -f so this will succeed even if the files don't exist
    rm -f a3driver a3driver.o

EDIT: Non ho notato che sei su Windows. Penso che l'unica differenza sta cambiando -o a3driverin -o a3driver.exe.


Il codice assoluto che sto cercando di usare è: p4a.exe: p4driver.cpp g ++ -o p4a p4driver.cpp MA, mi dice "separatore mancante". Sto usando TAB, ma me lo dice ancora. Qualche idea?
Befall

2
Per quanto ne so, quel messaggio di errore viene visualizzato solo se si dispone di spazi. Assicurati di non avere linee che iniziano con spazi (spazio + tab darà quell'errore). Questa è l'unica cosa che mi viene in mente ..
Brendan Long

Nota per i futuri editor: StackOverflow non può eseguire il rendering delle schede anche se le modifichi nella risposta, quindi per favore non provare a "correggere" la mia nota a riguardo.
Brendan Long,

35

Perché a tutti piace elencare i file sorgente? Un semplice comando find può occuparsene facilmente.

Ecco un esempio di un semplice C ++ Makefile. Rilascialo in una directory contenente .Cfile e quindi digita make...

appname := myapp

CXX := clang++
CXXFLAGS := -std=c++11

srcfiles := $(shell find . -name "*.C")
objects  := $(patsubst %.C, %.o, $(srcfiles))

all: $(appname)

$(appname): $(objects)
    $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(appname) $(objects) $(LDLIBS)

depend: .depend

.depend: $(srcfiles)
    rm -f ./.depend
    $(CXX) $(CXXFLAGS) -MM $^>>./.depend;

clean:
    rm -f $(objects)

dist-clean: clean
    rm -f *~ .depend

include .depend

2
Un motivo per non trovare automaticamente i file sorgente è che si possono avere target di build diversi che richiedono file diversi.
Hmijail piange le dimissioni il

Concordato @hmijail, così come i sottomoduli che contengono una tonnellata di fonti / intestazioni che non si desidera compilare / collegare ... e senza dubbio molte altre circostanze in cui la ricerca / l'uso esaustivi non sono adatti.
Ingegnere,

Perché utilizzare invece "shell find" e non "jolly"?
Nolan

1
@Nolan per trovare i file di origine in un albero di directory di origine
AlejandroVD

13

Hai avuto due opzioni.

Opzione 1: makefile più semplice = NO MAKEFILE.

Rinomina "a3driver.cpp" in "a3a.cpp", quindi nella riga di comando scrivi:

nmake a3a.exe

E questo è tutto. Se stai usando GNU Make, usa "make" o "gmake" o qualsiasi altra cosa.

Opzione 2: un makefile a 2 righe.

a3a.exe: a3driver.obj
    link /out:a3a.exe a3driver.obj

3
Questa sarebbe una risposta eccellente se non presupponesse così tante cose sui dettagli dell'ambiente del PO. Sì, sono su Windows, ma ciò non significa che lo stiano utilizzando nmake. La linkriga di comando sembra anche molto specifica per un compilatore particolare e dovrebbe almeno documentare quale.
triplo

6

Il tuo file Make avrà una o due regole di dipendenza in base alla compilazione e al collegamento con un singolo comando o con un comando per la compilazione e uno per il collegamento.

La dipendenza è un albero di regole che assomiglia a questo (si noti che il rientro deve essere un TAB):

main_target : source1 source2 etc
    command to build main_target from sources

source1 : dependents for source1
    command to build source1

Ci deve essere una riga vuota dopo i comandi per un obiettivo, e ci deve non essere una riga vuota prima i comandi. Il primo obiettivo nel makefile è l'obiettivo generale e altri obiettivi vengono creati solo se il primo obiettivo dipende da essi.

Quindi il tuo makefile sarà simile a questo.

a3a.exe : a3driver.obj 
    link /out:a3a.exe a3driver.obj

a3driver.obj : a3driver.cpp
    cc a3driver.cpp

6

Suggerisco (nota che il trattino è una TAB):

tool: tool.o file1.o file2.o
    $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@

o

LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)
tool: tool.o file1.o file2.o

Quest'ultimo suggerimento è leggermente migliore poiché riutilizza le regole implicite di GNU Make. Tuttavia, per funzionare, un file sorgente deve avere lo stesso nome dell'eseguibile finale (cioè: tool.ce tool).

Nota, non è necessario dichiarare le fonti. I file di oggetti intermedi vengono generati utilizzando la regola implicita. Di conseguenza, questo Makefilelavoro per C e C ++ (e anche per Fortran, ecc ...).

Si noti inoltre, per impostazione predefinita, Makefile utilizzare $(CC)come linker. $(CC)non funziona per il collegamento di file oggetto C ++. Modifichiamo LINK.osolo per questo. Se si desidera compilare il codice C, non è necessario forzare il LINK.ovalore.

Certo, puoi anche aggiungere i tuoi flag di compilation con variabili CFLAGSe aggiungere le tue librerie LDLIBS. Per esempio:

CFLAGS = -Wall
LDLIBS = -lm

Una nota a margine: se devi usare librerie esterne, suggerisco di usare pkg-config per impostare correttamente CFLAGSe LDLIBS:

CFLAGS += $(shell pkg-config --cflags libssl)
LDLIBS += $(shell pkg-config --libs libssl)

Il lettore attento noterà che questo Makefilenon viene ricostruito correttamente se si cambia un'intestazione. Aggiungi queste righe per risolvere il problema:

override CPPFLAGS += -MMD
include $(wildcard *.d)

-MMDconsente di creare file .d contenenti frammenti di Makefile relativi alle dipendenze delle intestazioni. La seconda riga li usa appena.

Di sicuro, un Makefile ben scritto dovrebbe anche includere cleane distcleanregole:

clean:
    $(RM) *.o *.d

distclean: clean
    $(RM) tool

Si noti, $(RM)è l'equivalente di rm -f, ma è una buona pratica non chiamarerm direttamente.

Anche la allregola è apprezzata. Per funzionare, dovrebbe essere la prima regola del tuo file:

all: tool

Puoi anche aggiungere una installregola:

PREFIX = /usr/local
install:
    install -m 755 tool $(DESTDIR)$(PREFIX)/bin

DESTDIRè vuoto per impostazione predefinita. L'utente può impostarlo per installare il programma su un sistema alternativo (obbligatorio per il processo di compilazione incrociata). Anche i gestori di pacchetti per la distribuzione multipla possono cambiare PREFIXper installare il pacchetto/usr .

Un'ultima parola: non posizionare i file di origine in sottodirectory. Se vuoi davvero farlo, tienilo Makefilenella directory principale e usa percorsi completi per identificare i tuoi file (es subdir/file.o.).

Quindi per riassumere, il tuo Makefile completo dovrebbe apparire come:

LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)
PREFIX = /usr/local
override CPPFLAGS += -MMD
include $(wildcard *.d)

all: tool
tool: tool.o file1.o file2.o
clean:
    $(RM) *.o *.d
distclean: clean
    $(RM) tool
install:
    install -m 755 tool $(DESTDIR)$(PREFIX)/bin

Verso la fine: non dovrebbero esserci linee vuote tra le regole? La risposta di John Knoeller lo ha affermato.
Peter Mortensen,

Nessuna delle implementazioni makeche conosco (GNU Make e BSD Make) necessita di linee vuote tra le regole. Tuttavia, esistono tonnellate di makeimplementazioni con i loro bug ^ Wspecificities.
Jérôme Pouiller,

5

Ho usato la risposta di Friedmud . Ci ho pensato per un po ', e sembra essere un buon modo per iniziare. Questa soluzione ha anche un metodo ben definito per aggiungere flag di compilatore. Ho risposto di nuovo, perché ho apportato modifiche per farlo funzionare nel mio ambiente, Ubuntu e g ++. Altri esempi di lavoro sono il miglior insegnante, a volte.

appname := myapp

CXX := g++
CXXFLAGS := -Wall -g

srcfiles := $(shell find . -maxdepth 1 -name "*.cpp")
objects  := $(patsubst %.cpp, %.o, $(srcfiles))

all: $(appname)

$(appname): $(objects)
    $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(appname) $(objects) $(LDLIBS)

depend: .depend

.depend: $(srcfiles)
    rm -f ./.depend
    $(CXX) $(CXXFLAGS) -MM $^>>./.depend;

clean:
    rm -f $(objects)

dist-clean: clean
    rm -f *~ .depend

include .depend

I makefile sembrano essere molto complessi. Ne stavo usando uno, ma stava generando un errore relativo al mancato collegamento nelle librerie g ++. Questa configurazione ha risolto il problema.

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.