Forum: Compiler & IDEs MSPGCC und math.h


von Jan Stumpg (Gast)


Lesenswert?

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

von Matthias (Gast)


Lesenswert?

Hi

-lm beim linken angeben.

Matthias

von Jan Stumpf (Gast)


Angehängte Dateien:

Lesenswert?

Mein Makefile habe ich mal angehangen.

Wo muss denn -lm hin?

danke
Jan

von Matthias (Gast)


Lesenswert?

Hi

ich bin zwar nicht der Super-makefile-Experte, würde aber mal sagen
Zeile 21:

${CC} -mmcu=${CPU} -lm -o $@ ${OBJECTS}

Matthias

von Jan Stumpf (Gast)


Lesenswert?

Jo Danke!

funktioniert!

mfg
Jan

von Rolf F. (Gast)


Lesenswert?

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?

von Jörg Wunsch (Gast)


Lesenswert?

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).

von Rolf F. (Gast)


Lesenswert?

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

von Rolf F. (Gast)


Lesenswert?

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>!

von Jörg Wunsch (Gast)


Lesenswert?

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.

von Rolf F. (Gast)


Lesenswert?

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.

von Jörg Wunsch (Gast)


Lesenswert?

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.

von Rolf F. (Gast)


Lesenswert?

> 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.

von Jörg Wunsch (Gast)


Lesenswert?

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'

von OldBug (Gast)


Lesenswert?

Ich wollte nur nochmal gerade auf meine Erkenntnisse verweisen:

  http://www.mikrocontroller.net/articles/Diskussion:MSPGCC

von Rolf F. (Gast)


Lesenswert?

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.

von OldBug (Gast)


Lesenswert?

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...

von Rolf F. (Gast)


Lesenswert?

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.

von OldBug (Gast)


Lesenswert?

>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
Noch kein Account? Hier anmelden.