1

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?

4
  • 1
    Put the flag after all the objects you are linking Commented Aug 12, 2016 at 19:19
  • Check [ this ] similar question. Commented Aug 12, 2016 at 19:29
  • @cxw the -lm flag is useless in your command line, which is a compilation line BTW. Commented Aug 12, 2016 at 19:52
  • Thanks all! That worked! I put -lm onto the makefile end of every file. Does updated gcc versions have same problem? Commented Aug 12, 2016 at 20:01

1 Answer 1

1

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)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.