gcc鏈接靜態庫時對待.a文件和.o文件的不同

  很多人都知道,gcc在鏈接靜態庫時是從前往後找符號。因此如果一份文件foo引用了靜態庫bar.a,那麼在鏈接命令中,bar.a必須放在foo的後面,也就是像gcc ... foo ... bar.a這樣;否則鏈接時會報找不到定義的錯誤(即undefined reference to ...)。

 

  .a文件其實沒什麼特別的地方,它不過是將多個.o文件打包成一份文件。如果我們在鏈接命令中,直接用.o文件替換.a文件,那也需要遵循gcc的這種鏈接順序嗎?可以用gcc .. bar.o ... foo這樣的鏈接命令嗎?可以做個簡單的試驗。

 

  假設我們有兩份源代碼文件。一份是foo.c,定義了一個foo函數。

void foo()
{
}

  另一份是main.c,裏面引用了foo函數:

void foo();

int main()
{
    foo();
}

  我們將foo.c編譯成foo.o,然後打包成foo.a:

$ gcc -c foo.c

$ ar rcs foo.a foo.o

  如果我們讓main.c鏈接foo.a,並且將foo.a放在main.c的前面,那就會如期望的那樣出現鏈接錯誤:

$ gcc -o test foo.a main.c
C:\Users\ADMINI~1\AppData\Local\Temp\ccan3qBI.o:main.c:(.text+0xc): undefined reference to `foo'
collect2.exe: error: ld returned 1 exit status

  但如果將foo.a換成foo.o,鏈接就不會報錯了:

$ gcc -o test foo.o main.c

  所以結論是:.o文件在鏈接中並不遵循.a文件那樣的鏈接順序,看來鏈接器找符號時,一定會搜索命令中的.o文件。

 

  StackOverflow裏的這篇帖子也提到了類似的事:http://stackoverflow.com/questions/11231101/gcc-linking-object-file-and-library-what-is-the-difference

 

  試驗用的gcc版本:

$ gcc -v
Using built-in specs.
COLLECT_GCC=e:\Zhixiang\MinGW\bin\gcc.exe
COLLECT_LTO_WRAPPER=e:/zhixiang/mingw/bin/../libexec/gcc/mingw32/4.8.1/lto-wrapper.exe
Target: mingw32
Configured with: ../gcc-4.8.1/configure --prefix=/mingw --host=mingw32 --build=mingw32 --without-pic --enable-shared --enable-static --with-gnu-ld --enable-lto --enable-libssp --disable-multilib --enable-languages=c,c++,fortran,objc,obj-c++,ada --disable-sjlj-exceptions --with-dwarf2 --disable-win32-registry --enable-libstdcxx-debug --enable-version-specific-runtime-libs --with-gmp=/usr/src/pkg/gmp-5.1.2-1-mingw32-src/bld --with-mpc=/usr/src/pkg/mpc-1.0.1-1-mingw32-src/bld --with-mpfr= --with-system-zlib --with-gnu-as --enable-decimal-float=yes --enable-libgomp --enable-threads --with-libiconv-prefix=/mingw32 --with-libintl-prefix=/mingw --disable-bootstrap LDFLAGS=-s CFLAGS=-D_USE_32BIT_TIME_T
Thread model: win32
gcc version 4.8.1 (GCC)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章