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.
