makefile updated header plötzlich nicht mehr



  • Hi,

    ich weiß nicht, warum aber obwohl ich im makefile nichts geändert habe, updated es scheinbar die .h-Datei nicht mehr.

    Makefile:

    CXX = g++			
    CXXFLAGS = -g -Wall -fPIC -O3 		
    DEPS = *.h	
    
    LD = g++
    LDFLAGS = -g 		
    
    SOURCES=$(wildcard *.cpp)
    
    OBJECTS=$(SOURCES:.cpp=.o)	
    EXECUTABLE=matching		
    
    CXXFLAGS      += $(shell root-config --cflags)
    LIBS           = $(shell root-config --libs)	
    NGLIBS         = $(shell root-config --glibs)
    GLIBS          = $(filter-out -lNew, $(NGLIBS))
    
    .SUFFIXES: .cpp
    
    # ================================================================================
    all: $(SOURCES) $(EXECUTABLE)	 											
    
    $(EXECUTABLE): $(OBJECTS) $(DEPS)										
    	$(CXX) $(CXXFLAGS) $(OBJECTS) -o $@ $(LIBS) 	
    
    .cpp.o:	
    	$(CXX) $(CXXFLAGS) -c $< -o $@ -I$(PWD)
    
    clean:
    	rm -f $(EXECUTABLE)  *.o
    

    matching.cpp hängt von APD.h und APD.cpp ab. Die ganze Zeit funktionierte es und ich habe überhaupt locker eine halbe Stunde benötigt, um zu merken, dass das Kompilieren nicht funktioniert, da die .h-Datei gar nicht aktualisiert wird.
    Vermute ich jedenfalls, denn wenn ich die main.cpp/matching.cpp kompilieren möchte, erhalte ich den error, dass eine Funktion bereits in APD.h definiert wäre und zwar in Zeile 67, obwohl die Datei seit einer halben Stunde nur aus 59 Zeilen besteht. Dass es vorher funktionierte, kann ja auch irgendwie kein Zufall sein ?!

    Kompilierungsfehler:

    g++ -g -Wall -fPIC -O3 -pthread -std=c++11 -Wno-deprecated-declarations -m64 -I/home/user/root/include -c matching.cpp -o matching.o -I/home/user/analysis/APDs/ #-I
    g++ -g -Wall -fPIC -O3 -pthread -std=c++11 -Wno-deprecated-declarations -m64 -I/home/user/root/include APD.o matching.o -o matching -L/home/user/root/lib -lCore -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lMultiProc -pthread -lm -ldl -rdynamic
    matching.o: In function operator<< <std::char_traits<char> >': /home/user/analysis/APDs/matching.cpp:31: multiple definition ofAPD::extract(std::ostream&) const'
    APD.o:/home/user/analysis/APDs/APD.h:59: first defined here
    matching.o: In function operator<<(std::ostream&, APD const&)': /home/user/analysis/APDs/matching.cpp:39: multiple definition ofoperator<<(std::ostream&, APD const&)'
    APD.o:/home/user/analysis/APDs/APD.h:67: first defined here
    collect2: error: ld returned 1 exit status
    make: *** [matching] Error 1

    In matching.cpp steht:

    #include "APD.h"

    In APD.h steht:

    #ifndef APD_H
    #define APD_H
    (...)
    #endif

    In APD.cpp steht:

    #include "APD.h"

    Die Dateien befinden sich tatsächlich im richtigen Pfad. Habt ihr eine Idee ?


  • Mod

    Da steht ja auch nirgendwo, dass die apd.o von apd.h abhinge, sondern nur, dass die Executable von apd.h abhinge. Und genau die erstellt er folglich neu. Mit dem alten apd.o. Denn die Abhängigkeiten der apd.o sind hier keine, folglich sieht sie immer aktuell aus, sofern sie existiert.



  • Ah, ok, vielen Dank!

    Dass er zuvor das passend kompilierte war dann stets quasi eher Zufall 😮



  • editedit:

    Habe jetzt:

    CXX = g++
    CXXFLAGS = -g -Wall -fPIC -O3

    LD = g++
    LDFLAGS = -g

    SOURCES=$(wildcard *.cpp)

    OBJECTS=(SOURCES:.cpp=.o)HEADERS=(SOURCES:.cpp=.o) HEADERS=(SOURCES:.cpp=.h)
    EXECUTABLE=matching

    CXXFLAGS += $(shell root-config --cflags)
    LIBS = $(shell root-config --libs)
    NGLIBS = $(shell root-config --glibs)
    GLIBS = $(filter-out -lNew, $(NGLIBS))

    .SUFFIXES: .cpp

    # ================================================================================
    all: $(SOURCES) $(EXECUTABLE)

    $(EXECUTABLE): (OBJECTS)(OBJECTS) (CXX) $(CXXFLAGS) $(OBJECTS) -o $@ $(LIBS)

    .cpp.o: $(SOURCES) (HEADERS)(HEADERS) (CXX) $(CXXFLAGS) -c $< -o @I@ -I(PWD)

    clean:
    rm -f $(EXECUTABLE) *.o

    Zwar erhalte ich keine Fehlermeldung mehr aber er erkennt nach wie vor nicht, wenn die .h-Datei geändert wird.


  • Mod

    .cpp.o: Wann sollte dieses Ziel je gebaut werden?

    Aber bevor du groß weiter tüftelst, sollte ich einschreiten und sagen, dass du momentan auf dem Holzweg bist. Du scheinst derzeit ein Makefile schreiben zu wollen, bei der sämtliche Objekte sowohl von sämtlichen Sourcen als auch von sämtlichen Headern abhängen. Das würde bedeuten, dass jedwede Änderung irgendwo einen kompletten Rebuild auslösen würde, was irgendwie gegen den Sinn von Makefiles geht.

    Üblich wäre, dass ein Objekt nur von seiner Source abhängt. Das ist sogar dermaßen üblich, dass man praktisch gar nichts mehr angeben muss, sofern man keine speziellen Compileroptionen braucht. Mit den Headern ist es schwieriger, weil nicht klar ist, welches Objekt von welchem Header abhängt. Eine Liste solcher Abhängigkeiten wird wohl kaum jemand von Hand pflegen wollen. Man kann entweder den faulen Weg wählen und sagen, dass Änderungen an Headern sowieso sehr selten sein sollten (in C vielleicht gerechtfertigt, in C++ weniger) und pauschal alles neu compilieren, wenn sich ein Header ändert; oder man kann automatisch die Abhängigkeiten erzeugen lassen, zum Beispiel kann der GCC automatisch eine Liste aller Abhängigkeiten eines Quellcodes erzeugen (und das kann man dann auch vor dem Deployment machen, man ist also nicht darauf angewiesen, dass es auf dem Zielsystem GCC gibt).



  • danke, kann die Antwort nur leider nicht ganz einordnen.

    Letztlich habe ich akut eine main.cpp, die von einer .h- und einer dazugehörigen .cpp-Datei abhängt.
    Was ich bezwecken wollte, war, weitestgehend zu vermeiden, dass ich explizite Dateinamen angebe, sodass ich das makefile quasi unter Änderung des target-Namens prinizpiell universell einsetzen kann. Aktuelle bin ich dabei den Header zu erstellen, deshalb kommt es da noch recht häufig zu Änderungen 🙂

    Wenn ich es richtig verstanden habe, müsste ich quasi also explizit die Abhängigkeiten angeben ?


  • Mod

    Progressive schrieb:

    Letztlich habe ich akut eine main.cpp, die von einer .h- und einer dazugehörigen .cpp-Datei abhängt.

    Ich bezweifle, dass eine main.cpp von einem Header, noch von einer anderen .cpp-Datei abhängt. Viel eher wird wohl eine Objektdatei erzeugt werden sollen, die von main.cpp und main.h abhängt. Diese kleinen Ungenauigkeiten machen dir dein momentanes Makefile kaputt.

    Was ich bezwecken wollte, war, weitestgehend zu vermeiden, dass ich explizite Dateinamen angebe, sodass ich das makefile quasi unter Änderung des target-Namens prinizpiell universell einsetzen kann. Aktuelle bin ich dabei den Header zu erstellen, deshalb kommt es da noch recht häufig zu Änderungen 🙂

    Make ist eigentlich recht gut da drin, diese Beziehungen automatisch herzustellen. Dafür gibt es zahlreiche automatische Regeln (->Handbuch), das heißt, du musst bei einfachen Projekten praktisch gar nichts mehr schreiben außer einer Liste der Sourcen.

    Problematisch sind Abhängigkeiten von Headern. Diese können und werden durch einfache automatische Regeln nicht beachtet werden. Falls du wirklich Änderungen in Headern machst, wird dir also nichts anderes übrig bleiben außer einem der in der vorherigen Antwort vorgeschlagenen Verfahren, namentlich:
    -Pauschal sagen, dass bei einer Änderung an einem Header alles neu compiliert werden soll
    -Die Header-Abhängigkeiten von Hand pflegen
    -Die Header-Abhängigkeiten automatisiert pflegen



  • SeppJ schrieb:

    Progressive schrieb:

    Letztlich habe ich akut eine main.cpp, die von einer .h- und einer dazugehörigen .cpp-Datei abhängt.

    Ich bezweifle, dass eine main.cpp von einem Header, noch von einer anderen .cpp-Datei abhängt. Viel eher wird wohl eine Objektdatei erzeugt werden sollen, die von main.cpp und main.h abhängt.

    Ich glaube, das wollte ich eigentlich sagen 😃
    Also in main.cpp wird eine .h und eine .cpp-Datei eingefügt. Letztlich.

    SeppJ schrieb:

    Diese kleinen Ungenauigkeiten machen dir dein momentanes Makefile kaputt.

    Was ich bezwecken wollte, war, weitestgehend zu vermeiden, dass ich explizite Dateinamen angebe, sodass ich das makefile quasi unter Änderung des target-Namens prinizpiell universell einsetzen kann. Aktuelle bin ich dabei den Header zu erstellen, deshalb kommt es da noch recht häufig zu Änderungen 🙂

    Make ist eigentlich recht gut da drin, diese Beziehungen automatisch herzustellen. Dafür gibt es zahlreiche automatische Regeln (->Handbuch), das heißt, du musst bei einfachen Projekten praktisch gar nichts mehr schreiben außer einer Liste der Sourcen.

    Problematisch sind Abhängigkeiten von Headern. Diese können und werden durch einfache automatische Regeln nicht beachtet werden. Falls du wirklich Änderungen in Headern machst, wird dir also nichts anderes übrig bleiben außer einem der in der vorherigen Antwort vorgeschlagenen Verfahren, namentlich:
    -Pauschal sagen, dass bei einer Änderung an einem Header alles neu compiliert werden soll
    -Die Header-Abhängigkeiten von Hand pflegen
    -Die Header-Abhängigkeiten automatisiert pflegen

    Mh, ok. Ich verschiebe den Umstand mal auf später, wenn es an die Feinheiten geht. Bis der Header final ist, cleane ich einfach vorher immer.
    So umfangreich ist es aktuell nicht, Optimierungen müssen warten 🕶


  • Mod

    Dann lies dir aber unbedingt mal die ganzen automatischen regeln durch. Sehr praktisch. Dein Makefile wird dann außer einer Liste aller Sourcen nichts mehr enthalten.

    Außerdem, da du es nicht benutzt hast: .phony-Targets.



  • Danke, werde es mir merken!
    Auf phony targets bin ich auch schon gestoßen, hatte aber, da ich nach anderen Sachen Ausschau hielt, nicht weiter den Bezug gesehen 🙂
    Werde es mir dann aber auch mal angucken!


Anmelden zum Antworten