Forum: Compiler & IDEs Linken in einer Lib schlägt fehl


von Christopher C. (Gast)


Lesenswert?

Hi,

ich portiere derzeit mein CFramework und eine andere Bibliothek von dem 
MS Compiler zu GCC (die MS Unterstützung für C ist nicht die Beste), 
also die Dateien zu einem Eclipse Projekt kopiert und kompiliert. So 
weit so gut. Nachdem ich jedoch ein Testprogramm geschrieben habe, 
jammert der Linker an vielen Stellen, dass dort eine Funktion ist, zu 
dem er keine Referenz findet. Nur warum? Die Pfade und Bibliotheken sind 
drin und der Compiler und der Linker haben sonst nichts zu meckern.
Mir ist aufgefallen, dass der Linker kein Problem mit der CFramework Lib 
hat, sondern mit der anderen Lib, welche dass das CFramework benutzt. 
Und genau dort liegt das Problem. Der Linker findet die Referenz von den 
CFramework Funktionen nicht, die (und nur die) in der anderen Bibliothek 
verwendet werden, das eigentliche Programm hat keine Problem das 
CFramework zu benutzen.

Ich hoffe, dass ich das Problem ausreichend schildern konnte, denn am 
Code kanns nicht liegen.

Vielen Dank für eure Hilfe!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christopher C. schrieb:
> Nachdem ich jedoch ein Testprogramm geschrieben habe,
> jammert der Linker an vielen Stellen, dass dort eine Funktion ist, zu
> dem er keine Referenz findet.

Mach's mal bitte konkret, am besten mit einem kurzen Beispielprogramm
sowie mit der Kommandozeile, mit der der Linker aufgerufen wird.

von Christopher C. (Gast)


Lesenswert?

OK hier mal ein Beispiel:

CFramework.c:
1
void stopwatch_start()
2
{
3
...
4
}
5
6
...

Hier wird dann das Framework benutzt:
CEngine.c
1
void DoSomething()
2
{
3
    stopwatch_start();
4
...
5
}

main.c:
1
...
2
int main(void)
3
{
4
    ...
5
    DoSomething(); // <-- undefined reference to `stopwatch_start' CEngine.c
6
    ...
7
}

Hier die Ausgabe von Eclipse:
1
gcc -IC:\Users\Christopher\C_Projekte\CFramework\src -IC:\Users\Christopher\C_Projekte\CEngine\src -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -o src\Main.o ..\src\Main.c
2
gcc -LC:\Users\Christopher\C_Projekte\CFramework\Debug -LC:\Users\Christopher\C_Projekte\CEngine\Debug -o CEngine_Test.exe src\Main.o -lCFramework -lCEngine -lgdi32 -luser32 -lkernel32 -lopengl32 -lglu32
Und dann gehts los mit Fehlern :(.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christopher C. schrieb:
> Und dann gehts los mit Fehlern :(.

Ja, mit welchen denn?

Und wie sind all die vielen Bibliotheken, die du da hast, denn
entstanden?  (libCFramework.a, libCEngine.a)

Gehört nun main.o zu libCEngine.a?

von Christopher C. (Gast)


Lesenswert?

Also diese drei Codedateien gehören je zu einem Projekt.
CFramework.c -> CFramework
CEngine.c -> CEngine (braucht CFramework)
main.c -> Programm (linkt CFramework und CEngine)

von Christopher C. (Gast)


Lesenswert?

Achso und die Fehler sind allesamt "undefined reference" Fehler, die in 
den Dateien der CEngine angezeigt werden. Hoffe das Hilft weiter :).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christopher C. schrieb:
> Also diese drei Codedateien gehören je zu einem Projekt.

Das allein hat doch aber noch nichts mit Bibliotheken zu tun.

Mir dünkt, du schmeißt hier gerade sämtliche Begriffe durcheinander.

Compiliere diese drei Dateien jeweils separat, und dann linkst du
die erhaltenen Objekte zusammen.  Nix "Bibliothek", keine -l
Optionen (außer denen für Systembibliotheken, soweit erforderlich).

gcc -o executable main.o CFramework.o CEngine.o

Fertig ist die Laube.

von Konrad S. (maybee)


Lesenswert?

Früher war's mal so, dass der Linker statische Bibliotheken nur von 
links nach rechts einmal sequenziell abgearbeitet hat. Man musste also 
die Bibliotheken in der richtigen Reihenfolge beim Linken angeben und 
ggf. auch mal eine Bibliothek mehrfach angeben, z.B. wenn A und B sich 
gegenseitig benötigen "-lA -lB -lA".

von Christopher C. (Gast)


Lesenswert?

Nein, du verstehtst mich falsch, das war nur ein Beispiel, die Projekte 
haben weit mehr als nur eine Codedatei. Bibliotheken daraus zu machen, 
macht schon Sinn.
Am Anfang hab ich die drei Projekte schon mal für den GCC gemacht, das 
funktionierte auch. Danach wechselte ich dann zu Visual Studio 2010, da 
ich hörte, dass es die beste IDE für C++ ist (somit eigentlich auch für 
C). Allerdings stellte sich dann heraus, dass die IDE wirklich gut, der 
Compiler aber für C Müll ist. Ich schrieb aber trotzdem noch ein wenig 
weiter an meinem Bibliotheken und nun will ich wieder zurück zu GCC.

Hier noch mal die ganze Ausgabe:
1
gcc -IC:\Users\Christopher\C_Projekte\CFramework\src -IC:\Users\Christopher\C_Projekte\CEngine\src -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -o src\Main.o ..\src\Main.c
2
gcc -LC:\Users\Christopher\C_Projekte\CFramework\Debug -LC:\Users\Christopher\C_Projekte\CEngine\Debug -o CEngine_Test.exe src\Main.o -lCFramework -lCEngine -lgdi32 -luser32 -lkernel32 -lopengl32 -lglu32
3
C:\Users\Christopher\C_Projekte\CEngine\Debug/libCEngine.a(Framelimiter.o): In function `framelimiter':
4
C:\Users\Christopher\C_Projekte\CEngine\Debug/../src/Framelimiter.c:9: undefined reference to `stopwatch_new'
5
C:\Users\Christopher\C_Projekte\CEngine\Debug/libCEngine.a(Framelimiter.o): In function `framelimiter_update':
6
C:\Users\Christopher\C_Projekte\CEngine\Debug/../src/Framelimiter.c:16: undefined reference to `stopwatch_stop'
7
C:\Users\Christopher\C_Projekte\CEngine\Debug/../src/Framelimiter.c:17: undefined reference to `stopwatch_getElapsedMilliseconds'
8
C:\Users\Christopher\C_Projekte\CEngine\Debug/../src/Framelimiter.c:20: undefined reference to `stopwatch_restart'

Ich hab zwar die alten Projekte noch, kann aber leider keinen 
Unterschied in den Einstellungen feststellen. Kann das überhaupt nicht 
nachvollziehen.

von Stefan E. (sternst)


Lesenswert?

1
... -lCFramework -lCEngine ...
Falsche Reihenfolge.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Stefan Ernst schrieb:
>
1
... -lCFramework -lCEngine ...
Falsche Reihenfolge.

Bzw. siehe Beitrag "Re: Linken in einer Lib schlägt fehl"

Konkret also:
1
-lCFramework -lCEngine -lCFramework

von Christopher C. (Gast)


Lesenswert?

Endlich funktionierts!
Dachte es wäre egal wie man die Bibliotheken anordnet. Und selbst wenn, 
dachte ich, die wären richtig angeordnet.

Vielen Dank!

von Compilerfachmann (Gast)


Lesenswert?

aha,

Christopher C. schrieb:

> Am Anfang hab ich die drei Projekte schon mal für den GCC gemacht, das
> funktionierte auch. Danach wechselte ich dann zu Visual Studio 2010, da
> ich hörte, dass es die beste IDE für C++ ist (somit eigentlich auch für
> C). Allerdings stellte sich dann heraus, dass die IDE wirklich gut, der
> Compiler aber für C Müll ist. Ich schrieb aber trotzdem noch ein wenig
> weiter an meinem Bibliotheken und nun will ich wieder zurück zu GCC.

deshalb steigt man von einem funktionierenden System um,

Jörg Wunsch schrieb:
>>... -lCFramework -lCEngine ...Falsche Reihenfolge.
>
> Bzw. siehe Beitrag "Re: Linken in einer Lib schlägt fehl"
>
> Konkret also:
> -lCFramework -lCEngine -lCFramework......

muss ich mir mal merken, wenn ich wieder zuviel zu tun haben

von Dirk D. (dirkd)


Lesenswert?

> Allerdings stellte sich dann heraus, dass die IDE wirklich gut, der
> Compiler aber für C Müll ist

Woran machst Du das fest?



> -lCFramework -lCEngine -lCFramework

Kann man machen. Hat aber den Nachteil daß es kompliziert/aufwändig 
werden kann wenn man noch mehr Komponenten mit diesen Abhängigkeiten 
verwenden will.

Aber diese zirkulären Abhängigkeiten sind häufig ein Anzeichen für ein 
schlechtes Design. Überleg mal, ob Du es nicht anders aufteilen  kannst.

Wenn das nicht geht (oder zu kompliziert/aufwändig ist) kannst Du auch 
die Linker-Gruppen vom GCC/LD verwenden.

 -Wl,--start-group -lCFramework -lCEngine  -Wl,--end-group

dann versucht der LD diese Abhängikeiten selbst aufzulösen.

von ./. (Gast)


Lesenswert?

Nen ordentlicher Linker hat dafuer das Flag: --reread-libraries
oder --reread-exhaustive-libraries.

von Christopher C. (Gast)


Lesenswert?

> Aber diese zirkulären Abhängigkeiten sind häufig ein Anzeichen für ein
> schlechtes Design. Überleg mal, ob Du es nicht anders aufteilen  kannst.

Danke für die Rückmeldung. Aber so schlimm is es nicht, ich kann einfach 
mit:
-lCEngine -lCFramework
linken. Die Reihenfolge war einfach falsch.

Vielen Dank für eure Bemühungen ;).

mfg

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Dirk Dörr schrieb:
>> Allerdings stellte sich dann heraus, dass die IDE wirklich gut, der
>> Compiler aber für C Müll ist
>
> Woran machst Du das fest?

Microsoft investiert meines Wissens praktisch nichts mehr in C, d. h.
sie sind bei ANSI C89 / ISO C90 mit ihrer Entwicklung stehengeblieben.
Inzwischen haben wir nun schon C11 …

von Dirk D. (dirkd)


Lesenswert?

> Microsoft investiert meines Wissens praktisch nichts mehr in C
Na ja, veraltet ok, aber Müll...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Dirk Dörr schrieb:
>> Microsoft investiert meines Wissens praktisch nichts mehr in C
> Na ja, veraltet ok, aber Müll...

Wenn etwas hoffnungslos veraltet ist, wird es irgendwann Müll.  Erst,
wenn es 20 Jahre lang bereits als Müll galt, sodass es kaum noch
irgendwas davon auf der Welt gibt, bekommt es wieder Wert. ;-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.