Funktionen auslagern, Makefile schreiben



  • Hi,

    ich möchte einige Funktionen aus meiner Datei auslagern.

    1. Wie und was muss ich inkludieren, damit ich auf die Funktionen zugreifen kann?
    2. Mein Makefile sieht momentan so aus:

    # Makefile
    
    CFLAGS+= -v -I/usr/include
    LDFLAGS+= -L/usr/lib -l xml2
    
    parseXmlDoc: parseXmlDoc.cc
    	$(CC) $(CFLAGS) $(LDFLAGS) parseXmlDoc.cc -o parseXmlDoc
    

    Wie muss ich das erweitern, damit ich schlussendlich alles beisammen hab?

    mfg chuqa



  • Ich hoffe ich habe deine Frage nicht falsch verstanden. Hier ein kleines Beispiel... Angenommen du hast folgenden Quelltext

    #include <iostream>
    using namespace std;
    
    void f()
    {
      cout << "Kein langweiliger Standardspruch!\n";
    }
    
    int main()
    {
      f();
    }
    

    Nun willst du die Funktion f separieren...

    // f.h
    #ifndef __F_H__
    #define __F_H__
    
    /*
     * Deklaration: Prototyp der Funktion f
     */
    
    void f();
    
    #endif
    
    // f.cpp
    #include "f.h"
    
    #include <iostream>
    using namespace std;
    
    /*
     * Implementierung der Funktion f
     */
    
    void f()
    {
      cout << "Kein langweiliger Standardspruch!\n";
    }
    
    // main.cpp
    #include "f.h"
    
    int main()
    {
      f();
    }
    

    Das Makefile könnte dann wie folgt aussehen:

    all : test

    test : main.o f.o
    g++ main.o f.o -o test

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

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

    clean :
    rm -f *~
    rm -f *.o

    rm : clean
    rm -f test



  • Bei so einem einfachen Fall kann das Makefile noch einfacher sein:

    CC=$(CXX)
    main: main.o f.o
    

    Das geht, da make bereits einige Standardtargets kennt. So weiß make, wie er aus einer *.cpp-Datei eine *.o-Datei macht.

    Wenn jetzt make aufgerufen wird, versucht er, main zu bauen. Er benötigt dazu main.o. Das gibt es nicht. Aber er findet eine main.cpp, aus der er eine erzeugen kann. Genauso verfährt er mit f.o. Auch weiß er, wie man Programme linkt. Das tut er leider mit $CC, welches den c-compiler darstellt. Das funktioniert nicht mit c++ und daher die 1. Zeile, die $CC neu definiert.

    CXXFLAGS und LDFLAGS können zusätzlich gesetzt werden. -I/usr/include und -L/usr/lib sind aber unnötig, da diese zu den Standardflags des compilers gehören. Willst Du libxml2 verwenden, reicht ein:

    LDFLAGS=-lxml2
    


  • Du hast Recht. Aber auf soetwas verlasse ich mich ungern, da es bei etwas älteren Versionen von make nicht Gang und Gebe war.

    Wenn man noch zusätzliche Parameter angeben möchte muss man zwangsläufig so vorgehen...

    QTINC = -I/usr/include/qt3
    KDEINC = -I/usr/include/kde
    QTLIB = -L/usr/lib
    KDELIB = -L/usr/lib
    QTBIN = /usr/share/qt3/bin

    all : ksimplebrowser

    ksimplebrowser : main.o ksimplebrowser.o
    g++ -O3 $(QTLIB) $(KDELIB) -lkdecore -lkdeui -lqt-mt -lkhtml \
    main.o ksimplebrowser.o -o ksimplebrowser

    main.o : main.cpp
    g++ -c -O3 $(QTINC) $(KDEINC) main.cpp

    ksimplebrowser.o : ksimplebrowser.cpp ksimplebrowser.moc
    g++ -c -O3 $(QTINC) $(KDEINC) ksimplebrowser.cpp

    ksimplebrowser.moc : ksimplebrowser.h
    $(QTBIN)/moc ksimplebrowser.h > ksimplebrowser.moc

    /Edit: Wo sind die Tabs geblieben? 🙂



  • Gut danke erstmal,

    ich schau mir das morgen dann an,
    für heute habe ich erstmal Feierabend 😉

    mfg chuqa



  • Ich würde solche definitiven Aussagen, wie "zwangsläufig" lieber nicht verwenden. Schau mal da:

    QTINC = -I/usr/include/qt3 
    KDEINC = -I/usr/include/kde 
    QTLIB = -L/usr/lib 
    KDELIB = -L/usr/lib 
    QTBIN = /usr/share/qt3/bin
    LDFLAGS = $(QTLIB) $(KDELIB) -lkdecore -lkdeui -lqt-mt -lkhtml
    CXXFLAGS = -O3 $(QTINC) $(KDEINC)
    
    all : ksimplebrowser 
    .moc.h:
        $(QTBIN)/moc $^ > $@
    
    ksimplebrowser : main.o ksimplebrowser.o 
    ksimplebrowser.o : ksimplebrowser.cpp ksimplebrowser.h
    

    (ungetestet)

    Das hat ausserdem den Vorteil, daß ich nicht explizit g++ spezifiziere, sondern automatisch der standard-c++-compiler genommen wird. Nicht jedes System basiert auf gcc/g++.

    Hilfreich wäre hier auch die Option -M vom gcc. Der compiliert nicht, sondern gibt einfach alle Abhängigkeiten im Makefile-Format aus.

    Das -L/usr/lib kann man sich auch sparen, da diese bereits im gcc eincompiliert sind.

    -O3 für den Linker ist ausserdem unnötig.

    Ich habe jetzt mal mit Leerzeichen eingerückt. Im richtigen Makefile müssen es natürlich Tabs sein.

    Für komplexere Projekte empfehle ich autoconf und automake (auch autohell genannt;) ) einsetzen. Kompliziert, aber das Ergebnis ist wirklich brauchbar.



  • So ich glaube ich habe es jetzt.

    So siehts aus und funktioniert:

    CFLAGS+= -v -I/usr/include
    LDFLAGS+= -L/usr/lib -l xml2
    OBJECTS = getParamOptions.o
    
    parseXmlDoc: parseXmlDoc.cc $(OBJECTS) Makefile glob.h
    	$(CC) $(CFLAGS) $(LDFLAGS) parseXmlDoc.cc -o parseXmlDoc $(OBJECTS)
    
    getParamOptions.o: getParamOptions.cc
    	$(CC) -c $(CFLAGS) getParamOptions.cc
    

    Ich weiß die Flags kann man noch ändern bzw. weglassen, und die OBJECTS kann man bestimmt auch noch um Makefile und glob.h ergänzen und sich damit das unten sparen (?), aber es funktioniert zumindestens und tut seine arbeit ;).
    Ich danke euch.

    mfg chuqa



  • @ tntnet:

    Gut überzeugt. 🙂 Aber es ist schon vielmehr eine Geschmackssache. Wenn man bedenkt das make nur ein Programm ist das das Programmieren vereinfachen soll; make ist ja schließlich keine Programmiersprache. 😉


Anmelden zum Antworten