C++-Projekt kompilieren?



  • Hallo,

    in unserem Blockkurs C++ sollen wir ein Projekt erstellen, in dem wir in einer Headerdatei eine Funktion deklarieren, sie in einer Sourcefile definieren und in einer anderen Sourcefile benutzen. Visual Studio und andere machen das automatisch, aber wie geht das mit dem gcc? Die müssen ja am Ende irgendwie zusammengelinkt werden, um zu einer ausführbaren Datei gemacht zu werden.

    Kann mir jemand helfen?


  • Mod

    Wenn man das von Hand macht, dann geht das ungefähr so:

    Man hat eine Hauptprogrammdatei, nennen wir sie mal main.cc

    Dann hat man mehrere Sourcedateien, in denen die Funktionen definiert sind (das heißt richtig mit vollständigem Code), nehmen wir mal an es sind drei mit den Namen 1.cc, 2.cc, 3.cc. Zu diesen Dateien gehören Headerdateien, die man sinnigerweise (muss man aber nicht) genauso nennt wie die zugehörige Sourcedatei, also 1.h, 2.h, 3.h. In diesen Dateien stehen nur die Funktionsdeklarationen (also nur der Kopf der Funktion). Diese .h Dateien sind es, die man mittels #include an den Stellen einbindet, an denen man sie braucht. Die .h Dateien müssen vom Compiler gefunden werden können, gcc sucht standardmäsig im aktuellen Verzeichnis und in einigen Systempfaden. Mittels der Kommandozeilenoption -I/pfad/ kann man weitere Pfade angeben.

    Wenn man jetzt kompiliert und nur wenige Dateien hat, ist erstmal die einfachste Methode dies:

    g++ main.cc 1.cc 2.cc 3.cc -o wie_mein_programm_heißen_soll weitere_optionen
    

    Die Reihenfolge ist dabei egal.

    Das wird aber schnell unübersichtlich und hat den Nachteil, dass immer alles neu kompiliert werden muss. Die semiautomatische Variante ist folgendes:
    Man kompiliert die einzelnen Dateien zu Objektdateien:

    g++ -c dateiname.cc weitere_optionen
    

    Dies erzeugt eine Objektdatei dateiname.o mit dem kompilierten aber noch nicht gelinkten Code. Das letztendliche Programm erstellt man dann mittels

    g++ main.cc 1.o 2.o 3.o -o wie_mein_programm_heißen_soll weitere_optionen
    

    Das ist aber recht aufwändig, weil man immer wieder aufpassen muss, welche Datei von welcher abhängt und gegebenenfalls neu kompiliert werden muss. Deswegen solltest du diese semiautomatische Variante besser nicht wählen, sondern bei der zuerst gezeigten Variante bleiben. Wenn es dann doch zu viel wird für die erste Variante gibt es dann die vollautomatische Variante mittels Makefiles, die die Vorteile der zweiten Variante mit der Einfachheit der ersten Variante verbindet. Dies ist jedoch ein komplexes Kapitel, dass du dir lieber mal in einem Buch oder im Netz durchliest, denn der Platz reicht hier nicht, um dies zu erklären. Außerdem sollte man vorher etwas Erfahrung mit den anderen Varianten gesammelt haben, damit man versteht, was das überhaupt soll.



  • Hallo SeppJ,

    vielen vielen Dank. Die makefiles-Geschichte kenne ich bereits. Musste in meinem Praktikum auch alles über makefiles zum laufen bringen (nicht selbst schreiben sondern nur über make, make clean usw. alles regeln). Aber dadurch, dass ich es eben immer automatisch machen ließ, wusste ich nicht, wie man es manuell macht. Deine Antwort ist sehr ausführlich und verständlich und hat auch sofort funktioniert.

    Vielen Dank 👍



  • Ich hab dann nochmal kurz eine Frage. Ich hab das gleiche, was ich mit Funktionen machen wollte, einmal kurz mit Variablen ausprobiert:

    //teil2.cpp
    x2 = 20;
    
    //Funktionsdefinition
    int maximum(int a, int b){
    	if(a>b) return a;
    	else return b;
    }
    
    //variable.hpp
    int x2;
    
    //maximum.hpp
    int maximum(int a, int b);
    

    Und die main:

    #include <iostream>
    #include "maximum.hpp"
    #include "variable.hpp"
    
    using namespace std;
    
    int main(){
    
    	int x,y,max, eingabe;
    
    	cout<<"Geben Sie die erste Zahl ein: ";
    	cin>>x;
    	cout<<"\nGeben Sie die zweite Zahl ein: ";
    	cin>>y;
    	max = maximum(x,y);
    	cout<<"Was ist das Maximum Ihrer beiden Zahlen :";
    	cin>>eingabe;
    	if(eingabe == max) cout<<"Sie haben Recht. Das Maximum der beiden Zahlen ist :"<<max<<endl;
    	else cout<<"Das stimmt nicht. Das Maximum der beiden Zahlen ist :"<<max<<endl;
    
    	cout<<"x2: "<<x2<<endl;
    
    	return 0;
    }
    

    Ok, das Programm ist seltsam 😃 , aber ich will ja rumspielen. So, erstens wollte ich fragen, ob das mit der Variablen so korrekt ist, also in seinem Header deklariert und in der Sourcedatei teil2.cpp definiert. Als ich im Header int x2; und in der entsprechenden Sourcefile int x2 = 20; eingegeben hatte, bekam ich ne Fehlermeldung(Warum?). Nun hab ich das so wie oben im Codeblock gemacht und bekomme folgende Meldung:

    ...$ g++ main.cpp teil2.cpp -o projekt
    teil2.cpp:2: Fehler: expected constructor, destructor, or type conversion before »=« token

    Was bedeutet das?


  • Mod

    teil2.cpp kennt bei dir variable.hpp nicht. Da fehlt noch ein #include"variable.hpp"



  • Außerdem sollten Variablen nicht in Header-Dateien definiert werden, sondern nur mittels "extern" deklariert werden, d.h.:

    // Variable.hpp
    extern int x2;
    
    // Variable.cpp
    int x2 = 20;
    

    Das Stichwort dafür lautet: ODR (one definition rule).

    Bei Funktionen wird eine Funktionsdeklaration automatisch als "extern" angesehen, daher entfällt es dort. Aber genauso wie für Funktionen darf es für Variablen nur genau eine Definition geben.
    Würdest du "Variable.hpp" in zwei verschiedenen Source-Dateien einbinden (#include), so hättest du sonst zwei verschiedene Variablen definiert -> und der Linker würde dir dann einen Fehler generieren!


Log in to reply