gcc链接过程中定义了三个集合:可重定位目标文件集合E、未解析符号集合U和已定义符号集合D,链接基本流程如下:
1) 按命令行指定顺序依次处理每个目标文件和库文件;
2) 如果为目标文件,将其加入集合E,将其所有符号加入D,将得到解析的符号从U中移除;
3) 如果为静态库文件,若库中的某个目标文件能够解析U中的一个或多个符号,则按1)中方式进行链接处理;
4) 如果为动态库文件,移除U中得到解析的符号,在D中加入库中符号;
5) 若集合U最终为空,链接成功,对E中文件进行合并和重定位处理,生成可执行文件,否则报告链接出错(输出“undefined reference to......”)。
根据gcc链接器工作原理,被依赖目标文件(或库)必须放在引用该文件的目标文件(或库)的后面(如果放在前面,链接器在处理被依赖文件时,不知道后面会有对该文件的引用,被引用的符号就不会提取出来),gcc手册中对这种依赖的描述如下:
-l library
native with the library as a separate argument is only for
POSIX
compliance and is not recommended.)
It makes a difference where in the command you write this option;
the linker searches and processes libraries and object files in the
order they are specified. Thus, foo.o -lz bar.o searches library z
after file foo.o but before bar.o. If bar.o refers to functions in
z, those functions may not be loaded.
如果确实无法理清依赖顺序,可以采用如下两种方法:
a) 重复指定,如gcc -o test.c -la -lb -la;
b) 使用Xlinker选项,如gcc -o test.c -Xlinker "-(" -la -lb "-)",gcc手册中对Xlinker的描述如下:
-Xlinker option
Pass option as an option to the linker. You can use this to
supply system-specific linker options that GCC does not
recognize. If you want to pass an option that takes a separate argument, you
must use -Xlinker twice, once for the option and once for the
argument. For example, to pass -assert definitions, you must
write -Xlinker -assert -Xlinker definitions. It does not work to
write -Xlinker "-assert definitions", because this passes the
entire string as a single argument, which is not what the linker
expects. When using the GNU linker, it is usually more convenient to pass
arguments to linker options using the option=value syntax than as
separate arguments. For example, you can specify -Xlinker
-Map=output.map rather than -Xlinker -Map -Xlinker output.map.
Other linkers may not support this syntax for command-line
options.