1

I am making a C program called reporter, here is the include:

#include <lcthw/dbg.h>
#include <lcthw/stats.h>
#include <stdio.h>
#include <math.h>

This is where the problem happened:

Stats_dump(stats);

Stats_dump in Stats.c(implementation file):

void Stats_dump(Stats *st){
fprintf(stderr,"sum : %f, sumsq %f, n: %ld,min:%f, max: %f,mean: %f, stddev: %f",
    st->sum,st->sumsq,st->n,st->min,st->max,Stats_mean(st),Stats_stddev(st));}

which lead to the error in Stats_stddev in Stats.h:

static inline double Stats_stddev(Stats *st){
return sqrt((st->sumsq-st->sum*st->sum/st->n)/(st->n-1)); // potential error?
}

When I run this line in makefile(build/libYOURLIBRARY.a is where I store self-made lib like stats) :

cc -g -O2 -Wall -Wextra -Isrc -rdynamic  -fPIC  reporter.c -lm  build/libYOURLIBRARY.a -o reporter

However, it returns:

build/libYOURLIBRARY.a(stats.o): In function `Stats_stddev':
/media/thang/DATA/gay/liblcthw/src/lcthw/stats.h:17: undefined reference to `sqrt'

I have included math.h in every single file, and also add -lm to every line of makefile, but to no avail.

What might have caused this issue, and how to solve this?

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
Van Teo Le
  • 164
  • 3
  • 11

1 Answers1

3

Some linkers tend to be fairly simple beasts. When they encounter a -lsomething on the command line, they use it to satisfy any currently unresolved symbols.

Introducing a new unresolved symbol (such as with your build/libYOURLIBRARY.a) may not cause it to back up and try the previously-mentioned libraries again.

In your particular case, it'll probably be fixed by just moving -lm to after your archive file:

cc -g -O2 -Wall -Wextra -Isrc -rdynamic  -fPIC  reporter.c build/libYOURLIBRARY.a -lm -o reporter

That way, the unresolved symbol is known when you start looking at the math library, and it will therefore resolve it.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Yes, it solved my problem,however,i have already add -lm once when i compiled stats.c into stats.o, and after that i put stats.o into build/libYOURLIBRARY.a, doesn't that linker count? – Van Teo Le Sep 25 '19 at 08:00
  • @Van: no. The act of archiving objects into a library is just that. It takes object files (which have unresolved references) and puts them in a library (still with unresolved references). It's when you try to *combine* objects (from compiling C files, objects that have already been compiled or objects that have already been compiled and put into an archive lib) into an executable form that you need to resolve all references. When compiling, you don't need the lib, you only need the headers - the libs probably aren't even used. – paxdiablo Sep 25 '19 at 08:09
  • You have to remember that what you *run* (such as `gcc`) is usually a front end that invokes pre-processors, compilers, assemblers, library managers, linkers and so on (either as separate processes or as stages). Even if you do specify `-lm` to the front end, it probably won't be used for anything other than the linking stage. – paxdiablo Sep 25 '19 at 08:14