makefile



  • neue Version (Danke an DrGreenthumb):

    TARGET   :=./programm
    CXXFLAGS :=-g -W -Wall -O2
    CXX      :=g++
    LIBS     :=
    EXT      :=cc
    
    SOURCES  :=$(wildcard *.$(EXT))
    OBJECTS  :=$(patsubst %.$(EXT),%.o,$(SOURCES))
    DEPS     :=$(patsubst %.$(EXT),%.dep,$(SOURCES))
    
    all: $(TARGET)
    
    $(TARGET): $(OBJECTS) $(DEPS)
      $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS)
    
    -include $(DEPS)
    
    %.o: %.cc
      $(CXX) $(CXXFLAGS) -c $< -o $@
    
    %.dep: %.cc
      $(CXX) $(CXXFLAGS) -MM $< -MT $(<:.cc=.o) > $@
    
    .PHONY: clean
    clean:
      rm -f $(TARGET) *.o *.dep
    

    Ich werde den Beitrag und den Rest der rudf FAQ bald mal auf Vordermann bringen

    ---------

    nachdem (er weiß schon wer) wochenlang nach alternativen für make gesucht hat und nachdem ich ihm sagte, daß make seinen bescheidenen wünschen durchaus genügen würde, und er sogar zu faul ist, die doku von make aufzuschlagen hier ein makefile für alle faulen.
    http://volkard.de/make/makefile

    TARGET:=test.exe
    OPTS:=-O3
    
    sources:=$(wildcard *.cpp)
    objects:=$(patsubst %.cpp,%.o,$(sources))
    deps:=$(patsubst %.cpp,%.dep,$(sources))
    
    $(TARGET):  $(objects) $(deps)
        $(CXX) $(OPTS) -o $(TARGET) $(objects)
    
    include $(sources:.cpp=.dep)
    
    %.o:    %.cpp
        $(CXX) -c $<
    
    %.dep: %.cpp
        $(CXX) -MM $< > $@
    
    .PHONY: clean
    clean:
        rm $(TARGET)
        rm *.o
        rm *.dep
    

    es nimmt sich aus dem aktuellen verzeichnis alle *.cpp und klopt sie zusammen in die ausführbare datei, die man in der ersten zeile spezifiziert hat. außerdem beachtet er, ob sich header-dateien veränbdert haben und compiliert gegebenenfalls die betroffenen cpps neu. und so wie make das halt macht. nur ohne, daß man das makefile ständig umbasteln muß, wenn mal ne datei dazu kommt.

    ja, es ist für linux. laßt euch von tet.exe nicht so erschrecken.



  • goil. wofür braucht man das ? und warum linux und exe ?



  • Original erstellt von <goil>:
    goil. wofür braucht man das ? und warum linux und exe ?

    aus kompatibilitätsgründen. weil win nur test.exe kann aber linux sogar test.exe kann. wenn du win nicht magst, kannste das .exe wegmachen.



  • verbesserungen (hab sie nicht geprüft):

    TARGET:=wpc59
    CXXFLAGS:=-O3
    
    sources:=$(wildcard *.cpp)
    objects:=$(patsubst %.cpp,%.o,$(sources))
    deps:=$(patsubst %.cpp,%.dep,$(sources))
    
    all: $(TARGET)
    
    $(TARGET):      $(objects) $(deps)
            $(CXX) $(CXXFLAGS) -o $(TARGET) $(objects)
    
    include $(sources:.cpp=.dep)
    
    %.o:    %.cpp
            $(CXX) $(CXXFLAGS) -c $<
    
    %.dep: %.cpp
            $(CXX) -MM $< > $@
    
    .PHONY: clean
    clean:
            rm $(TARGET)
            rm *.o
            rm *.dep
    


  • deine Makefile ist zwar toll, aber du vergisst, dass man wenn man Programme veröffentlicht damit rechnen muss, dass Leute die Programme auf den merkwürdigsten und ältesten System kompilieren wollen, deswegen gibt es ja configure und damit man das bequem und portable machen kann, nutzt man autoconf, was auf automake basiert, also schreibt man Makefiles kaum noch selber sondern kloppt sich lieber mit wilden M4 Macros und Shell Scripten in autoconf und dem merkwürdigem automake rum.



  • Find ich gut. Gefällt mir doch besser als mein AWK-Gewusel. 🙂

    Beim generieren der deps würde ich auch ein CXXFLAGS reintun, sonst hagelts Warnungen wegen eventueller zusätzlicher Include-Pfade. Ist wohl aber egal.

    Ich hoffe die Leute ziehen diesen simplen Makefile einem riesigen Autoconf/Automake-Gewurstel vor, weil falsch angewandt (und das ist leider sehr oft der Fall) schafft das mehr Probleme als es lösen sollte.



  • TARGET:=wpc59
    CXXFLAGS:=-O3
    
    sources:=$(wildcard *.cpp)
    objects:=$(patsubst %.cpp,%.o,$(sources))
    deps:=$(patsubst %.cpp,%.dep,$(sources))
    
    all: $(TARGET)
    
    $(TARGET):      $(objects) $(deps)
            $(CXX) $(CXXFLAGS) -o $(TARGET) $(objects)
    
    include $(sources:.cpp=.dep)
    
    %.o:    %.cpp
            $(CXX) $(CXXFLAGS) -c $<
    
    %.dep: %.cpp
            $(CXX) $(CXXFLAGS) -MM $< > $@
    
    .PHONY: clean
    clean:
            rm $(TARGET)
            rm *.o
            rm *.dep
    


  • Original erstellt von kingruedi:
    deine Makefile ist zwar toll, aber du vergisst, dass man wenn man Programme veröffentlicht damit rechnen muss...

    nee.
    und wenn jemand standard-c++ nehmen muß, um das gewurstele los zu werden. das makefile ist erstmal angemessen, weils unerhört einfach zu benutzen.



  • @Volkard
    Wenn du Zeit und Lust hast, könntest du dein makefile mal erklären?
    Ich habe mittlerweile drei Tutorials über make gelesen und muss gestehen, dass ich nach wie vor nicht kapiere wie diese Tool funktioniert. Bei mir endet das dann immer damit, dass ich mir vom Visual Studio die Dependencies generieren lasse und dann in mein makefile für jede einzelne cpp-Datei eine eigene "compilier mal"-Regel einbaue.

    Und noch eine Frage:
    Kann man in einem makefile auch sowas reinmachen wie:
    #ifdef WIN32
    compilier bitte zusätzlich auch noch diese cpp-Datei
    #endif



  • @Hume

    Original erstellt von volkard:
    **```
    TARGET:=wpc59 #Programmname (Default-Target und Ausgabename für den Compiler)
    CXXFLAGS:=-O3 #Optimierungen etc

    sources:=(wildcard *.cpp) #sources nicht den wert "*.cpp" sondern gleich die #Namen aller *.cpp-Dateien im Verzeichnis zuweisen. objects:=(patsubst %.cpp,%.o,$(sources)) #objects entspricht (sources), aber #.cpp wird durch .obj ersetzt deps:=(patsubst %.cpp,%.dep,$(sources)) #siehe oben

    all: $(TARGET) #bei "make" wird "make all" gemacht, was hier einem "make wpc59"
    #entspricht

    #target "wpc59" festlegen:
    #wpc59 hat als $(objects) und (deps) als Abhängigkeit (wird neu erstellt #wenn sich eine der in objects/ deps angeführten Dateien geändert hat #(CXX) ist der Standard-C++-Compiler, kompiliert werden die $(objects) mit
    #den Optionen aus $(CXXFLAGS) zu (TARGET)(TARGET) (TARGET): $(objects) $(deps)
    $(CXX) $(CXXFLAGS) -o $(TARGET) $(objects)

    include $(sources:.cpp=.dep) #include checkt hier nach Makefiles mit der Endung
    #.dep und ansonsten dem gleichen Dateinamen wie
    #eine der Dateien aus $(sources)

    %.o: %.cpp #alle .o Dateien (hängen von allen
    #.cpp-Dateien ab)
    $(CXX) $(CXXFLAGS) -c $< #jede .cpp-Datei zu .o kompilieren
    %.dep: %.cpp
    $(CXX) $(CXXFLAGS) -MM $< > $@ #für jede Datei ein eigenes Makefile
    #erstellen, Systemheader ausgenommen

    .PHONY: clean #verhindern dass eine Datei mit dem Namen "clean" nicht
    #make clean durcheinanderbringt, siehe
    # http://www.gnu.org/manual/make/html_node/make_37.html#SEC41
    clean:
    rm $(TARGET)
    rm *.o
    rm *.dep

    Ist sicher nicht alles so ganz optimal erklärt, aber für gute Erklärungen gibt es ja auch http://www.gnu.org/manual/make/ 😉

    kingruedi: Ich finde solche Standalone-Makefiles auch recht praktisch da man für Projekte die (nohc) nicht ausgeliefert werden sollen sondern nur für den Privatgebrauch gedacht sind, meistens autoconf und Konsorten nicht braucht (Dafür IMO zu fett und bringen keine nennenswerten Vorteile). 🙂

    edit: @Hume: Ich vergaß, wenn ich betriebssystem-spezifische Funktionen einbaue dann verwende ich normalerweise ein

    os=$(shell uname -s)
    ifeq ($(os), Linux)
            sources += linuxSpezifisches.cpp
    endif
    ifeq ($(os), nmansOsXP)
            sources += myStuff.cpp
    endif
    

    aber da Windows ja wohl kein uname haben dürfte wird das auf die Art wohl ein bisschen schwierig, mach uU einfach ein Win32-Target oder so. (Denk auch daran dass Du mit der Compileroption "-DmeinDefine" beim Kompilieren das Symbol "meinDefine" definieren kannst!)

    edit2: "1 Node pro Seite"-Anzeige des Manuals für "Phony-Targets" aktiviert.

    [ Dieser Beitrag wurde am 04.05.2003 um 01:38 Uhr von nman editiert. ]



  • Original erstellt von nman:
    aber da Windows ja wohl kein uname haben dürfte wird das auf die Art wohl ein bisschen schwierig

    Microsoft Windows XP [Version 5.1.2600]
    (C) Copyright 1985-2001 Microsoft Corp.
    
    C:\source>uname
    WindowsNT
    //klappt irgendwie
    
    C:\source>set
    COMPUTERNAME=VOLKARD-5H271OH
    OS=Windows_NT
    //die meisten rausgelöscht
    //mit OS läßt sich evtl was anstellen
    
    C:\source>which uname.exe
    c:\bin\uname.exe
    //ach deswegen isses da. teil der gnu utils für win
    


  • Original erstellt von HumeSikkins:
    @Volkard
    Wenn du Zeit und Lust hast, könntest du dein makefile mal erklären?

    ich werd keine besseren Worte finden, als die von http://www.gnu.org/manual/make/ , wo ich auch alles her hab. dazu noch den DJGPP (aber die echte GCC tuts auch) zum rumspielen und viel zeit.

    Und noch eine Frage:
    Kann man in einem makefile auch sowas reinmachen wie:
    #ifdef WIN32
    compilier bitte zusätzlich auch noch diese cpp-Datei
    #endif

    das widerspricht eigentlich meinen vorstellungen von nem einfacen makefile. gehen tut das. aber ibts keinen anderen weg? für was brauchste das denn?



  • hast in c++ eh zu entscheiden, welches system und so und das dann doppelt zu machen klingt net fein. zumal man makefiles nicht anfassen mag. schätze, du solltest hier lieber mal ne ./sys/win32/*.cpp includen oder noch nen besseren tick finden. oder sich ne schnittstelle zum makefile überlegen, damit das trotzdem unangetastet bleiben kann, obwohl man für verschiedene systeme manche sachen dazumachen mag.



  • @nman
    Danke fein. Ich muss wohl schlicht und einfach nochmal versuchen die Philosophie hinter make zu verstehen.

    für was brauchste das denn?

    Ich habe eine Klasse die auf Posix-kompatiblen Funktionionen aufbaut. Im Normalfall reichen also ein paar includes. Unter Win98 gibt es aber genau diese Posix-kompatiblen Funktionen nicht. Also verwende ich in diesem Fall selbst implementierte Funktionen mit der selben Schnittstelle. Die Definitionen dieser Funktionen müssen nun aber natürlich mit übersetzt und gelinkt werden. Also habe ich unter Win98 eine cpp-Datei mehr.

    [ Dieser Beitrag wurde am 04.05.2003 um 11:16 Uhr von HumeSikkins editiert. ]



  • Original erstellt von HumeSikkins:
    **Ich habe eine Klasse die auf Posix-kompatiblen Funktionionen aufbaut. Im Normalfall reichen also ein paar includes. Unter Win98 gibt es aber genau diese Posix-kompatiblen Funktionen nicht. Also verwende ich in diesem Fall selbst implementierte Funktionen mit der selben Schnittstelle. Die Definitionen dieser Funktionen müssen nun aber natürlich mit übersetzt und gelinkt werden. Also habe ich unter Win98 eine cpp-Datei mehr.
    **

    schreibe noch ein header und cpp,
    in normal fall includet sie die postfix header, unter win98 includet sie deinen header und in die cpp datei beinhaltet deinen code

    dann arbeites du mit den gleichen header und das makefile ist immer gleich



  • schreibe noch ein header und cpp

    Genau das habe ich gemacht. Habe jetzt dirstream.h, dirstreamw32.h und dirstreamw32.cpp.

    in normal fall includet sie die postfix header

    Genau. dirstream.h macht sowas:

    #ifdef HAT_POSIX_KRAM
    #include <dirent.h>
    #include <sys/stat.h>
    #else
    #include "dirstreamw32.h"
    #endif
    

    die cpp datei beinhaltet deinen code

    Richtig. Die dirstreamw32.cpp beinhaltet die Definitonen der Funktionen wir opendir, readdir usw.

    dann arbeites du mit den gleichen header und das makefile ist immer gleich

    So. Und hier kann ich dir nicht mehr folgen. Ich arbeite in der tat immer mit dem gleichen Header. User müssen immer nur dirstream.h inkludieren. Das makefile kann meiner Meinung nach aber nicht gleich bleiben, da es unter Win98 noch die dirstreamw32.cpp berücksichtigen muss.

    Was übersehe ich?



  • dirstreamw32.cpp

    #ifdef WIN32
    //dein code
    #else
    //nix
    #endif
    

    auch unter unix wird dann die dirstream32.cpp gelinkt, blos sie ist leer



  • Oha. So einfach kann es sein 🙂
    Danke fein.



  • und wenn jemand standard-c++ nehmen muß, um das gewurstele los zu werden. das makefile ist erstmal angemessen, weils unerhört einfach zu benutzen.

    ja klar, zum testen des Projekts etc. ist das natürlich gut, ich schreib mir am Anfang des Projekts auch idr. erst eine Makefile per Hand (vorallem da ich automake nicht mag)

    das widerspricht eigentlich meinen vorstellungen von nem einfacen makefile. gehen tut das. aber ibts keinen anderen weg? für was brauchste das denn?

    jo, einfach ist das nicht mehr aber nötig in der Praxis und dafür nimmt man ja auch eigentlich ein configure Script aber langsam geht die Mode dahin, dass man alles von Make bearbeiten lässt, ist eh viel praktischer.

    wobei in Humes Situation eh kein autoconf noch Makefile Tricks mit uname helfen, da Windows nicht POSIX kompatibel ist und man auch nicht vom User erwarten kann, dass der Cygwin oä. installiert hat



  • [ Dieser Beitrag wurde am 07.05.2003 um 04:10 Uhr von volkard editiert. ]


Anmelden zum Antworten