Hi! ich habe Probleme beim mspgcc die math-funktionen (z.b. fsin() oder floor) zu benutzen. Ich bekomme immer die Fehlermeldung : /cygdrive/c/mspgcc/test/main.c:63: undefined reference to `floor' Ich denke, ich müsste die libm.a dazulinken, aber ich weiss nicht wie!?! Vielen Dank im Voraus Jan Stumpf
Hi ich bin zwar nicht der Super-makefile-Experte, würde aber mal sagen Zeile 21: ${CC} -mmcu=${CPU} -lm -o $@ ${OBJECTS} Matthias
Also ich habe es dutzende male probiert, aber das funktioniert nie:
> msp430-gcc -mmcu=msp430x149 -lm -o test2.elf test2.c
/tmp/ccGGuHKx.o(.text+0xe0): In function `main':
: undefined reference to `sinf'
obwohl in test2.c
#include <math.h>
am Anfang steht.
Welcher Trick fehlt denn da?
Pack das -lm ans Ende. Die undefined reference entsteht im Linker ja erst beim Verarbeiten des Objektmoduls, der aus test2.c übersetzt worden ist, aber libm.a (-lm) hatte der Linker zu diesem Zeitpunkt bereits gesehen (und für nichts benutzen können).
Ok, also > msp430-gcc -mmcu=msp430x149 -o -lm test2.elf test2.c msp430-gcc: test2.elf: Datei oder Verzeichnis nicht gefunden und das funktioniert auch nicht! Also habe ich mal das obige Makefile genommen, ${CC} -mmcu=${CPU} -lm -o $@ ${OBJECTS} reingesetzt und das funktioniert ebenfalls nicht: msp430-gcc -mmcu=msp430x149 -O2 -Wall -g -c -o test2.o test2.c msp430-gcc -mmcu=msp430x149 -lm -o test2.elf test2.o test2.o(.text+0x86): In function `main': /home/rf0/c/mspgcc/old/test2/test2.c:83: undefined reference to `expf' make: *** [test2.elf] Fehler 1 Sieht so aus, als wären die Gleitpunkt-Funktionen beim mspgcc nur Vaporware, denn auf ARM9, PC u. a. ist Compilieren +Linken auch mit expf problemlos, wenn man math.h includiert und -lm angibt: > gcc -Wall -O2 -lm -o foo foo.c > echo $? 0
Ahhh, da ist ein ganz spezieller Trick nötig: > msp430-gcc -mmcu=msp430x149 -O2 -Wall -g -c -o test2.o test2.c > msp430-gcc -mmcu=msp430x149 -o test2.elf test2.o -lm > echo $? 0 Da muß man erstmal drauf kommen ... Im Manual steht natürlich auch nichts dazu und in den leztzen 2 1/2 war das auch auf der Mailingliste nicht zu erfahren; es ist also richtig geheim, denn in KEINEM von den dutzenden Code Examples ist ein #include <math.h>!
Wofür habe ich dir eigentlich eine Antwort geschrieben? Genau das schrob ich doch (einen halben Tag vor deinem ,,spziellen Trick''): ,,pack das -lm ans Ende''. Das hat gar nichts mit MSP-GCC zu tun, es ist einfach in der Arbeitsweise des Unix-Linkers begründet. Bibliotheken werden ausschließlich linear abgearbeitet. Daher ist es zwecklos, eine Bibliothek vor den eigenen Dateien anzugeben -- der Linker hätte ja nie einen Grund, daraus auch nur irgendetwas zu entnehmen, da er ja zu diesem Zeitpunkt kein einziges Symbol als undefiniert in der Sammlung hat.
Ich bin von dem Ende vor den Dateinamen im aktuellen Verzeichnis ausgegangen, wie oben beschrieben. Und der Unix-Linker muß beim MSPGCC modifiziert sein, denn beispielsweise bei der Crosscompilierung für ARM hatte ich das Problem nie; daß das Problem auch auf PC nicht auftaucht, hatte ich ja auch oben beschrieben. Daß der Unix-Linker linear linkt, weiß ich auch, aber ich kenne ihn seit 10 Jahren nur so, daß damit nur die Objekt-Dateien festgelegt werden (d. h. welche von mehreren möglichen genommen werden); daß er einige überhaupt nicht findet, wenn sie nicht in einer ganz bestimmten Reihenfolge stehen, ist mir neu und das ist auch im ANSI-C nicht spezifiziert. Das ist eine böse Falle, in die regelmäßig auch andere Programmierer geraten, wie ich auch auf der Mailing-Liste sehe.
Sorry, du liegst immer noch schief. Ich habe MSP-GCC nie in der Hand gehabt, aber ich bin mir ziemlich sicher, dass der Linker nicht modifiziert ist, sondern ein stinknormaler Linker ist. (Das Einzige, was der MSP-GCC-Autor wohl pusht ist, -ffunction-sections im Compiler und --gc-sections im Linker zu benutzen, um automatisch alle nicht benutzten Funktionen auch noch aus dem Ergebnis rauszukippen. Ich finde persönlich, dass diese Vorgehensweise nur zu erhöhter Schlampigkeit im Softwaredesign führt, und würde sie daher nicht propagieren.) Die Architekturen, gegen die du vergleichst, sind vermutlich welche mit dynamischen Bibliotheken. In diesem Falle fügt der Linker ja nicht die eigentliche Bibliothek selbst ein, sondern überlässt diese Bindung für die Laufzeit. Dadurch ist dann die Linkreihenfolge ziemlich egal, wenn der Krempel denn überhaupt da war, wird er zur Laufzeit auch gefunden. Es ist dennoch ein prinzipieller Fehler, die Bibliotheken vor den Objektmodulen anzugeben, die Teile aus den Libs referenzieren -- auch wenn dieser Fehler bei dynamischen Libs weniger Konsequenzen hat. > Daß der Unix-Linker linear linkt, weiß ich auch, aber ich kenne ihn > seit 10 Jahren nur so, daß damit nur die Objekt-Dateien festgelegt > werden (d. h. welche von mehreren möglichen genommen werden); ... Diesen Satz verstehe ich nicht. Der Linker linkt alle genannten Objektmoduln (egal wo sie stehen), also alle .o-Dateien (bzw. in deinem ersten Fall die temporären .o-Dateien, die der Compiler aus den .c-Dateien gemacht hat -- am Prinzip ändert sich trotzdem nichts). In dem Moment, wo auf der Kommandozeile eine Bibliothek auftaucht, sieht er nach, ob er aus dieser Bibliothek ein derzeit undefiniertes externes Symbol befriedigen kann. Sollten dabei neue undefinierte Symbole entstehen, wird die aktuelle Bibliothek erneut durchsucht, bis schließlich aus dieser Bibliothek ,,nichts mehr zu holen'' ist. Dann geht es weiter mit dem, was auf der Kommandozeile steht. Ist es eine weitere Bibliothek, dann selbiger Algorithmus erneut, ist es (wie in deinem obigen Fall) ein weiterer Objektmodul, dann wird er komplett und ohne nachzusehen gelinkt. Die bisherig verarbeiteten (statischen) Bibliotheken hat er zu diesem Zeitpunkt bereits ,,vergessen'', d.h. sollten aus deinem neuen Objektmodul (oder aus einer späteren Bibliothek) weitere undefinierte externe Symbole entstehen, so bleiben diese undefiniert, sofern nicht weiter hinten auf der Kommanodozeile noch eine Bibliothek kommt, die sie auflösen könnte. Daher benutzt der GCC beim Linken übrigens am Ende seiner eigenen Bibliotheksliste, die er dem Linker übergibt (sieht man mit gcc -v) sowas wie: »... -lc -lgcc -lc«. Die erste Referenz auf die C-Bibliothek löst alles auf, was die Applikation aus dieser benötigt. Danach wird GCC's eigene libgcc.a befragt, in der er einige Hilfsfunktionen untergebracht hat. Da diese Funktionen aber wieder Referenzen auf die C-Bibliothek haben könnten, wird diese am Ende nochmals angegeben. > daß er einige überhaupt nicht findet, wenn sie nicht in einer ganz > bestimmten Reihenfolge stehen, ist mir neu und das ist auch im > ANSI-C nicht spezifiziert. Im ANSI-C gibt es überhaupt keine Aussage zur Arbeitsweise des Linkers (mit Ausnahme von Minimalanforderungen). Es muss nichtmal überhaupt einen solchen geben.
> Die Architekturen, gegen die du vergleichst, sind vermutlich welche > mit dynamischen Bibliotheken. Ja, aber es ist erfahrungsgemäß egal ob man dynamisch oder statisch linken läßt auf PC oder ARM oder auch beim Crosscompilieren für ARM. Da ist egal wo das -lm angegeben wird. Daß es beim MSPGCC ganz anders ist, überrascht daher sehr. Deshalb habe ich auch lange gebraucht um auf diesen geheimen Trick zu kommen.
Du liegst immer noch falsch. j@uriah 270% cat > foo.c #include <math.h> #include <stdio.h> double foo; double bar(void) { return sin(foo); } int main(void) { foo = .875; printf("%f\n", bar()); return 0; } j@uriah 271% cc -O -static -o foo foo.c -lm j@uriah 272% ./foo 0.767544 j@uriah 273% cc -O -static -lm -o foo foo.c /var/tmp//ccetuS7R.o(.text+0x13): In function `bar': : undefined reference to `sin'
Ich wollte nur nochmal gerade auf meine Erkenntnisse verweisen: http://www.mikrocontroller.net/articles/Diskussion:MSPGCC
Ja, man kann übrigens auch den Namen der Lib direkt angeben: msp430-gcc -Os -mmcu=msp430x149 -o test2.elf test2.c /usr/local/msp430/msp430/lib/libm.a Dieses Linker-Verhalten ist inkonsistent, da dieser Zusatz-Aufwand für andere Libs wie libc nicht nötig ist.
Falls Du Dich wieder auf den ARM-Crosscompiler beziehst: Das stimmt ebenfalls nicht :) Habs grad nachgeschaut: in all meinen Makefiles ist sowohl die libc.a als auch die libgcc.a per -lc / -lgcc in den LDFLAGS angegeben...
Crosscompilierst Du für hosted oder freestanding implementation? Ich habe für ARM bisher nur für hosted implementation crosscompiliert und da war kein Unterschied zum compilieren auf und für PC. Und beim MSPGCC braucht man -lc nicht extra angeben.
>Crosscompilierst Du für hosted oder freestanding implementation? Bisher nur Freestanding. >Und beim MSPGCC braucht man -lc nicht extra angeben. Das liegt daran, daß man dem Compiler bestimmte Standardargumente beim Kompilieren mitgeben kann, das sind die sogenannten 'specs', die entweder 'buitl-in' oder in einer Datei abgelegt werden. Beim (msp430-) GCC erfährt man dies mit (siehe Jörgs Beitrag): [ 7:51:05] $ msp430-gcc -v msp430-gcc -v Reading specs from /cygdrive/c/mspgcc/bin/../lib/gcc-lib/msp430/3.2.3/specs Configured with: ./configure --target=msp430 --prefix=/c/local/liechtic/daten/mspgcc/build/installed --disable-nls Thread model: single gcc version 3.2.3 Wenn man sich diese Datei mal ansieht, findet man in den Zeilen 47-51 folgendes: *lib: %{*:-lc } *libgcc: %{*: -lgcc } Der arm-elf-gcc liefert: [ 7:52:30] $ arm-elf-gcc -v arm-elf-gcc -v Using built-in specs. Target: arm-elf Configured with: ../../gcc-4.0.0/configure --enable-languages=c,c++ --enable-interwork --enable-multilib --with-gcc --with-gnu-ld --with-gnu-as --with-stabs --disable-shared --enable-threads --disable-win32-registry --disable-nls --target=arm-elf --enable-sjlj-exceptions --with-newlib --prefix=c:/WinARM -v Thread model: single gcc version 4.0.0 Diese 'built-in-specs' kann man sich mit der Kommandozeilenoption '-dumpspsecs' ansehen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.