我正在尝试编译一个名为COSI的模拟程序: http://www.broadinstitute.org/~sfs/cosi/cosi_1.2.1.tar
使用tar xfp cosi_package.tar
解压缩后,我尝试按照新创建的目录make
中的README中的说明运行cosi_1.2
。不幸的是,我收到很多错误,例如
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
有问题的子目录中的MAKEFILE如下所示:
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)
显然,所有错误都缺少数学函数。因此,我尝试将-lm
添加到CFLAGS
,但它没有帮助。有什么建议我可以做什么?
答案 0 :(得分:4)
-lm
是链接器标志。它应该出现在链接器命令的末尾:
$(CC) -v -o $@ $@.o $(ARFILE) ../cosi_rand/random.a -lm
显然某些编译器允许-l
出现在任何地方。我仍然没有发现哪些做了,但我的GCC最终想要它们,并且依赖于相反的顺序:如果random.a
需要libm
,那么libm
应该链接在之后 random.a
。
我还从链接器命令中删除了$(CFLAGS)
,因为在链接时你应该传递链接器选项,而不是编译器选项。
答案 1 :(得分:1)
链接器按照它们在命令行上的顺序搜索依赖项。因此,当您要求链接器链接库(例如-lm
)时,链接器将查看是否存在依赖于库的任何内容。如果没有,那么库将被丢弃。
要解决此问题,建议您始终将库放在所有源/目标文件之后。
注意:此依赖关系顺序也在库之间使用,因此如果您有一个依赖于库B的库A,那么您需要在命令行上放置A之前的A.如果你有两个彼此依赖的库,这当然会很难。