odoland odoland - 3 months ago 13
Linux Question

Issue with gcc on Ubuntu Bash on windows with math library

I have a makefile that uses "-lm" flag to include the math library. I also included #include for each .c file.
I am still getting error and "undefined reference" to the math such as exp, floor, and pow etc.

Using bash on windows Ubuntu.

Copy of my terminal output:

labyu@DESKTOP-U037B9F:~/software/BICseq2/NBICseq-norm_v0.2.4$ make
gcc -g -O2 -Wall -lm -c -o combineFile/combine.o combineFile/combine.c
gcc -g -O2 -Wall -lm -c -o lib/read.o lib/read.c
lib/read.c: In function ‘read_table’:
lib/read.c:74:14: warning: variable ‘flag’ set but not used [-Wunused-but-set-variable]
int i=0,j=0,flag=1,low_mmry = 40000, is_num=0,k;
^
gcc -g -O2 -Wall -lm combineFile/combine.o lib/read.o -o combineFile/combineFile
gcc -g -O2 -Wall -lm -c -o DataPrepare/DtaPrep.o DataPrepare/DtaPrep.c
gcc -g -O2 -Wall -lm -c -o lib/statlib.o lib/statlib.c
gcc -g -O2 -Wall -lm DataPrepare/DtaPrep.o lib/read.o lib/statlib.o -o DataPrepare/PrepPois
DataPrepare/DtaPrep.o: In function `print_oneline':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:593: undefined reference to `pow'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:591: undefined reference to `log'
DataPrepare/DtaPrep.o: In function `calculate_bias':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:685: undefined reference to `pow'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:690: undefined reference to `exp'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:681: undefined reference to `log'
DataPrepare/DtaPrep.o: In function `fprint_gc_bin':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:810: undefined reference to `floor'
DataPrepare/DtaPrep.o: In function `fprintf_predicted':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:850: undefined reference to `exp'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:860: undefined reference to `floor'
DataPrepare/DtaPrep.o: In function `calculate_bias':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/DataPrepare/DtaPrep.c:749: undefined reference to `exp'
lib/statlib.o: In function `db_shuffle':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:56: undefined reference to `floor'
lib/statlib.o: In function `db_shuffle_int':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:71: undefined reference to `floor'
lib/statlib.o: In function `rgamma1':
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:99: undefined reference to `log'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:100: undefined reference to `pow'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:103: undefined reference to `pow'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:104: undefined reference to `exp'
/home/labyu/software/BICseq2/NBICseq-norm_v0.2.4/lib/statlib.c:90: undefined reference to `log'
collect2: error: ld returned 1 exit status
make: *** [PrepPois] Error 1


But, when I make a sample program, such as this: test.c

#include <stdio.h>
#include <math.h>

int main(void)
{
int number;
number = pow(10,2);
printf("%d\n", number);
return 0;
}


I can use gcc test.c even without the -lm flag and it compiles fine.

Is this a bug?

Answer

In your test case, since all data is constant, it seems the compiler computes directly the value (it may depend on the compiler, but recent versions of gcc seem to handle this fine)

When disassembling the code (x86) we see it clearly

   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 30             sub    $0x30,%rsp
   8:   e8 00 00 00 00          callq  d <main+0xd>

direct 100 value passed to printf at the line below

   d:   c7 45 fc 64 00 00 00    movl   $0x64,-0x4(%rbp)
  14:   8b 45 fc                mov    -0x4(%rbp),%eax
  17:   89 c2                   mov    %eax,%edx
  19:   48 8d 0d 00 00 00 00    lea    0x0(%rip),%rcx        # 20 <main+0x20>
  20:   e8 00 00 00 00          callq  25 <main+0x25>
  25:   b8 00 00 00 00          mov    $0x0,%eax
  2a:   90                      nop
  2b:   48 83 c4 30             add    $0x30,%rsp
  2f:   5d                      pop    %rbp
  30:   c3                      retq
  31:   90                      nop

i have changed the code to this:

#include <stdio.h>
#include <math.h>

int main(void)
{
   int number;
   int v=10;
   number = pow(v,2);
   printf("%d\n", number);
   return 0;
 }

And now when I nm the file I get:

>nm simplemath.o
0000000000000000 b .bss
0000000000000000 d .data
0000000000000000 p .pdata
0000000000000000 r .rdata
0000000000000000 r .rdata$zzz
0000000000000000 t .text
0000000000000000 r .xdata
                 U __main
0000000000000000 T main
                 U pow
                 U printf

Before I introduced the variable, the pow symbol was not referenced. The compiler did the math statically.

The disassembly shows a more complex code, using float registers and all.

0000000000000000 <main>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 40             sub    $0x40,%rsp
   8:   e8 00 00 00 00          callq  d <main+0xd>
   d:   c7 45 fc 0a 00 00 00    movl   $0xa,-0x4(%rbp)
  14:   66 0f ef c0             pxor   %xmm0,%xmm0
  18:   f2 0f 2a 45 fc          cvtsi2sdl -0x4(%rbp),%xmm0
  1d:   48 b8 00 00 00 00 00    movabs $0x4000000000000000,%rax
  24:   00 00 40
  27:   48 89 45 e8             mov    %rax,-0x18(%rbp)
  2b:   f2 0f 10 4d e8          movsd  -0x18(%rbp),%xmm1
  30:   e8 00 00 00 00          callq  35 <main+0x35>  <== the linker wil add the call to pow here
  35:   f2 0f 2c c0             cvttsd2si %xmm0,%eax
  39:   89 45 f8                mov    %eax,-0x8(%rbp)
  3c:   8b 45 f8                mov    -0x8(%rbp),%eax
  3f:   89 c2                   mov    %eax,%edx
  41:   48 8d 0d 00 00 00 00    lea    0x0(%rip),%rcx        # 48 <main+0x48>
  48:   e8 00 00 00 00          callq  4d <main+0x4d>
  4d:   b8 00 00 00 00          mov    $0x0,%eax
  52:   90                      nop
  53:   48 83 c4 40             add    $0x40,%rsp
  57:   5d                      pop    %rbp
  58:   c3                      retq

But to my surprise, no need of -lm, it links OK without it. Newest gcc versions must include it by default since it's often used. Maybe someone can confirm. You version seems to need it, mine doesn't (gcc 4.9.4)

Comments