8

我一直在尝试构建一些使用数学函数的代码(例如pow)。

math.h-lm包括在内,并且在构建期间使用该标志。

当像这样调用编译时(-lm命令开头的标志),它失败了,说有一个未定义的引用pow

gcc -lm -O3 main.o clustering.o grassberger.o hash.o list.o mat.o metropolis.o motif_ids.o output.o permutation.o prob.o random.o results.o role.o stubs.o switches.o -o mfinder
main.o: In function `get_sn_motif_id':
main.c:(.text+0x28d): undefined reference to `pow'

-lm标志放在命令的末尾时,它就起作用了!

gcc -O3 main.o clustering.o grassberger.o hash.o list.o mat.o metropolis.o motif_ids.o output.o permutation.o prob.o random.o results.o role.o stubs.o switches.o -o mfinder -lm

这是正常的吗?

4

2 回答 2

18

是的,这很正常。对于许多链接器,指定目标文件和库的顺序很重要。

引用“GCC 简介 - 用于 GNU 编译器 gcc 和 g++”

链接器的传统行为是在命令行指定的库中从左到右搜索外部函数。这意味着包含函数定义的库应该出现在使用它的任何源文件或目标文件之后。这包括使用快捷-l选项指定的库,如以下命令所示:

$ gcc -Wall calc.c -lm -o calc (correct order)

这种行为很常见,但绝不是普遍的。如有疑问,最好查阅链接器手册。例如,在我的 Ubuntu 系统上man ld声明:

   -l namespec
   --library=namespec

       ...

       The linker will search an archive only once, at the location where
       it is specified on the command line.  If the archive defines a
       symbol which was undefined in some object which appeared before the
       archive on the command line, the linker will include the
       appropriate file(s) from the archive.  However, an undefined symbol
       in an object appearing later on the command line will not cause the
       linker to search the archive again.

换句话说,这个链接器确实按照gcc书中描述的方式运行。

于 2012-01-25T08:59:53.903 回答
4

An Introduction to GCC - 用于 GNU 编译器 gcc 和 g++ 中所述

链接器的传统行为是在命令行指定的库中从左到右搜索外部函数。这意味着包含函数定义的库应该出现在使用它的任何源文件或目标文件之后。

我认为你看到了同样的行为。

请注意,它还进一步指出,

大多数现代链接器搜索所有库,无论顺序如何,但最好遵循从左到右排序库的约定。

于 2012-01-25T09:01:21.563 回答