我一直在尝试构建一些使用数学函数的代码(例如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
这是正常的吗?
答案 0 :(得分:18)
是的,这很正常。对于许多链接器,指定目标文件和库的顺序很重要。
引用"An Introduction to GCC - for the GNU compilers gcc and 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
书中描述的方式相同。
答案 1 :(得分:4)
如 An Introduction to GCC - for the GNU compilers gcc and g++
中所述链接器的传统行为是在命令行中指定的库中从左到右搜索外部函数。这意味着包含函数定义的库应出现在使用它的任何源文件或目标文件之后。
我认为你看到了同样的行为。
请注意,它还进一步声明,
大多数现代链接器搜索所有库,无论顺序如何,但最好遵循从左到右排序库的约定。