在makefile中应该在哪里添加-lm标志?

3
我正在尝试编译一个名为COSI的仿真程序: http://www.broadinstitute.org/~sfs/cosi/cosi_1.2.1.tar 使用tar xfp cosi_package.tar解压后,在新创建的目录cosi_1.2中按照README中的说明运行make。不幸的是,我遇到了很多错误,例如:
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,但没什么帮助。有什么建议吗?

2个回答

8

-lm 是一个链接器标志。它应该出现在链接器命令的末尾:

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

显然,一些编译器允许-l出现在任何位置。我仍然没有找到哪些编译器可以这样做,但我的GCC希望它们出现在末尾,并且以依赖性的相反顺序:如果random.a需要libm,那么应该在random.a之后链接libm
我还从链接器命令中删除了$(CFLAGS),因为在链接时应该传递链接器选项而不是编译器选项。

1
非常感谢,它有效了!也感谢您的解释,我曾想知道为什么在一个非常出名/经常使用的程序中出现错误...等待期过后,我接受了您的答案。 - Andarin

1
链接器按照命令行上的顺序搜索依赖项。因此,当您要求链接器与库链接(例如使用-lm),链接器会查看是否有任何依赖于该库的内容。如果没有,则该库将被丢弃。
为解决此问题,建议始终在所有源/对象文件之后放置库。
注意:此依赖关系顺序也用于库之间,因此如果您有一个依赖于库B的库A,则需要在命令行上将A放在B之前。如果有两个相互依赖的库,则这当然会很困难。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接