Forum: Compiler & IDEs undefined reference to `log' - obwohl #include<math.h>


von Daniel (Gast)


Lesenswert?

Hallo zusammen,

gleich vornweg - ich bin newbee im Bereich ARM und arbeite mich gerade 
ein mit Hilfe des Buch "C Programming for Embedded Microcontrollers".
Ich nutze das Olimex-DevBoard At91SAM7x256 mit Eclipse und 
Yagarto-Toolchain.
Bisher war alles lösbar.

Nun wollte ich die "log"-Funktion nutzen. Trotz einbinden der math.h 
folgt beim Kompilieren folgende Fehlermeldung
1
**** Build of configuration Default for project Tempsense ****
2
3
make all 
4
arm-elf-gcc -c -g -mcpu=arm7tdmi -O0 -Wall -I./Drivers -DAT91SAM7X256 Code/main.c -o main.o
5
arm-elf-gcc -nostartfiles -Wl,-Map,out.map,--cref -T Startup/RAM.ld  -n -o tempsens.elf startup.o main.o syscalls.o dbgu.o
6
main.o: In function `CHECK_TEMPERATUR':
7
E:\ARM_C\_Ram-Prog\Tempsens/Code/main.c:74: undefined reference to `log'
8
collect2: ld returned 1 exit status
9
make: *** [sram] Error 1

Warum???
1
#include <stdio.h>
2
#include <math.h>
3
#include "at91sam7x.h"
4
#include "dbgu.h"
5
6
void CHECK_TEMPERATUR(void);
7
void INIT_ADC(void);
8
void Delay(void);
9
void INIT_LCD(void);
10
11
char my_str[40];
12
13
int main(void)
14
{
15
  DBGUInit(DBGU_115200);
16
  DBGUTxMsg(my_str);
17
  INIT_LCD();
18
  while (1)
19
  {
20
    Delay();
21
    CHECK_TEMPERATUR();
22
  }
23
}
24
25
void INIT_LCD(void)
26
{
27
...
28
}
29
30
void CHECK_TEMPERATUR(void)
31
{
32
    unsigned int ADC5, i;
33
    float Rtemp, Temp;
34
    INIT_ADC();
35
    ADC5=0;
36
    for(i=0;i<128;i++) //Mittelwertbildung - 128 Werte
37
    {
38
      ADC_CR = 0x00000002;        //Starten der Wandlung
39
      while(!(ADC_SR & 0x00000020));
40
      ADC5 += ADC_CDR5;
41
    }
42
    ADC5 /= 128;
43
    Rtemp = ( (1024-ADC5) * 1800 ) /ADC5;
44
45
    Temp = log(Rtemp/2595.2) / (-0.0431));
46
47
    sprintf(my_str,"\rAktuelle Temp = %f", Temp);
48
    DBGUTxMsg(my_str);
49
}

von tpircher (Gast)


Lesenswert?

Du must die libm dazulinken. Fuege die Option -lm zu dem letzten Aufruf 
von gcc (linking stage) dazu.

von Thomas (Gast)


Lesenswert?

Daniel schrieb:
>     Temp = log(Rtemp/2595.2) / (-0.0431));

Da stimmt was mit den Klammern nicht

von Daniel (Gast)


Lesenswert?

@Thomas: Das mit den Klammern ist durch säubern für hier enstanden.

@tpircher: Wo mache ich das?
Hier mein "makefile"
1
#----------------------------------------------------------------------------------
2
#   FILENAME:       Makefile
3
#
4
#   DESCRIPTION:    Makefile for compiling and linking the OSPLC Framework code
5
#
6
#----------------------------------------------------------------------------------
7
8
#----------------------------------------------------------------------------------
9
# TODO: Change the name of the output files for your project
10
#    (Replace "Framework" with your projects name)
11
#----------------------------------------------------------------------------------
12
OUTFILE_SRAM=tempsens
13
14
TARGET=AT91SAM7X256
15
16
INCL=./Drivers
17
18
# Paths to standard and maths library files - assumes default YAGARTO installation
19
LIBGCC=C:/Programme/yagarto/lib/gcc/arm-elf/4.4.2/libgcc.a
20
LIBC=C:/Programme/yagarto/arm-elf/lib/libc.a
21
LIBM=C:/Programme/yagarto/arm-elf/lib/libm.a
22
LIBA=C:/Programme/yagarto/arm-elf/lib/liba.a
23
24
25
# Optimisation settings
26
# optimisation for size
27
#OPTIM=-Os
28
# no optimisation - for debug mode
29
OPTIM=-O0
30
31
AS=arm-elf-gcc
32
CC=arm-elf-gcc
33
LD=arm-elf-gcc
34
OBJCOPY=arm-elf-objcopy
35
OBJDUMP=arm-elf-objdump
36
CCFLAGS=-g -mcpu=arm7tdmi $(OPTIM) -Wall -I$(INCL) -D$(TARGET)
37
ASFLAGS=-D__ASSEMBLY__ -D$(TARGET) -g -mcpu=arm7tdmi -c $(OPTIM) -Wall -I$(INCL)
38
39
# Linker flags.
40
#  -Wl,... :    tell GCC to pass this to linker.
41
#  -Map    :    create map file
42
#  --cref  :    add cross reference to map file
43
LDFLAGS_R+=-nostartfiles -Wl,-Map,out.map,--cref
44
LDFLAGS_R+=-T Startup/RAM.ld
45
46
47
#----------------------------------------------------------------------------------
48
# TODO: Add all the object files generated for you project to the framework
49
#    objects listed below
50
#----------------------------------------------------------------------------------
51
OBJS=startup.o \
52
     main.o \
53
   syscalls.o \
54
   dbgu.o
55
56
rebuild: clean all
57
58
all: sram
59
60
sram: $(OBJS)
61
  $(LD) $(LDFLAGS_R)  -n -o $(OUTFILE_SRAM).elf $(OBJS)
62
  $(OBJCOPY) --strip-debug --strip-unneeded $(OUTFILE_SRAM).elf -O binary $(OUTFILE_SRAM).bin
63
  
64
#----------------------------------------------------------------------------------
65
# TODO: Add your object file compilation instructions
66
#----------------------------------------------------------------------------------
67
68
main.o: Code/main.c
69
  $(CC) -c $(CCFLAGS) Code/main.c -o main.o
70
71
startup.o:  Startup/startup.S
72
  $(AS) $(ASFLAGS) Startup/startup.S -o startup.o
73
  
74
dbgu.o: Drivers/dbgu.c
75
  $(CC) -c $(CCFLAGS) Drivers/dbgu.c -o dbgu.o
76
  
77
syscalls.o: syscalls.c 
78
  $(CC) -c $(CCFLAGS) syscalls.c -o syscalls.o 
79
  
80
clean:
81
  -rm *.o *.bin *.elf *.map

von Thomas P. (tpircher) Benutzerseite


Lesenswert?

in der Sektion Linker flags.
1
LDFLAGS_R+=-lm

von Daniel (Gast)


Lesenswert?

Meldung erscheint immer noch

von Thomas P. (tpircher) Benutzerseite


Lesenswert?

Taucht die Option -lm im Output von make auf? Hast du ein "make clean" 
und ein anschliessendes "make" probiert?

von Daniel (Gast)


Lesenswert?

1
**** Build of configuration Default for project Tempsense ****
2
3
make all 
4
arm-elf-gcc -nostartfiles -Wl,-Map,out.map,--cref -T Startup/RAM.ld -lm  -n -o tempsens.elf startup.o main.o syscalls.o dbgu.o
5
main.o: In function `CHECK_TEMPERATUR':
6
E:\ARM_C\_Ram-Prog\Tempsens/Code/main.c:74: undefined reference to `log'
7
collect2: ld returned 1 exit status
8
make: *** [sram] Error 1

von Daniel (Gast)


Lesenswert?

clean und danach build
1
**** Build of configuration Default for project Tempsense ****
2
3
make all 
4
arm-elf-gcc -D__ASSEMBLY__ -DAT91SAM7X256 -g -mcpu=arm7tdmi -c -O0 -Wall -I./Drivers Startup/startup.S -o startup.o
5
arm-elf-gcc -c -g -mcpu=arm7tdmi -O0 -Wall -I./Drivers -DAT91SAM7X256 Code/main.c -o main.o 
6
arm-elf-gcc -c -g -mcpu=arm7tdmi -O0 -Wall -I./Drivers -DAT91SAM7X256 syscalls.c -o syscalls.o 
7
arm-elf-gcc -c -g -mcpu=arm7tdmi -O0 -Wall -I./Drivers -DAT91SAM7X256 Drivers/dbgu.c -o dbgu.o
8
arm-elf-gcc -nostartfiles -Wl,-Map,out.map,--cref -T Startup/RAM.ld -lm  -n -o tempsens.elf startup.o main.o syscalls.o dbgu.o
9
main.o: In function `CHECK_TEMPERATUR':
10
E:\ARM_C\_Ram-Prog\Tempsens/Code/main.c:74: undefined reference to `log'
11
collect2: ld returned 1 exit status
12
make: *** [sram] Error 1

von Thomas P. (tpircher) Benutzerseite


Lesenswert?

Das ist sehr seltsam. Kannst du gar keine Funktion aus libm aufrufen? 
Wie steht es mit logf(), oder pow()?

von Stefan E. (sternst)


Lesenswert?

Das "-lm" muss hinter die Object-Files (ja, beim Linken spielt die 
Reihenfolge eine Rolle).

von Thomas P. (tpircher) Benutzerseite


Lesenswert?

Stefan Ernst schrieb:
> ja, beim Linken spielt die Reihenfolge eine Rolle).

andenkopfschlag Natuerlich! :)
Die Zeile im Makefile koennte dann so aussehen:
1
sram: $(OBJS)
2
  $(LD) $(OBJS) $(LDFLAGS_R) -n -o $(OUTFILE_SRAM).elf

von Daniel (Gast)


Lesenswert?

Ich habe etwas rausgefunden
funkioniert nicht: Temp = log(Rtemp);
funktioniert     : Temp = log(2.2);

d.h. steht ein Wert in der Klammer funktioniert es und wenn der 
Variablenname innerhalb der Klammer steht macht er mir das Problem beim 
Kompilieren

von Daniel (Gast)


Lesenswert?

Danke!-)

Ich habe aus:
1
sram: $(OBJS)
2
  $(LD) $(LDFLAGS_R)  -n -o $(OUTFILE_SRAM).elf $(OBJS)

das gemacht
1
sram: $(OBJS)
2
  $(LD) $(OBJS) $(LDFLAGS_R)  -n -o $(OUTFILE_SRAM).elf

UND ES FUNKTIONIERT

von Daniel (Gast)


Lesenswert?

Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, 
Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, 
Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke


Ich habe da schon den ganzen Tag damit verbracht

von Thomas P. (tpircher) Benutzerseite


Lesenswert?

Dein Problem wurde schon von Stefan geloest, aber nur zur Information:

Daniel schrieb:
> funktioniert     : Temp = log(2.2);
> funkioniert nicht: Temp = log(Rtemp);

Du verwendest einen neuen GCC? Der erkennt, dass log(2.2) eine Konstante 
ist und ersetzt den Funktionsaufruf mit dem Ergebnis des Ausdrucks.

Das Ergebnis von log(Rtemp) ist zur Kompilationszeit nicht bekannt, und 
GCC muss die Funktion log() also aufrufen.

Im ersten Fall wird die log()-Funktion also nicht dazugelinkt, im 
zweiten Fall wird sie das. Deshalb hast du auch den Fehler nur bei der 
zweiten Variante bekommen.

von Mark B. (markbrandis)


Lesenswert?

Thomas Pircher schrieb:
> Du verwendest einen neuen GCC? Der erkennt, dass log(2.2) eine Konstante
> ist und ersetzt den Funktionsaufruf mit dem Ergebnis des Ausdrucks.

Huh, der Compiler rechnet Logarithmusfunktionen aus? Cool.

von Thomas P. (tpircher) Benutzerseite


Lesenswert?

Mark Brandis schrieb:
> Huh, der Compiler rechnet Logarithmusfunktionen aus? Cool.

GCC kann das seit v4.3. Ein Auszug aus 
http://gcc.gnu.org/gcc-4.3/changes.html :

> The GCC middle-end has been integrated with the MPFR library. This allows
> GCC to evaluate and replace at compile-time calls to built-in math
> functions having constant arguments with their mathematically equivalent
> results. In making use of MPFR, GCC can generate correct results
> regardless of the math library implementation or floating point precision
> of the host platform. This also allows GCC to generate identical results
> regardless of whether one compiles in native or cross-compile
> configurations to a particular target. The following built-in functions
> take advantage of this new capability: acos, acosh, asin, asinh, atan2,
> atan, atanh, cbrt, cos, cosh, drem, erf, erfc, exp10, exp2, exp, expm1,
> fdim, fma, fmax, fmin, gamma_r, hypot, j0, j1, jn, lgamma_r, log10, log1p,
> log2, log, pow10, pow, remainder, remquo, sin, sincos, sinh, tan, tanh,
> tgamma, y0, y1 and yn. The float and long double variants of these
> functions (e.g. sinf and sinl) are also handled. The sqrt and cabs
> functions with constant arguments were already optimized in prior GCC
> releases. Now they also use MPFR.

von Christian (Gast)


Lesenswert?

DANKE! auch von mir. Der Witz ist nämlich, auf Linux ubuntu 
2.6.38-11-generic geht mein Aufruf
$ gcc -D_REENTRANT  -Wall -lm -lpcan -lpthread -o s2algo 
tools/sens2algos.c
ohne Probleme. Dagegen haut's mir den auf
Linux ubuntu 3.5.0-36-generic #57~precise1-Ubuntu SMP
um die Ohren. Ich habe's nicht verstanden. Mit
$ gcc -D_REENTRANT  -Wall -pthread -o s2algo tools/sens2algos.c -lm 
-lpcan
wurde ich glücklich.
Und ich habe ernsthaft 1.5 Tage recherchiert!!

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.