Question

I am trying to compile a simulation program called COSI: http://www.broadinstitute.org/~sfs/cosi/cosi_1.2.1.tar

After unzipping it with tar xfp cosi_package.tar, I try to run make as stated in the README within the newly created directory cosi_1.2. Unfortunately, I get a lot of errors such as

coalescent.a(historical.o): In function `historical_process_pop_event':
historical.c:(.text+0x5c7): undefined reference to `log'
coalescent.a(historical.o): In function `historical_next_exp':
historical.c:(.text+0x76a): undefined reference to `exp'
../cosi_rand/random.a(ranbinom.o):ranbinom.c:(.text+0x702): more undefined references to `log' follow
collect2: ld returned 1 exit status
make[1]: *** [coalescent] Error 1
make[1]: Leaving directory `/home/myname/Desktop/cosi_1.2/cosi'
make: *** [all] Error 2

The MAKEFILE in the problematic sub-directory looks like this:

PACKAGE := coalescent
BINFILES := coalescent.c
SKIPFILES := 
ARFILE := $(PACKAGE).a
BINS := $(BINFILES:.c=)
PREFILES := $(wildcard *.c)
CFILES := $(filter-out $(SKIPFILES),$(PREFILES))
LIBFILES := $(filter-out $(BINFILES),$(CFILES))
OFILES := $(LIBFILES:.c=.o)
DFILES := $(CFILES:.c=.d)
FOO := $(ARFILE)(
BAR := )
AFILES := $(addprefix $(FOO), $(OFILES))
AFILES := $(addsuffix $(BAR), $(AFILES))
CC := gcc
CFLAGS := $(DEBUG) -O3 -Wall -ansi

all : $(BINS)
#   rm *.d; rm *.o
install : $(BINS)
    rm *.d; rm *.o
.PHONY : cleaninstall
cleaninstall : 
    rm $(BINS)

$(ARFILE) : $(AFILES)
    $(AR) cr $(ARFILE) $(?:.c=.o)
    $(RM) $(?:.c=.o)

$(BINS) : % : %.o $(ARFILE)
    ranlib $(ARFILE)
    $(CC) $(CFLAGS) -lm -v -o $@ $@.o $(ARFILE) ../cosi_rand/random.a


%.d: %.c
    @$(SHELL) -ec '$(CC) -MM $(CPPFLAGS) $< \
                      | sed '\''s/\($*\)\.o[ :]*/coalescent.a(\1.o) $@ : /g'\'' > $@; \
                      [ -s $@ ] || rm -f $@'

-include $(DFILES)

Obviously, all the errors are missing mathematical functions. Hence I tried adding -lm to CFLAGS but it didn't help. Any suggestions what I could do?

Was it helpful?

Solution

-lm is a linker flag. It should appear at the end of the linker command:

$(CC) -v -o $@ $@.o $(ARFILE) ../cosi_rand/random.a -lm

Apparently some compilers permit -l to appear anywhere. I still haven't found out which ones do, but my GCC wants them at the end, and in reverse order of dependency: if random.a needs libm, then libm should be linked in after random.a.

I also removed $(CFLAGS) from the linker command because you should pass linker options, not compiler options, when linking.

OTHER TIPS

The linker searches for dependencies in the order they are on the command line. So when you ask the linker to link with a library (with e.g. -lm) then the linker will see if there is anything that depends on the library. If there isn't then the library is discarded.

To solve this problem it's recommended that you should always put libraries after all source/object files.

Note: This dependency order is also used between libraries, so if you have a library A that depends on library B, then you need to place A before B on the command line. This of course makes it hard if you have two libraries that depend on each other.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top