[C] Getrenntes Kompilieren von Quelldateien

Cemil

Erfahrenes Mitglied
Hi,
ich möchte meine Quelldateien einzeln kompilieren und habe hierfür ein neues Projekt angelegt und alle diese Dateien dort eingefügt.

Hier die Dateien (MS WINDOWS + Dev-C++ v. 4.9.8.7 Beta):

/* main.c */
#include <stdio.h>

extern modul1(void);
extern modul2(void);

int main()
{
modul1();
modul2();
system("pause");
return 0;
}

---

/* modul1.c */
void modul1()
{
printf("Ich bin das Modul 1\n");
}

---

/* modul2.c */
void modul2()
{
printf("Ich bin Modul 2\n");
}

Ich habe die main-Datei kompiliert und habe danach drei Objektdateien (main.o, modul1.o, modul2.o) erhalten. Aber sobald ich die drei Objektdateien zu einer ausführbaren Datei linken möchte, klappt's nicht.

Was mache ich falsch?

Für eure Antworten bedanke ich mich im voraus.

Greetings...
 

Daniel Toplak

Erfahrenes Mitglied
Ich habe die main-Datei kompiliert und habe danach drei Objektdateien (main.o, modul1.o, modul2.o) erhalten. Aber sobald ich die drei Objektdateien zu einer ausführbaren Datei linken möchte, klappt's nicht.
Welche Fehlermeldungen erhältst du denn beim Linken?

Gruß Homer
 

Cemil

Erfahrenes Mitglied
Ich erhalte keine Fehlermeldungen. Ein leeres DOS-Fenster geht auf und das war's dann schon. Die modul1 und modul2 Dateien werden nicht angezeigt.

Grüsse...
 

Cemil

Erfahrenes Mitglied
Na wenigstens erhalte ich jetzt eine Fehlermeldung:

[Linker error] undefined reference to `modul1'
[Linker error] undefined reference to `modul2'

Hier nochmals die Quelldateien (geändert):

/* main.c */
#include <stdio.h>
#include <stdlib.h> /* für system(); */

extern void modul1(void); /* Fett = vergessen */
extern void modul2(void);

int main()
{
modul1();
modul2();
system("pause");
return 0;
}

---

/* modul1.c */
#include <stdio.h>

extern void modul1(void)
{
printf("Ich bin das Modul 1\n");
}

---

/* modul2.c */
#include <stdio.h>

extern void modul2(void)
{
printf("Ich bin Modul 2\n");
}

Grüsse
 

Kachelator

Peter Jerz
Code:
/* modul1.c */
#include <stdio.h>

extern void modul1(void) // <- hier kein extern!
{
  printf("Ich bin das Modul 1\n");
}
Lass das "extern" in modul1.c und modul2.c weg. Der Code befindet sich schliesslich in dieser Datei, und nicht ausserhalb, also "extern".
 

Cemil

Erfahrenes Mitglied
@Kachelator:
Hab ich gemacht. Die Dateien werden kompiliert und gelinkt, aber ich erhalte danach nur ein leeres DOS-Fenster (C:\WINDOWS\system32\cmd.exe). Es entsteht danach auch kein Linker-Fehler, denn sonst würde das Programm die cmd.exe nicht ausführen. Hab das Programm einem Kolleggen gepostet und bei Ihm lief das ganze einwandfrei (hat mit Dev-C++ getestet).

Ich kenne Dev-C++ nicht sehr gut. Müsste ich z. B. bei Projekt/Projekt Optionen irgendwelche Parameter (Compiler, Linker oder weiss ich was) einfügen?

Hatte vielleicht irgendjemand die gleichen Probleme mit Dev-C++?

Bin für jede Hilfe sehr dankbar.

Grüsse
 
Zuletzt bearbeitet:

Cemil

Erfahrenes Mitglied
Ich habs endlich. Bei Projekt/Projekt Optionen/Allgemein war als Typ Win32 GUI angegeben. Das war natürlich falsch und muss dementsprechend zu Win32 Konsole geändert werden.

Grüsse
 

Daniel Toplak

Erfahrenes Mitglied
Ein kleiner Tipp hier am Rande:
Wenn man in C oder C++ anfängt zum Programmieren, dann sollte man zunächst mal auf eine IDE (Integrated Development Environment) verzichten, und stattdessen mal einfach die Sourcefiles mit einem normalen Editor (Notepad) schreiben und dann mit einem Compiler (z.B. gcc) auf der Konsole übersetzen und zusammenlinken. Denn nur so versteht man die Logik von mehreren Dateien und ihren Abhängigkeiten. Was einem später bei Projekten die aus 10, 20, 50 und mehr Dateien bestehen zu gute kommt.

Gruß Homer
 

Norbert_D

Grünschnabel
Guten Tag,

die Fragen hier sind zwar schon über 15 Jahre alt, aber wenn man aktuell eine Lösung für das einzelne Kompilieren und zusammen linken von C-Programmen sucht, kommt man neben einigen voneinander abgeschriebenen Beispielen eben auch hier in dieses Forum. Die ausgeführten Beispiele sind ja zwar eigentlich ausreichend, geben aber doch nicht die richtigen und notwendigen Hinweise dazu, was denn wirklich zu beachten ist.
Ok, wenn man sich damit schon lange beschäftigt hat, ist das sicherlich alles klar und rund und ganz logisch und selbstverständlich, aber wenn eben nicht?!

1. Bezeichnung der einzelnen Dateien:

Gut, die Dateien haben ihre eigenen Namen mit dem Suffix c (oder cpp) und werden in der Hauptfunktion als extern Funktionen ohne Suffix aufgerufen. Diese "Unterfunktion" hat dann aber kein "main" mehr, sondern nochmals anstatt "main" ihren eigenen Funktionsnamen. Ist zwar nachträglich verständlich, aber eben nicht so gleich nachvollziehbar.
Auch ist in dem Beispiel unglücklich gewählt, daß die Hauptfunktion die Datei Bezeichnung „main.c“ hat. So wird das doch alles ziemlich unklar.

2,. Verlinken der Dateien:
Für das Kompilieren der Dateien ruf man in de Konsole

gcc -c Haupt.c modul1.c modul2.c
(Ich habe hier zum besseren Verständnis main.c durch Haupt.c ersetzt und so was wie -Wall weggelassen.)

auf
Ergebnis sind dann kompilierte Dateien Haupt.o modul1.o modul2.o mit dem Suffix .o

Und verlinkt man eben

gcc -o Haupt.o modul1.o modul2.o

Ist doch logisch, beim Kompilieren entsprechend dem Suffix -c und nun mal beim linken entsprechend dem Suffix halt -o

Doch blöderweise bedeutet der Schalter -o, daß der Name der verlinkten Datei eben der Name der Bezeichnung nach dem -o ist. Deshalb bekommt man keine Fehlermeldung des Linkers und auch keine Funktion in der so entstandenen nicht richtig verlinkten Datei!

Also richtig ist: gcc Haupt.o modul1.o modul2.o

ergibt a.out in der die drei Dateien richtig miteinander verlinkt sind.


3. Oder sein sollten: Tja, bei mir hat der linker natürlich gleich gemeckert, daß es da mehrere redeclarations gäbe. Klar, ich habe da Funktionen genommen, die ich vorher schon mal einzeln funktionstüchtig gemacht habe und da sind die Zählvariablen eben „a“ oder „n“ usw.

Nun also die angemeckerten Variablen irgendwie umbenennen oder als lokale Variable in den Unterfunktion verschieben. Sollte man ja immer machen, aber wenn man das Display (bei mit hier TM1637) überhaupt erst mal zum Funktionieren bringen will, dann ist man da erst mal ein bißchen großzügig.
Zum Schluß hieß dann der Aufruf

gcc -Wall -lwiringPi -o Funktion1234 Haupt.o modul1.o modul2.o

(lwiringPi natürlich nur, wenn man es braucht!)

und Funktion 1234 funktionierte.

Hoffe,m damit ein paar Leuten geholfen zu haben.

Grüße

Norbert





 

Neue Beiträge